greet.ts 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { Plugin, BotEventData, Event } from "src/model/plugin";
  2. import { GuildMember, PartialGuildMember, TextChannel } from "discord.js";
  3. import { getRepository } from "typeorm";
  4. import { logger } from "src/logging";
  5. import { GuildGreeting } from "@shared/db/entity/GuildGreeting";
  6. import { client } from "src/client";
  7. import { formatString } from "src/util";
  8. import { GuildVerification } from "@shared/db/entity/GuildVerification";
  9. import { tryDo } from "@shared/common/async_utils";
  10. @Plugin
  11. export class GreetPlugin {
  12. @Event("guildMemberAdd")
  13. async showGreetMessage(data: BotEventData, member: GuildMember | PartialGuildMember): Promise<void> {
  14. const greetInfo = await this.displayGreet(member, g => g.onJoinMessage);
  15. if (!greetInfo || !greetInfo.onJoinPrivateMessage) {
  16. return;
  17. }
  18. const verificationGuilds = getRepository(GuildVerification);
  19. const guild = await verificationGuilds.findOne(member.guild.id);
  20. if (!guild) {
  21. return;
  22. }
  23. const dmResult = await tryDo(member.createDM());
  24. if (!dmResult.ok) {
  25. logger.warn("greet: failed to create DM with user %s#%s (%s): %s", member.user?.username, member.user?.discriminator, member.id, dmResult.error);
  26. return;
  27. }
  28. const sendResult = await tryDo(dmResult.result.send(formatString(greetInfo.onJoinPrivateMessage, {
  29. memberID: member.id,
  30. memberTag: member.user?.tag ?? member.displayName,
  31. guildName: member.guild.name
  32. })));
  33. if (!sendResult.ok) {
  34. logger.warn("greet: failed to send DM greeting to %s#%s (%s): %s", member.user?.username, member.user?.discriminator, member.id, sendResult.error);
  35. }
  36. }
  37. @Event("guildMemberRemove")
  38. async showGoodbyeMessage(data: BotEventData, member: GuildMember | PartialGuildMember): Promise<void> {
  39. await this.displayGreet(member, g => g.onLeaveMessage);
  40. }
  41. private async displayGreet(member: GuildMember | PartialGuildMember, select: (greeting: GuildGreeting) => string) {
  42. const result = await this.getGreeting(member);
  43. if (!result)
  44. return undefined;
  45. const { guildGreeting, greetingChannel } = result;
  46. await greetingChannel.send(formatString(select(guildGreeting), {
  47. memberID: member.id,
  48. memberTag: member.user?.tag ?? member.displayName,
  49. guildName: member.guild.name
  50. }));
  51. return guildGreeting;
  52. }
  53. private async getGreeting(member: GuildMember | PartialGuildMember) {
  54. const repo = getRepository(GuildGreeting);
  55. const guildGreeting = await repo.findOne(member.guild.id);
  56. if (!guildGreeting) {
  57. logger.debug("Tried to greet user %s in guild %s but no greeting is defined!", member.id, member.guild.id);
  58. return undefined;
  59. }
  60. const greetingChannel = client.bot.channels.resolve(guildGreeting.greetingChannelId);
  61. if (!greetingChannel) {
  62. logger.warn("No channel %s in guild %s, can't greet!", guildGreeting.greetingChannelId, guildGreeting.guildId);
  63. return undefined;
  64. }
  65. if (!(greetingChannel instanceof TextChannel)) {
  66. logger.warn("Channel %s is of not a text channel (got type: %s)", greetingChannel.id, greetingChannel.type);
  67. return undefined;
  68. }
  69. return { guildGreeting, greetingChannel };
  70. }
  71. }