Skip to content

♻️ PR#235レビュー対応: Discordロール種別ごとの分岐と退会者ロールを実装#248

Open
Tivo0921 wants to merge 11 commits into
mainfrom
feature/discord-role-slim
Open

♻️ PR#235レビュー対応: Discordロール種別ごとの分岐と退会者ロールを実装#248
Tivo0921 wants to merge 11 commits into
mainfrom
feature/discord-role-slim

Conversation

@Tivo0921
Copy link
Copy Markdown
Contributor

@Tivo0921 Tivo0921 commented May 11, 2026

対応した指摘 (PR #235 コメント)

Shion1305 さんのレビューコメントに基づき、ロール付与ロジックを種別ごとに分岐させ、退会者ロールのフローを追加しました。

変更内容

ロール付与の分岐(lib/discord-role.ts

メンバー種別 付与ロール
学部生・院生 MEMBER_ROLE_ID + 学部X年 / 修士X年 / 博士X年 + 学部/学府ロール
卒業生 卒業生 のみ
その他 その他 のみ
退会者 退会者 のみ
  • MemberRoleParamsmemberType / optedOut を追加
  • isProfileValueName退会者 を追加(管理対象ロールとして削除候補に含める)
  • YEAR_ROLE_PATTERN から その他X年 パターンを除外(その他 は年号なしのロール)

退会者ロールのフロー

  • 退会確定時 (app/optout/confirm/.../page.tsx): markMemberOptedOut 後に 退会者 ロールを付与
  • 再入会時 (app/api/optout/rejoin/route.ts): markMemberRejoined 後に 退会者 ロールを削除し、プロフィールに応じた通常ロールを付与

その他修正

  • app/api/onboarding/route.ts: memberTypesyncMemberDiscordRoles に渡すよう修正
  • lib/admin/actions.ts: バルク同期の Firestore select に memberType を追加、種別ごとに正しいロール名を ensureRolesInMap に渡すよう修正

Test plan

手動テスト済み(実機の Discord サーバーで確認)

  • 学部生でオンボーディング完了 → 学部X年 + 学部ロールのみ付与される
  • 卒業生でオンボーディング完了 → 卒業生 ロールのみ付与される(年度・学部ロールなし)
  • その他でオンボーディング完了 → その他 ロールのみ付与される
  • 退会フローを踏む → 退会者 ロールが付き、他の管理対象ロールが削除される
  • 退会者が再入会 → 退会者 ロールが削除され、正しいロールが付与される
  • 管理者画面「全員同期」 → 各種別で正しいロールに同期される

🤖 Generated with Claude Code

Shun Ikeda and others added 11 commits April 28, 2026 20:44
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 付与対象を学年・学部ロールのみに変更(興味分野・メンバー種別は付与しない)
- 既存の興味分野・種別ロールは管理対象として削除する
- 同期結果の付与/削除カラムをロールIDではなく名前で表示
- ensureRolesInMap後に逆引きマップを構築し新規作成ロールも名前解決できるよう修正

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…o feature/discord-role-slim

# Conflicts:
#	lib/admin/actions.ts
- 卒業生: 卒業生ロールのみ付与(年度・学部ロールなし)
- その他: その他ロールのみ付与
- 退会者: opt-out確定時に退会者ロールを付与
- 再入会: 退会者ロールを削除し通常ロールを付与
- isProfileValueName に退会者を追加(管理対象に含める)
- MemberRoleParams に memberType / optedOut を追加
- バルク同期でも種別ごとに正しいロールを ensureRolesInMap に渡すよう修正

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Tivo0921 Tivo0921 requested a review from Shion1305 May 11, 2026 12:54
@github-actions
Copy link
Copy Markdown

Deployed on https://dev-pr-248-birbz3fm6q-an.a.run.app

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Discord ロール同期を「メンバー種別(学部生/院生/卒業生/その他)」「退会者(optedOut)」で分岐させ、退会・再入会・オンボーディング・管理者一括同期の各フローから同期できるようにするPRです。

Changes:

  • lib/discord-role.ts を追加し、Discord ロールの作成/付与/削除と同期ロジック(種別・退会者分岐)を実装
  • 退会確定/再入会/オンボーディング完了時にロール同期を呼ぶように API/ページ側を更新
  • 管理者ページに「Discordロール一括同期」パネルを追加し、Firestore→Discord の一括同期を実装

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
lib/discord-role.ts ロール名マップ取得・不足ロール作成・メンバーへのロール差分同期(退会者/卒業生/その他/通常)を追加
lib/admin/actions.ts 管理者用の一括ロール同期サーバーアクションを追加(Firestoreから対象取得→同期)
components/admin/role-sync-panel.tsx 管理画面から一括同期を実行し、付与/削除/エラーを表示するUIを追加
app/internal/(protected)/admin/page.tsx 管理者ページにロール同期パネルを追加
app/optout/confirm/[discordId]/[exp]/[messageId]/[sig]/page.tsx 退会確定時に退会者ロールへ同期する呼び出しを追加
app/api/optout/rejoin/route.ts 再入会時に退会者ロール削除+通常ロール付与の同期呼び出しを追加
app/api/onboarding/route.ts オンボーディング完了時にロール同期呼び出しを追加
app/layout.tsx テーマ初期化スクリプトを next/script から素の <script> に変更
.env.example MEMBER_ROLE_ID の説明を追加
.gitignore env.share を追加

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +173 to +176
// 退会者ロール付与 (fire-and-forget)
syncMemberDiscordRoles(discordId, { optedOut: true }).catch((e) => {
console.error("Failed to sync Discord roles (optout):", e);
});
Comment on lines +106 to +112
syncMemberDiscordRoles(session.user.id, {
year: updatedMember.yearByFiscal?.[String(new Date().getFullYear())],
faculty: updatedMember.enrollments?.find((e) => e.isCurrent)?.faculty,
memberType: updatedMember.memberType,
}).catch((e) => {
console.error("Failed to sync Discord roles (onboarding):", e);
});
Comment on lines +42 to +51
// 退会者ロール削除 + 通常ロール付与 (fire-and-forget)
if (member) {
syncMemberDiscordRoles(discordId, {
year: member.yearByFiscal?.[String(new Date().getFullYear())],
faculty: member.enrollments?.find((e) => e.isCurrent)?.faculty,
memberType: member.memberType,
}).catch((e) => {
console.error("Failed to sync Discord roles (rejoin):", e);
});
}
Comment thread lib/admin/actions.ts
Comment on lines +239 to +246
const targets = snap.docs.filter((doc) => doc.data().optedOut !== true);
result.total = targets.length;

const roleNameMap = await getGuildRoleNameMap();
console.log(
`[role-sync] ギルドロール ${roleNameMap.size}件を取得: [${[...roleNameMap.keys()].join(", ")}]`,
);
console.log(`[role-sync] 対象メンバー: ${result.total}件`);
Comment on lines +125 to +127
メンバー種別・学年・学部・興味分野は Discord
サーバーのロール名と自動マッチングし、不要になったロールは削除します。
年度メンバーロール(全員共通)は環境変数
<section className="mt-10">
<h2 className="text-lg font-semibold mb-4">Discordロール付与</h2>
<p className="text-sm text-muted-foreground mb-4">
登録済みメンバー全員に年度メンバーロールおよびメンバー種別ロールを一括付与します。
Comment thread .env.example
Comment on lines +31 to +33
# メンバー種別・学年・学部・興味分野のロールは Discord ギルドのロール名で自動マッチング。
# Discord サーバーのロール名をプロフィール値(例: "理工学部", "Python", "学部3年", "学部生")と
# 一致させれば env var の設定なしに自動で付与される。
Comment thread lib/discord-role.ts
Comment on lines +131 to +135
// ロール名 → ID のマップを返す。バッチ処理では一度だけ呼び出して使い回す。
export async function getGuildRoleNameMap(): Promise<Map<string, string>> {
const roles = await fetchGuildRoles();
return new Map(roles.map((r) => [r.name, r.id]));
}
Comment thread lib/discord-role.ts
Comment on lines +156 to +164
// params から付与すべきロール ID 一覧を返す。
// 退会者: 退会者ロールのみ
// 卒業生: 卒業生ロールのみ
// その他: その他ロールのみ
// 学部生・院生: MEMBER_ROLE_ID + 学年 + 学部/学府
function getTargetRoleIds(
params: MemberRoleParams,
roleNameMap: Map<string, string>,
): { roleIds: string[]; matched: string[]; notFound: string[] } {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants