Files
Booster-role/src/discord/bot.ts
T

65 lines
2.6 KiB
TypeScript

import type { Client } from "discord.js";
import type { AppConfig } from "../config";
import { createDb } from "../db";
import { BoosterRoleService } from "../services/boosterRoleService";
import { DrizzleBoosterRoleStore } from "../services/drizzleBoosterRoleStore";
import { DiscordRoleRepository } from "../services/discordRoleRepository";
import { handleGuildMemberUpdate } from "./events/guildMemberUpdate";
import { handleInteraction } from "./interactionHandler";
export function attachBotHandlers(client: Client, config: AppConfig): void {
const db = createDb(config.databaseUrl);
const store = new DrizzleBoosterRoleStore(db);
client.on("interactionCreate", async (interaction) => {
if (!interaction.isChatInputCommand() || !interaction.guild) return;
const service = new BoosterRoleService(
store,
new DiscordRoleRepository(interaction.guild),
{ anchorPosition: resolveAnchorPosition(interaction.guild, config.boosterRoleAnchorRoleId) }
);
await handleInteraction(interaction, service, {
isBoosting: async () => memberHasRole(interaction.member, config.boosterEligibilityRoleId)
});
});
client.on("guildMemberUpdate", async (oldMember, newMember) => {
const service = new BoosterRoleService(
store,
new DiscordRoleRepository(newMember.guild),
{ anchorPosition: resolveAnchorPosition(newMember.guild, config.boosterRoleAnchorRoleId) }
);
await handleGuildMemberUpdate(oldMember, newMember, service, config.boosterEligibilityRoleId);
});
}
function memberHasRole(member: unknown, roleId: string): boolean {
return Boolean(
member &&
typeof member === "object" &&
"roles" in member &&
member.roles &&
typeof member.roles === "object" &&
"cache" in member.roles &&
member.roles.cache &&
typeof member.roles.cache === "object" &&
"has" in member.roles.cache &&
typeof member.roles.cache.has === "function" &&
member.roles.cache.has(roleId)
);
}
function resolveAnchorPosition(guild: { members: { me: { roles: { highest: { position: number } } } | null }; roles: { cache: { get(id: string): { position: number } | undefined } } }, anchorRoleId: string | null): number {
const botPosition = botRolePosition(guild);
if (!anchorRoleId) return botPosition;
const anchorPosition = guild.roles.cache.get(anchorRoleId)?.position ?? botPosition;
return Math.min(anchorPosition, botPosition);
}
function botRolePosition(guild: { members: { me: { roles: { highest: { position: number } } } | null } }): number {
return guild.members.me?.roles.highest.position ?? 1;
}