Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .dev.vars.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
DISCORD_BOT_TOKEN=
DISCORD_TOKEN=
DISCORD_GUILD_ID=
DISCORD_PUBLIC_KEY=
DISCORD_ROLE_ID=
DISCORD_APPLICATION_ID=
GITHUB_APP_ID=
GITHUB_APP_INSTALLATION_ID=
GITHUB_APP_PRIVATE_KEY=
GH_PAT=
STUDY_JOIN_CHANNEL_ID=
19 changes: 9 additions & 10 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,20 @@ jobs:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
secrets: |
DISCORD_PUBLIC_KEY
DISCORD_BOT_TOKEN
DISCORD_TOKEN
DISCORD_GUILD_ID
DISCORD_ROLE_ID
DISCORD_APPLICATION_ID
APP_ID
APP_INSTALLATION_ID
APP_PRIVATE_KEY
GITHUB_APP_ID
GITHUB_APP_INSTALLATION_ID
GITHUB_APP_PRIVATE_KEY
Comment on lines +47 to +49

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

무슨 앱인지 너무 햇갈려서 앞에 GITHUB_ 접두어를 붙였습니다.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 처음에 github를 넣었었는데 github를 뺀게 github를 빼면 워크플로우 어딘가에서 보안 관련 이슈로 막았던 걸로 기억합니다!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분 맥락을 기록해놓지 않아서 지금 어디인지 확실하지 않네요! 우선 넣어보고 문제가 보이면 대처해야할 것 같습니다!

GH_PAT
env:
DISCORD_PUBLIC_KEY: ${{ secrets.DISCORD_PUBLIC_KEY }}
DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }}
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
DISCORD_GUILD_ID: ${{ secrets.DISCORD_GUILD_ID }}
DISCORD_ROLE_ID: ${{ secrets.DISCORD_ROLE_ID }}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

얘는 쓰이는데가 없어서 그냥 삭제하였습니다.

DISCORD_APPLICATION_ID: ${{ secrets.DISCORD_APPLICATION_ID }}
APP_ID: ${{ secrets.APP_ID }}
APP_INSTALLATION_ID: ${{ secrets.APP_INSTALLATION_ID }}
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
# GitHub App: 코드/Worker는 GITHUB_APP_* 를 읽지만, 기존 저장소 secret 이름은 APP_* 라 여기서 매핑
GITHUB_APP_ID: ${{ secrets.APP_ID }}
GITHUB_APP_INSTALLATION_ID: ${{ secrets.APP_INSTALLATION_ID }}
GITHUB_APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
GH_PAT: ${{ secrets.GH_PAT }}
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,24 @@ community-manager/

| Key | 설명 |
| ---------------------------- | ------------------------------------------ |
| `DISCORD_PUBLIC_KEY` | Discord App의 Ed25519 공개키 (서명 검증용) |
| `DISCORD_BOT_TOKEN` | Discord Bot Token |
| `DISCORD_PUBLIC_KEY` | Discord App의 Ed25519 공개키, 서명 검증용 (조직 공용 봇) |
| `DISCORD_TOKEN` | Discord Bot Token (조직 공용 봇) |
| `DISCORD_APPLICATION_ID` | Discord Application ID (조직 공용 봇) |
| `DISCORD_GUILD_ID` | 대상 Discord 서버 ID |
| `DISCORD_ROLE_ID` | 부여할 역할 ID |
| `GITHUB_APP_ID` | GitHub App ID |
| `GITHUB_APP_INSTALLATION_ID` | GitHub App의 조직 Installation ID |
| `GITHUB_APP_PRIVATE_KEY` | GitHub App Private Key (PEM 형식) |
| `GH_PAT` | GitHub PAT (후원 조회 GraphQL용) |
| `STUDY_JOIN_CHANNEL_ID` | 스터디 신청 포럼 채널 ID (cron 자동 처리) |

> **봇 자격증명 일원화**: `DISCORD_TOKEN`·`DISCORD_PUBLIC_KEY`·`DISCORD_APPLICATION_ID`는 커뮤니티 공용 봇(`DaleStudy`)의 **조직 레벨** 시크릿이며, CI(GitHub Actions) 배포 시 자동으로 주입됩니다. 저장소별로 개인 봇 자격증명을 따로 관리하지 않습니다.

### wrangler.jsonc vars (공개값, 커밋됨)

| Key | 설명 |
| ------------------ | ----------------- |
| `GITHUB_ORG` | GitHub 조직 이름 |
| `GITHUB_TEAM_SLUG` | 초대할 팀 slug |

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요거는 outdated 된 거 같아서 함께 수정했습니다.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 저거 outdated 된게 맞네요! 감사합니다!

| `GITHUB_ORG` | GitHub 조직 이름 |
| `ROLE_TEAM_CONFIG` | 역할-팀 매핑 (JSON, 슬래시 선택지) |

### 로컬 개발 (.dev.vars)

Expand Down
2 changes: 1 addition & 1 deletion plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ community-manager/
| Key | 설명 |
| -------------------- | ------------------------------------------ |
| `DISCORD_PUBLIC_KEY` | Discord App의 Ed25519 공개키 (서명 검증용) |
| `DISCORD_BOT_TOKEN` | Discord Bot Token |
| `DISCORD_TOKEN` | Discord Bot Token |
| `DISCORD_GUILD_ID` | 대상 Discord 서버 ID |
| `APP_ID` | GitHub App ID |
| `APP_INSTALLATION_ID`| GitHub App의 조직 Installation ID |
Expand Down
2 changes: 1 addition & 1 deletion scripts/register-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ try {
} catch {}

const APPLICATION_ID = process.env.DISCORD_APPLICATION_ID!;
const BOT_TOKEN = process.env.DISCORD_BOT_TOKEN!;
const BOT_TOKEN = process.env.DISCORD_TOKEN!;
const GUILD_ID = process.env.DISCORD_GUILD_ID!;
const ROLE_TEAM_CONFIG = JSON.parse(process.env.ROLE_TEAM_CONFIG!);

Expand Down
4 changes: 2 additions & 2 deletions scripts/register.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { RoleTeamConfig } from "../src/types.js";

const BOT_TOKEN = process.env.DISCORD_BOT_TOKEN;
const BOT_TOKEN = process.env.DISCORD_TOKEN;
const APPLICATION_ID = process.env.DISCORD_APPLICATION_ID;
const GUILD_ID = process.env.DISCORD_GUILD_ID;
const ROLE_TEAM_CONFIG = process.env.ROLE_TEAM_CONFIG;

if (!BOT_TOKEN || !APPLICATION_ID || !GUILD_ID || !ROLE_TEAM_CONFIG) {
console.error("필요한 환경 변수가 설정되지 않았습니다.");
console.error(
"필요: DISCORD_BOT_TOKEN, DISCORD_APPLICATION_ID, DISCORD_GUILD_ID, ROLE_TEAM_CONFIG",
"필요: DISCORD_TOKEN, DISCORD_APPLICATION_ID, DISCORD_GUILD_ID, ROLE_TEAM_CONFIG",
);
process.exit(1);
}
Expand Down
8 changes: 4 additions & 4 deletions src/github.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import type { Env } from "./types.js";

const mockEnv: Env = {
DISCORD_PUBLIC_KEY: "test-public-key",
DISCORD_BOT_TOKEN: "test-bot-token",
DISCORD_TOKEN: "test-bot-token",
DISCORD_GUILD_ID: "test-guild-id",
DISCORD_APPLICATION_ID: "test-app-id",
GITHUB_ORG: "DaleStudy",
APP_ID: "123456",
APP_INSTALLATION_ID: "789",
APP_PRIVATE_KEY: "",
GITHUB_APP_ID: "123456",
GITHUB_APP_INSTALLATION_ID: "789",
GITHUB_APP_PRIVATE_KEY: "",
ROLE_TEAM_CONFIG: "[]",
GH_PAT: "test-pat",
};
Expand Down
4 changes: 2 additions & 2 deletions src/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import type { Env } from "./types.js";
* GitHub App Installation Token 발급
*/
export async function getInstallationToken(env: Env): Promise<string> {
const jwt = await createJWT(env.APP_ID, env.APP_PRIVATE_KEY);
const jwt = await createJWT(env.GITHUB_APP_ID, env.GITHUB_APP_PRIVATE_KEY);

const tokenResponse = await fetch(
`https://api.github.com/app/installations/${env.APP_INSTALLATION_ID}/access_tokens`,
`https://api.github.com/app/installations/${env.GITHUB_APP_INSTALLATION_ID}/access_tokens`,
{
method: "POST",
headers: {
Expand Down
16 changes: 8 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ async function processVerify(

const [state] = await Promise.all([
inviteToTeam(env.GITHUB_ORG, teamConfig.teamSlug, githubUsername, token),
assignRole(env.DISCORD_GUILD_ID, discordUserId, roleConfig.discordRoleId, env.DISCORD_BOT_TOKEN),
assignRole(env.DISCORD_GUILD_ID, discordUserId, roleConfig.discordRoleId, env.DISCORD_TOKEN),
]);

console.log(`[verify] existingMembership=${existingMembership}, invited to team state=${state}, assigned Discord role=${roleConfig.discordRoleId}`);
Expand Down Expand Up @@ -149,7 +149,7 @@ function parseJoinMessage(content: string): ParsedJoinMessage | null {
}

async function handleChannelJoin(env: Env): Promise<void> {
const posts = await getForumPosts(env.DISCORD_GUILD_ID, env.STUDY_JOIN_CHANNEL_ID, env.DISCORD_BOT_TOKEN);
const posts = await getForumPosts(env.DISCORD_GUILD_ID, env.STUDY_JOIN_CHANNEL_ID, env.DISCORD_TOKEN);

const unprocessed = posts.filter((msg) => {
if (msg.author?.bot) return false;
Expand All @@ -171,9 +171,9 @@ async function handleChannelJoin(env: Env): Promise<void> {
threadId,
msg.id,
"⚠️ 메시지 형식이 올바르지 않습니다. 포스트 **제목(title)** 에 아래 형식으로 작성해주세요.\n```\n리트코드 스터디 8기 신청 (github_username, team)\n```",
env.DISCORD_BOT_TOKEN,
env.DISCORD_TOKEN,
);
await addReaction(threadId, msg.id, "❌", env.DISCORD_BOT_TOKEN);
await addReaction(threadId, msg.id, "❌", env.DISCORD_TOKEN);
continue;
}

Expand All @@ -187,18 +187,18 @@ async function handleChannelJoin(env: Env): Promise<void> {
msg.author.id,
env,
);
await replyToMessage(threadId, msg.id, result, env.DISCORD_BOT_TOKEN);
await replyToMessage(threadId, msg.id, result, env.DISCORD_TOKEN);
const reaction = result.startsWith("❌") || result.startsWith("⚠️") ? "❌" : "✅";
await addReaction(threadId, msg.id, reaction, env.DISCORD_BOT_TOKEN);
await addReaction(threadId, msg.id, reaction, env.DISCORD_TOKEN);
} catch (err: any) {
console.error(`[cron] error threadId=${threadId}`, err);
await replyToMessage(
threadId,
msg.id,
`⚠️ 오류가 발생했습니다: ${err?.message ?? "알 수 없는 오류"}`,
env.DISCORD_BOT_TOKEN,
env.DISCORD_TOKEN,
);
await addReaction(threadId, msg.id, "❌", env.DISCORD_BOT_TOKEN);
await addReaction(threadId, msg.id, "❌", env.DISCORD_TOKEN);
}
}
}
8 changes: 4 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ export interface RoleTeamConfig {

export interface Env {
DISCORD_PUBLIC_KEY: string;
DISCORD_BOT_TOKEN: string;
DISCORD_TOKEN: string;
DISCORD_GUILD_ID: string;
GITHUB_ORG: string;
APP_ID: string;
APP_INSTALLATION_ID: string;
APP_PRIVATE_KEY: string;
GITHUB_APP_ID: string;
GITHUB_APP_INSTALLATION_ID: string;
GITHUB_APP_PRIVATE_KEY: string;
ROLE_TEAM_CONFIG: string;
GH_PAT: string;
DISCORD_APPLICATION_ID: string;
Expand Down
2 changes: 1 addition & 1 deletion wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"compatibility_flags": ["nodejs_compat"],
"vars": {
"GITHUB_ORG": "DaleStudy",
"ROLE_TEAM_CONFIG": "[{\"value\":\"leetcode07\",\"label\":\"leetcode07\",\"discordRoleId\":\"1233209102495383572\",\"teamSlug\":\"leetcode07\"},{\"value\":\"leetcode08\",\"label\":\"leetcode08\",\"discordRoleId\":\"1513390176200818769\",\"teamSlug\":\"leetcode08\"}]",
"ROLE_TEAM_CONFIG": "[{\"value\":\"leetcode07\",\"label\":\"leetcode07\",\"discordRoleId\":\"1474508579523268701\",\"teamSlug\":\"leetcode07\"},{\"value\":\"leetcode08\",\"label\":\"leetcode08\",\"discordRoleId\":\"1513390176200818769\",\"teamSlug\":\"leetcode08\"}]",
},
"kv_namespaces": [],
"durable_objects": {
Expand Down
Loading