import { Plugin, BotEventData, Event } from "src/model/plugin"; import { GuildMember, PartialGuildMember, TextChannel } from "discord.js"; import { getRepository } from "typeorm"; import { eventLogger, logger } from "src/logging"; import { GuildGreeting } from "@shared/db/entity/GuildGreeting"; import { client } from "src/client"; import { formatString } from "src/util"; import { GuildVerification } from "@shared/db/entity/GuildVerification"; import { tryDo } from "@shared/common/async_utils"; @Plugin export class GreetPlugin { @Event("guildMemberAdd") async showGreetMessage(data: BotEventData, member: GuildMember | PartialGuildMember): Promise { eventLogger.info("User %s#%s (%s) joined server %s (%s)", member.user?.username, member.user?.discriminator, member.user?.id, member.guild.name, member.guild.id); const greetInfo = await this.displayGreet(member, g => g.onJoinMessage); if (!greetInfo || !greetInfo.onJoinPrivateMessage) { return; } const verificationGuilds = getRepository(GuildVerification); const guild = await verificationGuilds.findOne(member.guild.id); if (!guild) { return; } const dmResult = await tryDo(member.createDM()); if (!dmResult.ok) { logger.warn("greet: failed to create DM with user %s#%s (%s): %s", member.user?.username, member.user?.discriminator, member.id, dmResult.error); return; } const sendResult = await tryDo(dmResult.result.send(formatString(greetInfo.onJoinPrivateMessage, { memberID: member.id, memberTag: member.user?.tag ?? member.displayName, guildName: member.guild.name }))); if (!sendResult.ok) { logger.warn("greet: failed to send DM greeting to %s#%s (%s): %s", member.user?.username, member.user?.discriminator, member.id, sendResult.error); } } @Event("guildMemberRemove") async showGoodbyeMessage(data: BotEventData, member: GuildMember | PartialGuildMember): Promise { eventLogger.info("User %s#%s (%s) left server %s (%s)", member.user?.username, member.user?.discriminator, member.user?.id, member.guild.name, member.guild.id); await this.displayGreet(member, g => g.onLeaveMessage); } private async displayGreet(member: GuildMember | PartialGuildMember, select: (greeting: GuildGreeting) => string) { const result = await this.getGreeting(member); if (!result) return undefined; const { guildGreeting, greetingChannel } = result; await greetingChannel.send(formatString(select(guildGreeting), { memberID: member.id, memberTag: member.user?.tag ?? member.displayName, guildName: member.guild.name })); return guildGreeting; } private async getGreeting(member: GuildMember | PartialGuildMember) { const repo = getRepository(GuildGreeting); const guildGreeting = await repo.findOne(member.guild.id); if (!guildGreeting) { logger.debug("Tried to greet user %s in guild %s but no greeting is defined!", member.id, member.guild.id); return undefined; } const greetingChannel = client.bot.channels.resolve(guildGreeting.greetingChannelId); if (!greetingChannel) { logger.warn("No channel %s in guild %s, can't greet!", guildGreeting.greetingChannelId, guildGreeting.guildId); return undefined; } if (!(greetingChannel instanceof TextChannel)) { logger.warn("Channel %s is of not a text channel (got type: %s)", greetingChannel.id, greetingChannel.type); return undefined; } return { guildGreeting, greetingChannel }; } }