From 8c705dd3179482ebbc3a1dfc4f0575850fae48a8 Mon Sep 17 00:00:00 2001 From: jihongeek Date: Tue, 3 Sep 2024 10:40:19 +0900 Subject: [PATCH 1/7] =?UTF-8?q?Feat:=20=EB=A7=81=ED=81=AC=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=EB=B2=A0=EC=9D=B4=EC=8A=A4=EC=97=90=20?= =?UTF-8?q?=EC=9E=88=EB=8A=94=20=EC=A0=95=EB=B3=B4=EB=A1=9C=20=EC=97=AC?= =?UTF-8?q?=EB=9F=AC=EA=B0=9C=EC=9D=98=20=EC=B1=84=EB=84=90=EC=97=90=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=EB=A5=BC=20=EB=B3=B4=EB=82=B4?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.ts | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/app.ts b/app.ts index 7b97b80..682c657 100644 --- a/app.ts +++ b/app.ts @@ -45,6 +45,17 @@ const getReservedMessages = async (databaseId : string) => { return response.results; } +interface LinkObject { + databaseId:string, + webhookUrl:string +} +const sendAllResservedMessages = async (linkDatabaseId :string) => { + const linkObjectArray:LinkObject[] = []; + for (const linkObject of linkObjectArray) { + await sendReservedMessages(linkObject.databaseId,linkObject.webhookUrl); + } +} + const sendReservedMessages = async (databaseId:string, webhookUrl:string) => { for (let messagePage of await getReservedMessages(databaseId)) { @@ -101,15 +112,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_ID === undefined) { + throw new Error("노션 - 디스코드 링크 데이터베이스 ID를 환경변수에서 읽을 수 없습니다."); } - const databaseId : string = process.env.DATABASE_ID; - const webhookUrl : string = process.env.WEBHOOK_URL; - sendReservedMessages(databaseId,webhookUrl); + const linkDatabaseId : string = process.env.LINK_DATABASE_ID; + sendAllResservedMessages(linkDatabaseId); } catch (error) { console.error(error); } \ No newline at end of file From 7f7e252a1e9d18fc43e0d9b7d7075cc8a73ffe14 Mon Sep 17 00:00:00 2001 From: Jihong Kim <34394165+jihongeek@users.noreply.github.com> Date: Tue, 3 Sep 2024 21:49:58 +0900 Subject: [PATCH 2/7] =?UTF-8?q?Feat:=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=B2=A0=EC=9D=B4=EC=8A=A4=20-=20=EC=9B=B9=ED=9B=85=20?= =?UTF-8?q?=EB=B3=84=20=EB=A9=94=EC=84=B8=EC=A7=80=20=EC=A0=84=EC=86=A1=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.ts | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/app.ts b/app.ts index 682c657..f90a236 100644 --- a/app.ts +++ b/app.ts @@ -28,6 +28,53 @@ const sendMessage = async (webhookUrl : string, message : DiscordMessage) => { ); } +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; +} + +interface LinkObject { + databaseId:string, + webhookUrl:string +} +/** + * 노션에 있는 링크 관리 데이터베이스에서 노션 DB-디스코드 웹훅 연결 정보 페이지를 가져오는 함수 + * @param linkDatabaseId - 노션 데이터베이스 ID + */ +const getLinks = 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 @@ -50,7 +97,7 @@ interface LinkObject { webhookUrl:string } const sendAllResservedMessages = async (linkDatabaseId :string) => { - const linkObjectArray:LinkObject[] = []; + const linkObjectArray:LinkObject[] = await getLinks(linkDatabaseId); for (const linkObject of linkObjectArray) { await sendReservedMessages(linkObject.databaseId,linkObject.webhookUrl); } From dad86748abe72e60b52423cc3427bdcd5dab3991 Mon Sep 17 00:00:00 2001 From: jihongeek Date: Wed, 4 Sep 2024 12:29:23 +0900 Subject: [PATCH 3/7] =?UTF-8?q?Chore:=20=EC=A3=BC=EC=84=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=ED=95=A8=EC=88=98=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.ts | 54 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/app.ts b/app.ts index f90a236..3a2ea5c 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,11 @@ 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) { @@ -37,15 +51,11 @@ const parseDatabaseId = (databaseURL : string) => { return databaseId; } -interface LinkObject { - databaseId:string, - webhookUrl:string -} /** - * 노션에 있는 링크 관리 데이터베이스에서 노션 DB-디스코드 웹훅 연결 정보 페이지를 가져오는 함수 + * 노션에 있는 링크 관리 데이터베이스에서 노션 DB-디스코드 웹훅 연결 정보 객체를 가져오는 함수 * @param linkDatabaseId - 노션 데이터베이스 ID */ -const getLinks = async (linkDatabaseId : string) => { +const getLinkObjectArray = async (linkDatabaseId : string) => { const response = await notion.databases.query({ database_id: linkDatabaseId }); @@ -92,17 +102,21 @@ const getReservedMessages = async (databaseId : string) => { return response.results; } -interface LinkObject { - databaseId:string, - webhookUrl:string -} -const sendAllResservedMessages = async (linkDatabaseId :string) => { - const linkObjectArray:LinkObject[] = await getLinks(linkDatabaseId); +/** + * 모든 노션 데이터베이스의 예약된 메시지를 전송하는 함수 + * @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)) { @@ -163,7 +177,7 @@ try { throw new Error("노션 - 디스코드 링크 데이터베이스 ID를 환경변수에서 읽을 수 없습니다."); } const linkDatabaseId : string = process.env.LINK_DATABASE_ID; - sendAllResservedMessages(linkDatabaseId); + sendAllReservedMessages(linkDatabaseId); } catch (error) { console.error(error); } \ No newline at end of file From 7fad88bbe71a8ba03e748028bd4e220309b19c0f Mon Sep 17 00:00:00 2001 From: jihongeek Date: Wed, 4 Sep 2024 16:07:30 +0900 Subject: [PATCH 4/7] =?UTF-8?q?Feat:=20=EB=A7=81=ED=81=AC=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=EB=B2=A0=EC=9D=B4=EC=8A=A4=20ID=20=EB=8C=80?= =?UTF-8?q?=EC=8B=A0,=20=EB=A7=81=ED=81=AC=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=B2=A0=EC=9D=B4=EC=8A=A4=EC=9D=98=20=EB=A7=81=ED=81=AC=20?= =?UTF-8?q?=EC=A6=89,=20URL=EB=A1=9C=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20?= =?UTF-8?q?=EA=B0=80=EC=A0=B8=EC=98=AC=20=EC=88=98=20=EC=9E=88=EA=B2=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app.ts b/app.ts index 3a2ea5c..ea12df0 100644 --- a/app.ts +++ b/app.ts @@ -173,11 +173,11 @@ const sendReservedMessages = async (databaseId:string, webhookUrl:string) => { }; try { - if (process.env.LINK_DATABASE_ID === undefined) { + if (process.env.LINK_DATABASE_URL === undefined) { throw new Error("노션 - 디스코드 링크 데이터베이스 ID를 환경변수에서 읽을 수 없습니다."); } - const linkDatabaseId : string = process.env.LINK_DATABASE_ID; - sendAllReservedMessages(linkDatabaseId); + const linkDatabaseUrl : string = process.env.LINK_DATABASE_URL; + sendAllReservedMessages(parseDatabaseId(linkDatabaseUrl)); } catch (error) { console.error(error); } \ No newline at end of file From 813be04f36ca73af05b84c19bee201b8c4e166f1 Mon Sep 17 00:00:00 2001 From: jihongeek Date: Wed, 4 Sep 2024 16:13:37 +0900 Subject: [PATCH 5/7] =?UTF-8?q?Chore:=20=EB=A6=AC=EB=93=9C=EB=AF=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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 From 7612ca89ac89f8708aaa7d3f3aa31ecceca6449d Mon Sep 17 00:00:00 2001 From: Jihong Kim <34394165+jihongeek@users.noreply.github.com> Date: Fri, 13 Sep 2024 18:56:09 +0900 Subject: [PATCH 6/7] =?UTF-8?q?Chore:=20Secrets=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20Workflow=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/send_message.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/send_message.yml b/.github/workflows/send_message.yml index f066ca9..8cc2ac3 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 From 545be8164cf8ecabd3dfe88f5ef921c6c22bb96a Mon Sep 17 00:00:00 2001 From: Jihong Kim <34394165+jihongeek@users.noreply.github.com> Date: Fri, 13 Sep 2024 18:57:07 +0900 Subject: [PATCH 7/7] =?UTF-8?q?Fix:=20=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=84=A4=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.ts b/app.ts index ea12df0..e588670 100644 --- a/app.ts +++ b/app.ts @@ -174,7 +174,7 @@ const sendReservedMessages = async (databaseId:string, webhookUrl:string) => { try { if (process.env.LINK_DATABASE_URL === undefined) { - throw new Error("노션 - 디스코드 링크 데이터베이스 ID를 환경변수에서 읽을 수 없습니다."); + throw new Error("노션 - 디스코드 링크 데이터베이스 URL을 환경변수에서 읽을 수 없습니다."); } const linkDatabaseUrl : string = process.env.LINK_DATABASE_URL; sendAllReservedMessages(parseDatabaseId(linkDatabaseUrl));