diff --git a/.github/workflows/send_message.yml b/.github/workflows/send_message.yml index 18b4f1e..e9e96a3 100644 --- a/.github/workflows/send_message.yml +++ b/.github/workflows/send_message.yml @@ -27,5 +27,4 @@ jobs: run : npx tsc && node app.js env : NOTION_TOKEN : ${{secrets.NOTION_TOKEN}} - DATABASE_ID : ${{secrets.DATABASE_ID}} - WEBHOOK_URL : ${{secrets.WEBHOOK_URL}} \ No newline at end of file + LINK_DATABASE_URL : ${{secrets.LINK_DATABASE_URL}} \ No newline at end of file diff --git a/README.md b/README.md index c6e3fac..ddb0738 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,16 @@ 1. [노션 API 통합을 생성하여 API 토큰 얻기](https://www.notion.so/ko/help/create-integrations-with-the-notion-api) 2. [링크](https://instinctive-iron-d62.notion.site/notion-discord-post-46f37636879b45379693dc6757334f0d)로 이동해서 노션 페이지를 워크스페이스로 복제하기 3. [복제한 노션 페이지와 API 통합을 연결하기](https://www.notion.so/ko/help/add-and-manage-connections-with-the-api#%ED%8E%98%EC%9D%B4%EC%A7%80%EC%97%90-%EC%97%B0%EA%B2%B0-%EC%B6%94%EA%B0%80) -4. 공지 발송 노션 데이터베이스 ID 얻기(보기 링크를 복사한 다음 아래 예시처럼 ID 얻기) - ![데이터베이스 ID](https://files.readme.io/64967fd-small-62e5027-notion_database_id.png) +4. 공지 발송 노션 데이터베이스 링크 얻기(보기 링크 복사) 5. [메시지를 보낼 디스코드 채널에 웹훅을 생성하고 웹훅 URL 얻기](https://support.discord.com/hc/ko/articles/228383668-%EC%9B%B9%ED%9B%85%EC%9D%84-%EC%86%8C%EA%B0%9C%ED%95%A9%EB%8B%88%EB%8B%A4) -6. 레포지토리를 포크하고 **Settings > Security > Secrets and variable> Actions**에 노션 API 토큰, 노션 데이터베이스 ID, 웹훅 URL을 저장하기(노션 API 토큰 : `NOTION_TOKEN`, 데이터베이스 ID : `DATABASE_ID`, 디스코드 웹훅 URL : `WEBHOOK_URL`의 이름으로) -7. Actions 탭에 가서 Github Actions 활성화하고, 노션 페이지로 이동해서 메시지 예약하기 +6. 관리 데이터베이스에 4.에서 얻은 링크, 5.에서 얻은 웹훅 URL을 붙혀넣기 +7. 관리 데이터베이스 보기 링크를 복사하기 +8. 레포지토리를 포크하고 **Settings > Security > Secrets and variable> Actions**에 노션 API 토큰, 노션 데이터베이스 ID, 웹훅 URL을 저장하기(노션 API 토큰 : `NOTION_TOKEN`, 관리(링크)데이터베이스 링크 주소 : `LINK_DATABASE_URL`의 이름으로) +9. Actions 탭에 가서 Github Actions 활성화하고, 노션 페이지로 이동해서 메시지 예약하기 + +자세한 사용법은 [여기](https://instinctive-iron-d62.notion.site/notion-discord-post-46f37636879b45379693dc6757334f0d)에서 확인하실 수 있습니다! # 단독실행 -0. 환경변수 설정(노션 API 토큰 : `NOTION_TOKEN`, 데이터베이스 ID : `DATABASE_ID`, 디스코드 웹훅 URL : `WEBHOOK_URL`의 이름으로) +0. 환경변수 설정(노션 API 토큰 : `NOTION_TOKEN`, 관리(링크)데이터베이스 링크 주소 : `LINK_DATABASE_URL`) 1. 의존성 설치 ```shell npm install diff --git a/app.ts b/app.ts index 7b97b80..e588670 100644 --- a/app.ts +++ b/app.ts @@ -1,6 +1,20 @@ import fetch from 'node-fetch'; import {Client,isFullPageOrDatabase,isFullBlock} from '@notionhq/client'; +/** + * 디스코드 메시지를 나타내는 인터페이스 + */ +interface DiscordMessage { + content : string +} +/** + * 메시지 예약 데이터베이스 ID와 디스코드 웹훅 링크가 있는 객체 인터페이스 + */ +interface LinkObject { + databaseId:string, + webhookUrl:string +} + if (process.env.NOTION_TOKEN === undefined) { throw new Error("노션 API 토큰을 환경변수에서 읽을 수 없습니다."); } @@ -8,13 +22,9 @@ const notion = new Client({ auth: process.env.NOTION_TOKEN, }) -interface DiscordMessage { - content : string -} - /** * 웹훅으로 디스코드 채널에 메시지를 보내는 함수 - * @param webhookUrl - 디스코드 웹훕 주소 URL + * @param webhookUrl - 디스코드 웹훅 주소 URL * @param message - 디스코드 메시지 객체 */ const sendMessage = async (webhookUrl : string, message : DiscordMessage) => { @@ -27,7 +37,54 @@ const sendMessage = async (webhookUrl : string, message : DiscordMessage) => { } ); } +/** + * 노션 데이터베이스 URL에서 데이터베이스 ID만 추출해서 반환하는 함수 + * @param databaseURL 노션 데이터베이스 (보기)링크(URL) + * @returns databaseId 노션 데이터베이스 ID + */ +const parseDatabaseId = (databaseURL : string) => { + const databaseIdObject = /[a-z0-9]+\?v/.exec(databaseURL); + if (databaseIdObject === null) { + throw new Error("노션 데이터 베이스 ID를 찾을 수 없습니다."); + } + const databaseId = databaseIdObject[0].split("\?v")[0]; + return databaseId; +} +/** + * 노션에 있는 링크 관리 데이터베이스에서 노션 DB-디스코드 웹훅 연결 정보 객체를 가져오는 함수 + * @param linkDatabaseId - 노션 데이터베이스 ID + */ +const getLinkObjectArray = async (linkDatabaseId : string) => { + const response = await notion.databases.query({ + database_id: linkDatabaseId + }); + let linkObjectArray:LinkObject[] = []; + for (const linkPage of response.results) { + if (!isFullPageOrDatabase(linkPage)) { + continue; + } + if (!("rich_text" in linkPage.properties["디스코드 웹훅 URL"])) { + continue; + } + if (!("rich_text" in linkPage.properties["노션 데이터베이스 링크"])) { + continue; + } + const databaseURLObject = linkPage.properties["노션 데이터베이스 링크"].rich_text.at(0); + if (databaseURLObject === undefined) { + continue; + } + const webhookURLObject = linkPage.properties["디스코드 웹훅 URL"].rich_text.at(0); + if (webhookURLObject === undefined) { + continue; + } + const databaseURL = databaseURLObject.plain_text; + const databaseId = parseDatabaseId(databaseURL); + const webhookURL = webhookURLObject.plain_text; + linkObjectArray.push({webhookUrl:webhookURL,databaseId:databaseId}); + } + return linkObjectArray; +} /** * 노션에 있는 데이터베이스에서 메시지가 담겨있는 페이지들을 가져와서 반환하는 함수 * @param databaseId - 노션 데이터베이스 ID @@ -45,6 +102,21 @@ const getReservedMessages = async (databaseId : string) => { return response.results; } +/** + * 모든 노션 데이터베이스의 예약된 메시지를 전송하는 함수 + * @param linkDatabaseId 링크 노션 데이터베이스 ID + */ +const sendAllReservedMessages = async (linkDatabaseId :string) => { + const linkObjectArray:LinkObject[] = await getLinkObjectArray(linkDatabaseId); + for (const linkObject of linkObjectArray) { + await sendReservedMessages(linkObject.databaseId,linkObject.webhookUrl); + } +} +/** + * 예약 메시지 데이터베이스에 있는 예약된 메시지를 디스코드 웹훅으로 전송하는 함수 + * @param databaseId 예약 메시지 데이터베이스 ID + * @param webhookUrl 디스코드 웹훅 URL 주소 + */ const sendReservedMessages = async (databaseId:string, webhookUrl:string) => { for (let messagePage of await getReservedMessages(databaseId)) { @@ -101,15 +173,11 @@ const sendReservedMessages = async (databaseId:string, webhookUrl:string) => { }; try { - if (process.env.DATABASE_ID === undefined) { - throw new Error("노션 데이터베이스 ID를 환경변수에서 읽을 수 없습니다."); - } - if (process.env.WEBHOOK_URL === undefined) { - throw new Error("디스코드 웹훅 URL 주소를 환경변수에서 읽을 수 없습니다."); + if (process.env.LINK_DATABASE_URL === undefined) { + throw new Error("노션 - 디스코드 링크 데이터베이스 URL을 환경변수에서 읽을 수 없습니다."); } - const databaseId : string = process.env.DATABASE_ID; - const webhookUrl : string = process.env.WEBHOOK_URL; - sendReservedMessages(databaseId,webhookUrl); + const linkDatabaseUrl : string = process.env.LINK_DATABASE_URL; + sendAllReservedMessages(parseDatabaseId(linkDatabaseUrl)); } catch (error) { console.error(error); } \ No newline at end of file