diff options
author | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2021-08-25 14:47:07 -0400 |
---|---|---|
committer | IRONM00N <64110067+IRONM00N@users.noreply.github.com> | 2021-08-25 14:47:07 -0400 |
commit | 0af0be5ab4ea0d972d9c406b28b81ee41a06cbdb (patch) | |
tree | cb5d6f06a115d7e9c3d38ea44995161f6c158082 /src/listeners | |
parent | 76622cfcd13727949ef3a0baa30bf72007132cd2 (diff) | |
download | tanzanite-0af0be5ab4ea0d972d9c406b28b81ee41a06cbdb.tar.gz tanzanite-0af0be5ab4ea0d972d9c406b28b81ee41a06cbdb.tar.bz2 tanzanite-0af0be5ab4ea0d972d9c406b28b81ee41a06cbdb.zip |
join roles, sticky roles, join messages, support threads etc
Diffstat (limited to 'src/listeners')
-rw-r--r-- | src/listeners/client/interactionCreate.ts | 4 | ||||
-rw-r--r-- | src/listeners/guild/guildCreate.ts | 18 | ||||
-rw-r--r-- | src/listeners/guild/guildDelete.ts | 16 | ||||
-rw-r--r-- | src/listeners/guild/guildMemberAdd.ts | 103 | ||||
-rw-r--r-- | src/listeners/guild/guildMemberRemove.ts | 67 | ||||
-rw-r--r-- | src/listeners/guild/syncUnban.ts | 7 | ||||
-rw-r--r-- | src/listeners/message/automodCreate.ts | 14 | ||||
-rw-r--r-- | src/listeners/message/supportThreads.ts | 43 |
8 files changed, 261 insertions, 11 deletions
diff --git a/src/listeners/client/interactionCreate.ts b/src/listeners/client/interactionCreate.ts index 7dc20ec..d76a484 100644 --- a/src/listeners/client/interactionCreate.ts +++ b/src/listeners/client/interactionCreate.ts @@ -1,5 +1,5 @@ import { BushListener } from '@lib'; -import { ClientEvents } from 'discord.js'; +import { BushClientEvents } from '../../lib/extensions/discord.js/BushClientEvents'; export default class InteractionCreateListener extends BushListener { public constructor() { @@ -10,7 +10,7 @@ export default class InteractionCreateListener extends BushListener { }); } - public override async exec(...[interaction]: ClientEvents['interactionCreate']): Promise<unknown> { + public override async exec(...[interaction]: BushClientEvents['interactionCreate']): Promise<unknown> { if (!interaction) return; if (interaction.isCommand()) { void client.console.info( diff --git a/src/listeners/guild/guildCreate.ts b/src/listeners/guild/guildCreate.ts new file mode 100644 index 0000000..21a7ab0 --- /dev/null +++ b/src/listeners/guild/guildCreate.ts @@ -0,0 +1,18 @@ +import { BushListener, Guild } from '../../lib'; +import { BushClientEvents } from '../../lib/extensions/discord.js/BushClientEvents'; + +export default class GuildCreateListener extends BushListener { + public constructor() { + super('guildCreate', { + emitter: 'client', + event: 'guildCreate', // when the bot joins a guild + category: 'client' + }); + } + + public override async exec(...[guild]: BushClientEvents['guildCreate']): Promise<void> { + void client.console.info('JoinGuild', `Joined <<${guild.name}>> with <<${guild.memberCount?.toLocaleString()}>> members.`); + const g = await Guild.findByPk(guild.id); + if (!g) void Guild.create({ id: guild.id }); + } +} diff --git a/src/listeners/guild/guildDelete.ts b/src/listeners/guild/guildDelete.ts new file mode 100644 index 0000000..a59f45e --- /dev/null +++ b/src/listeners/guild/guildDelete.ts @@ -0,0 +1,16 @@ +import { BushListener } from '../../lib'; +import { BushClientEvents } from '../../lib/extensions/discord.js/BushClientEvents'; + +export default class GuildDeleteListener extends BushListener { + public constructor() { + super('guildDelete', { + emitter: 'client', + event: 'guildDelete', //when the bot leaves a guild + category: 'client' + }); + } + + public override exec(...[guild]: BushClientEvents['guildDelete']): void { + void client.console.info('LeaveGuild', `Left <<${guild.name}>> with <<${guild.memberCount?.toLocaleString()}>> members.`); + } +} diff --git a/src/listeners/guild/guildMemberAdd.ts b/src/listeners/guild/guildMemberAdd.ts new file mode 100644 index 0000000..bf6e0b6 --- /dev/null +++ b/src/listeners/guild/guildMemberAdd.ts @@ -0,0 +1,103 @@ +import { MessageEmbed, Snowflake, Util } from 'discord.js'; +import { BushGuildMember, BushListener, BushTextChannel, StickyRole } from '../../lib'; +import { BushClientEvents } from '../../lib/extensions/discord.js/BushClientEvents'; + +export default class GuildMemberAddListener extends BushListener { + public constructor() { + super('guildMemberAdd', { + emitter: 'client', + event: 'guildMemberAdd', + category: 'client' + }); + } + + public override async exec(...[member]: BushClientEvents['guildMemberAdd']): Promise<void> { + void this.sendWelcomeMessage(member); + void this.joinAndStickyRoles(member); + } + + public async sendWelcomeMessage(member: BushGuildMember): Promise<void> { + if (client.config.isDevelopment) return; + const welcomeChannel = await member.guild.getSetting('welcomeChannel'); + if (!welcomeChannel) return; + const welcome = this.client.channels.cache.get(welcomeChannel) as BushTextChannel | undefined; + if (!welcome) return; + if (member.guild.id !== welcome?.guild.id) throw new Error('Welcome channel must be in the guild.'); + const embed = new MessageEmbed() + .setDescription( + `${this.client.util.emojis.join} **${Util.escapeMarkdown( + member.user.tag + )}** joined the server. There are now ${member.guild.memberCount.toLocaleString()} members.` + ) + .setColor(this.client.util.colors.green); + await welcome + .send({ embeds: [embed] }) + .then(() => this.client.console.info('OnJoin', `Sent a message for <<${member.user.tag}>> in <<${member.guild.name}>>.`)) + .catch(() => + this.client.console.warn('OnJoin', `Failed to send message for <<${member.user.tag}>> in <<${member.guild.name}>>.`) + ); + } + + public async joinAndStickyRoles(member: BushGuildMember): Promise<void> { + if (client.config.isDevelopment) return; + if (await member.guild.hasFeature('stickyRoles')) { + const hadRoles = await StickyRole.findOne({ where: { guild: member.guild.id, user: member.id } }); + if (hadRoles?.roles?.length) { + const rolesArray = hadRoles.roles + .map((roleID: Snowflake) => { + const role = member.guild.roles.cache.get(roleID); + if (role && !member.roles.cache.has(roleID)) { + if (role.name !== '@everyone' || !role.managed) return role.id; + } + }) + .filter((role) => role) as Snowflake[]; + if (hadRoles.nickname && member.manageable) { + void member.setNickname(hadRoles.nickname).catch(() => {}); + } + if (rolesArray?.length) { + const addedRoles = await member.roles + .add(rolesArray, "Returning member's previous roles.") + .catch( + () => void this.client.console.warn('ReturnRoles', `There was an error returning <<${member.user.tag}>>'s roles.`) + ); + if (addedRoles) { + void this.client.console.info( + 'RoleData', + `Assigned sticky roles to <<${member.user.tag}>> in <<${member.guild.name}>>.` + ); + } else if (!addedRoles) { + const failedRoles: string[] = []; + for (let i = 0; i < rolesArray.length; i++) { + await member.roles + .add(rolesArray[i], "[Fallback] Returning member's previous roles.") + .catch(() => failedRoles.push(rolesArray[i])); + } + if (failedRoles.length) { + void this.client.console.warn('RoleData', 'Failed assigning the following roles on Fallback:' + failedRoles); + } else { + void this.client.console.info( + 'RoleData', + `[Fallback] Assigned sticky roles to <<${member.user.tag}>> in <<${member.guild.name}>>.` + ); + } + } + } + } + } else { + const joinRoles = await member.guild.getSetting('joinRoles'); + if (!joinRoles) return; + await member.roles + .add(joinRoles, 'Join roles.') + .then(() => + this.client.console.info('RoleData', `Assigned join roles to <<${member.user.tag}>> in <<${member.guild.name}>>.`) + ) + .catch( + () => + void this.client.console.warn( + 'OnJoin', + `Failed to assign join roles to <<${member.user.tag}>>, in <<${member.guild.name}>>.` + ) + ); + } + } +} diff --git a/src/listeners/guild/guildMemberRemove.ts b/src/listeners/guild/guildMemberRemove.ts new file mode 100644 index 0000000..f25108f --- /dev/null +++ b/src/listeners/guild/guildMemberRemove.ts @@ -0,0 +1,67 @@ +import { MessageEmbed, Util } from 'discord.js'; +import { BushGuildMember, BushListener, BushTextChannel, PartialBushGuildMember, StickyRole } from '../../lib'; +import { BushClientEvents } from '../../lib/extensions/discord.js/BushClientEvents'; + +export default class GuildMemberRemoveListener extends BushListener { + public constructor() { + super('guildMemberRemove', { + emitter: 'client', + event: 'guildMemberRemove', + category: 'guild' + }); + } + + public override async exec(...[member]: BushClientEvents['guildMemberRemove']): Promise<void> { + void this.sendWelcomeMessage(member); + void this.stickyRoles(member); + } + + public async sendWelcomeMessage(member: BushGuildMember | PartialBushGuildMember): Promise<void> { + if (client.config.isDevelopment) return; + const user = member.partial ? await client.users.fetch(member.id) : member.user; + await util.sleep(0.05); // ban usually triggers after member leave + const isBan = member.guild.bans.cache.has(member.id); + const welcomeChannel = await member.guild.getSetting('welcomeChannel'); + if (!welcomeChannel) return; + const welcome = this.client.channels.cache.get(welcomeChannel) as BushTextChannel | undefined; + if (member.guild.id !== welcome?.guild.id) throw new Error('Welcome channel must be in the guild.'); + const embed: MessageEmbed = new MessageEmbed() + .setDescription( + `${this.client.util.emojis.leave} **${Util.escapeBold(user.tag)}** ${ + isBan ? 'banned from' : 'left' + } the server. There are now ${welcome.guild.memberCount.toLocaleString()} members.` + ) + .setColor(isBan ? util.colors.orange : util.colors.red); + welcome + .send({ embeds: [embed] }) + .then(() => client.console.info('OnLeave', `Sent a message for <<${user.tag}>> in <<${member.guild.name}>>.`)) + .catch(() => + this.client.console.warn('OnLeave', `Failed to send message for <<${user.tag}>> in <<${member.guild.name}>>.`) + ); + } + + public async stickyRoles(member: BushGuildMember | PartialBushGuildMember): Promise<void> { + if (!(await member.guild.hasFeature('stickyRoles'))) return; + if (member.partial) throw new Error('Partial member, cannot save sticky roles.'); + const rolesArray = member.roles.cache.filter((role) => role.name !== '@everyone').map((role) => role.id); + const nickname = member.nickname; + if (rolesArray) { + const [row, isNew] = await StickyRole.findOrBuild({ + where: { + user: member.user.id, + guild: member.guild.id + }, + defaults: { + user: member.user.id, + guild: member.guild.id, + roles: rolesArray + } + }); + row.roles = rolesArray; + if (nickname) row.nickname = nickname; + await row + .save() + .then(() => this.client.console.info('RoleData', `${isNew ? 'Created' : 'Updated'} info for <<${member.user.tag}>>.`)); + } + } +} diff --git a/src/listeners/guild/syncUnban.ts b/src/listeners/guild/syncUnban.ts index b1e4fd9..9a6a607 100644 --- a/src/listeners/guild/syncUnban.ts +++ b/src/listeners/guild/syncUnban.ts @@ -1,15 +1,16 @@ import { ActivePunishment, ActivePunishmentType, BushListener } from '@lib'; -import { ClientEvents } from 'discord.js'; +import { BushClientEvents } from '../../lib/extensions/discord.js/BushClientEvents'; export default class SyncUnbanListener extends BushListener { public constructor() { super('guildBanRemove', { emitter: 'client', - event: 'guildBanRemove' + event: 'guildBanRemove', + category: 'guild' }); } - public override async exec(...[ban]: ClientEvents['guildBanRemove']): Promise<void> { + public override async exec(...[ban]: BushClientEvents['guildBanRemove']): Promise<void> { const bans = await ActivePunishment.findAll({ where: { user: ban.user.id, diff --git a/src/listeners/message/automodCreate.ts b/src/listeners/message/automodCreate.ts index ff87513..ca61dd0 100644 --- a/src/listeners/message/automodCreate.ts +++ b/src/listeners/message/automodCreate.ts @@ -59,7 +59,7 @@ export default class AutomodMessageCreateListener extends BushListener { void message.delete().catch(() => {}); void message.member?.warn({ moderator: message.guild.me!, - reason: 'Saying a blacklisted word.' + reason: 'Saying a blacklisted word' }); break; @@ -68,7 +68,7 @@ export default class AutomodMessageCreateListener extends BushListener { void message.delete().catch(() => {}); void message.member?.mute({ moderator: message.guild.me!, - reason: 'Saying a blacklisted word.', + reason: 'Saying a blacklisted word', duration: 900_000 // 15 minutes }); break; @@ -77,7 +77,7 @@ export default class AutomodMessageCreateListener extends BushListener { void message.delete().catch(() => {}); void message.member?.mute({ moderator: message.guild.me!, - reason: 'Saying a blacklisted word.', + reason: 'Saying a blacklisted word', duration: 0 // perm }); break; @@ -102,9 +102,11 @@ export default class AutomodMessageCreateListener extends BushListener { new MessageEmbed() .setTitle(`[Severity ${highestOffence}] Automod Action Performed`) .setDescription( - `**User:** ${message.author} (${message.author.tag})\n**Sent From**: <#${message.channel.id}> [Jump to context](${ - message.url - })\n**Blacklisted Words:** ${util.surroundArray(Object.keys(offences), '`').join(', ')}` + `**User:** ${message.author.tag} (${message.author.tag})\n**Sent From**: <#${ + message.channel.id + }> [Jump to context](${message.url})\n**Blacklisted Words:** ${util + .surroundArray(Object.keys(offences), '`') + .join(', ')}` ) .addField('Message Content', `${await util.codeblock(message.content, 1024)}`) .setColor(color) diff --git a/src/listeners/message/supportThreads.ts b/src/listeners/message/supportThreads.ts new file mode 100644 index 0000000..ce2aa0d --- /dev/null +++ b/src/listeners/message/supportThreads.ts @@ -0,0 +1,43 @@ +import { GuildTextBasedChannels } from 'discord-akairo'; +import { MessageEmbed } from 'discord.js'; +import { BushListener, BushTextChannel } from '../../lib'; +import { BushClientEvents } from '../../lib/extensions/discord.js/BushClientEvents'; + +export default class MessageVerboseListener extends BushListener { + public constructor() { + super('supportThreads', { + emitter: 'client', + event: 'messageCreate', + category: 'message' + }); + } + + public override async exec(...[message]: BushClientEvents['messageCreate']): Promise<Promise<void> | undefined> { + if (!message.guild || !message.channel) return; + // todo: make these configurable etc... + if (message.guild.id !== '516977525906341928') return; // mb + if (message.channel.id !== '714332750156660756') return; // neu-support-1 + if (!(message.channel as BushTextChannel).permissionsFor(message.guild.me!).has('USE_PUBLIC_THREADS')) return; + const thread = await message.startThread({ + name: `Support - ${message.author.username}#${message.author.discriminator}`, + autoArchiveDuration: 1440, + reason: 'Support Thread' + }); + const embed = new MessageEmbed() + .setTitle('NotEnoughUpdates Support') + .setDescription( + `Welcome to Moulberry Bush Support:tm:\n\nPlease make sure you have the latest prerelease found in <#693586404256645231>.\nAdditionally if you need help installing the mod be sure to read <#737444942724726915> for a guide on how to do so.` + ) + .setColor('BLURPLE'); + void thread + .send({ embeds: [embed] }) + .then(() => + client.console.info( + 'supportThread', + `opened a support thread for <<${message.author.tag}>> in <<${ + (message.channel as GuildTextBasedChannels).name + }>> in <<${message.guild!.name}>>.` + ) + ); + } +} |