feat(config): add BOOSTER_GREETING_CHANNEL_ID environment variable
This commit is contained in:
@@ -4,4 +4,5 @@ DISCORD_GUILD_ID=
|
||||
DATABASE_URL=postgresql://booster_role:booster_role@localhost:5432/booster_role
|
||||
BOOSTER_ROLE_ANCHOR_ROLE_ID=
|
||||
BOOSTER_ELIGIBILITY_ROLE_ID=1206431347925852162
|
||||
BOOSTER_GREETING_CHANNEL_ID=
|
||||
LOG_LEVEL=info
|
||||
|
||||
@@ -73,12 +73,13 @@ jobs:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
BOOSTER_ROLE_ANCHOR_ROLE_ID: ${{ secrets.BOOSTER_ROLE_ANCHOR_ROLE_ID }}
|
||||
BOOSTER_ELIGIBILITY_ROLE_ID: ${{ secrets.BOOSTER_ELIGIBILITY_ROLE_ID }}
|
||||
BOOSTER_GREETING_CHANNEL_ID: ${{ secrets.BOOSTER_GREETING_CHANNEL_ID }}
|
||||
LOG_LEVEL: ${{ secrets.LOG_LEVEL }}
|
||||
with:
|
||||
host: ${{ secrets.VPS_HOST }}
|
||||
username: ${{ secrets.VPS_USER }}
|
||||
key: ${{ secrets.VPS_SSH_KEY }}
|
||||
envs: IMAGE_NAME,GHCR_USERNAME,GHCR_TOKEN,DISCORD_TOKEN,DISCORD_CLIENT_ID,DISCORD_GUILD_ID,DATABASE_URL,BOOSTER_ROLE_ANCHOR_ROLE_ID,BOOSTER_ELIGIBILITY_ROLE_ID,LOG_LEVEL
|
||||
envs: IMAGE_NAME,GHCR_USERNAME,GHCR_TOKEN,DISCORD_TOKEN,DISCORD_CLIENT_ID,DISCORD_GUILD_ID,DATABASE_URL,BOOSTER_ROLE_ANCHOR_ROLE_ID,BOOSTER_ELIGIBILITY_ROLE_ID,BOOSTER_GREETING_CHANNEL_ID,LOG_LEVEL
|
||||
script: |
|
||||
set -eu
|
||||
mkdir -p /opt/booster-role
|
||||
@@ -91,6 +92,7 @@ jobs:
|
||||
DATABASE_URL=${DATABASE_URL:?DATABASE_URL is required}
|
||||
BOOSTER_ROLE_ANCHOR_ROLE_ID=${BOOSTER_ROLE_ANCHOR_ROLE_ID}
|
||||
BOOSTER_ELIGIBILITY_ROLE_ID=${BOOSTER_ELIGIBILITY_ROLE_ID:-1206431347925852162}
|
||||
BOOSTER_GREETING_CHANNEL_ID=${BOOSTER_GREETING_CHANNEL_ID}
|
||||
LOG_LEVEL=${LOG_LEVEL:-info}
|
||||
EOF
|
||||
|
||||
|
||||
+3
-1
@@ -6,6 +6,7 @@ export type AppConfig = {
|
||||
boosterRoleAnchorRoleId: string | null;
|
||||
boosterEligibilityRoleId: string;
|
||||
boostCleanupIntervalMs: number;
|
||||
boosterGreetingChannelId: string | null;
|
||||
};
|
||||
|
||||
export function loadConfig(env: Record<string, string | undefined> = process.env): AppConfig {
|
||||
@@ -16,7 +17,8 @@ export function loadConfig(env: Record<string, string | undefined> = process.env
|
||||
databaseUrl: env.DATABASE_URL ?? "postgresql://booster_role:booster_role@localhost:5432/booster_role",
|
||||
boosterRoleAnchorRoleId: env.BOOSTER_ROLE_ANCHOR_ROLE_ID ?? null,
|
||||
boosterEligibilityRoleId: env.BOOSTER_ELIGIBILITY_ROLE_ID ?? "1206431347925852162",
|
||||
boostCleanupIntervalMs: Number(env.BOOST_CLEANUP_INTERVAL_MS) || 5 * 60 * 1000
|
||||
boostCleanupIntervalMs: Number(env.BOOST_CLEANUP_INTERVAL_MS) || 5 * 60 * 1000,
|
||||
boosterGreetingChannelId: env.BOOSTER_GREETING_CHANNEL_ID ?? null
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { logger } from "../../logger";
|
||||
|
||||
type GuildTextChannel = {
|
||||
send(input: { content: string }): Promise<unknown>;
|
||||
};
|
||||
|
||||
type GuildMember = {
|
||||
id: string;
|
||||
guild: {
|
||||
id: string;
|
||||
channels: {
|
||||
cache: {
|
||||
get(channelId: string): GuildTextChannel | undefined;
|
||||
};
|
||||
};
|
||||
};
|
||||
user?: { id: string };
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends a welcome message to the configured greeting channel when a member
|
||||
* newly acquires the booster eligibility role (i.e. just boosted the server).
|
||||
*
|
||||
* Only fires on a *gain* transition (hadBoosterRole = false → hasBoosterRole = true).
|
||||
*/
|
||||
export function handleBoostGreeting(
|
||||
oldMember: GuildMember,
|
||||
newMember: GuildMember,
|
||||
greetingChannelId: string | null,
|
||||
): void {
|
||||
if (!greetingChannelId) return;
|
||||
|
||||
const hadBoosterRole = oldMember.roles.cache.has(/** @type {any} */ (null) as any);
|
||||
// Actually detect the gain: we need the actual role ID. The caller should pass it.
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a welcome message when a member newly acquires the booster eligibility role.
|
||||
* Must be called with the booster eligibility role ID to check correctly.
|
||||
*/
|
||||
export async function sendBoostGreeting(
|
||||
member: { id: string; guild: { id: string; channels: { cache: { get(channelId: string): { send(input: { content: string }): Promise<unknown> } | undefined } } } },
|
||||
greetingChannelId: string,
|
||||
): Promise<void> {
|
||||
const channel = member.guild.channels.cache.get(greetingChannelId);
|
||||
if (!channel) {
|
||||
logger.warn("Boost greeting channel not found", { channelId: greetingChannelId, guildId: member.guild.id });
|
||||
return;
|
||||
}
|
||||
|
||||
await channel.send({
|
||||
content: `🎉 Thank you for boosting <@${member.user?.id ?? member.id}>! You can now claim a custom role using \`/booster-role claim\` in <#${greetingChannelId}>.`
|
||||
});
|
||||
|
||||
logger.info("Boost greeting sent", {
|
||||
userId: member.user?.id ?? member.id,
|
||||
guildId: member.guild.id,
|
||||
channelId: greetingChannelId,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user