From 52ec49e84f5dbc14b338668001e353e4eef362df Mon Sep 17 00:00:00 2001 From: Jonathan Date: Fri, 29 Jan 2021 20:04:34 -0500 Subject: [PATCH 1/4] fix(nickname): max 32 characters for nicknames --- src/commands/Moderation/Member Modding/nickname.ts | 14 +++++++++----- src/languages/en-US.ts | 1 + src/lib/types/Languages.d.ts | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/commands/Moderation/Member Modding/nickname.ts b/src/commands/Moderation/Member Modding/nickname.ts index a96ab554..e6e45c7e 100644 --- a/src/commands/Moderation/Member Modding/nickname.ts +++ b/src/commands/Moderation/Member Modding/nickname.ts @@ -12,7 +12,7 @@ import { CommandOptions } from 'klasa'; permissionLevel: PermissionsLevels.MODERATOR, requiredPermissions: ['MANAGE_NICKNAMES'], runIn: ['text'], - usage: ' [nickname:string]' + usage: ' [nickname:string{,32}]' }) export default class extends SteveCommand { @@ -20,11 +20,15 @@ export default class extends SteveCommand { const member = await msg.guild.members.fetch(user); if (!member) return msg.channel.send(msg.guild.language.tget('userNotInGuild', user.tag)); - await member.setNickname(nickname); + try { + await member.setNickname(nickname); - return msg.channel.send(nickname - ? msg.guild.language.tget('commandNicknameSet', user.tag) - : msg.guild.language.tget('commandNicknameCleared', user.tag)); + return msg.channel.send(nickname + ? msg.guild.language.tget('commandNicknameSet', user.tag) + : msg.guild.language.tget('commandNicknameCleared', user.tag)); + } catch (err) { + return msg.channel.send(msg.guild.language.tget('commandNicknameUnableToSet', err, user.tag)); + } } } diff --git a/src/languages/en-US.ts b/src/languages/en-US.ts index 6b1d7435..8c8ea1a9 100644 --- a/src/languages/en-US.ts +++ b/src/languages/en-US.ts @@ -601,6 +601,7 @@ export default class extends Language { }), commandNicknameSet: user => `${user}'s nickname has been set.`, commandNicknameCleared: user => `${user}'s nickname has been cleared.`, + commandNicknameUnableToSet: (error, userTag) => `Unable to change ${userTag}'s nickname: **${error}**`, commandRoleDescription: 'Add or remove a role from a member', commandRoleExtended: builder.display('role', { examples: [ diff --git a/src/lib/types/Languages.d.ts b/src/lib/types/Languages.d.ts index 7a1be06c..e8443587 100644 --- a/src/lib/types/Languages.d.ts +++ b/src/lib/types/Languages.d.ts @@ -246,6 +246,7 @@ declare module 'klasa' { commandNicknameExtended: string; commandNicknameSet: (user: string) => string; commandNicknameCleared: (user: string) => string; + commandNicknameUnableToSet: (error: string, userTag: string) => string; commandRoleDescription: string; commandRoleExtended: string; commandRoleRemove: (roles: string) => string; From 7ad520a91592ef8a151733dca551c707f6c02cb7 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 31 Jan 2021 12:45:52 -0500 Subject: [PATCH 2/4] remove trusted role system --- src/commands/Self-Assign/assign.ts | 7 ---- .../Server Settings/settrustedrole.ts | 24 -------------- .../toggletrustedrolerequirement.ts | 32 ------------------- src/events/guildMemberAdd.ts | 11 ------- src/events/guildMemberUpdate.ts | 22 ------------- src/languages/en-US.ts | 20 ++---------- src/lib/schemas/Guild.ts | 5 +-- src/lib/setup/PermissionLevels.ts | 5 --- src/lib/types/Enums.d.ts | 1 - src/lib/types/Languages.d.ts | 9 ------ src/lib/types/settings/GuildSettings.ts | 3 -- src/serializers/trustedrolesetting.ts | 14 -------- 12 files changed, 3 insertions(+), 150 deletions(-) delete mode 100644 src/commands/Server Settings/settrustedrole.ts delete mode 100644 src/commands/Server Settings/toggletrustedrolerequirement.ts delete mode 100644 src/serializers/trustedrolesetting.ts diff --git a/src/commands/Self-Assign/assign.ts b/src/commands/Self-Assign/assign.ts index 15b5c98f..a1b7757f 100644 --- a/src/commands/Self-Assign/assign.ts +++ b/src/commands/Self-Assign/assign.ts @@ -30,13 +30,6 @@ export default class extends SteveCommand { public async run(msg: GuildMessage, roles: Role[]): Promise { if (Reflect.has(msg.flagArgs, 'list')) return this.listAssignableRoles(msg); - const trustedRoleID = msg.guild.settings.get(GuildSettings.Roles.Trusted); - const trustedRoleRequirement = msg.guild.settings.get(GuildSettings.Roles.RequireTrustedRoleForSelfAssign) as boolean; - - if (trustedRoleID && trustedRoleRequirement && !msg.member.roles.cache.has(trustedRoleID)) { - throw msg.guild.language.tget('commandAssignRoleNeedTrusted', msg.guild.roles.cache.get(trustedRoleID)!.name); - } - const removed: string[] = []; const added: string[] = []; diff --git a/src/commands/Server Settings/settrustedrole.ts b/src/commands/Server Settings/settrustedrole.ts deleted file mode 100644 index 2c3160d5..00000000 --- a/src/commands/Server Settings/settrustedrole.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { SteveCommand } from '@lib/structures/commands/SteveCommand'; -import { PermissionsLevels } from '@lib/types/Enums'; -import { GuildMessage } from '@lib/types/Messages'; -import { GuildSettings } from '@lib/types/settings/GuildSettings'; -import { ApplyOptions } from '@skyra/decorators'; -import { Message, Role } from 'discord.js'; -import { CommandOptions } from 'klasa'; - -@ApplyOptions({ - description: lang => lang.tget('commandSetTrustedRoleDescription'), - extendedHelp: lang => lang.tget('commandSetTrustedRoleExtended'), - permissionLevel: PermissionsLevels.MODERATOR, - runIn: ['text'], - usage: '' -}) -export default class extends SteveCommand { - - public async run(msg: GuildMessage, [role]: [Role]): Promise { - await msg.guild.settings.update(GuildSettings.Roles.Trusted, role.id, msg.guild.id); - - return msg.channel.send(msg.guild.language.tget('commandSetTrustedRoleSet', role.name)); - } - -} diff --git a/src/commands/Server Settings/toggletrustedrolerequirement.ts b/src/commands/Server Settings/toggletrustedrolerequirement.ts deleted file mode 100644 index 1b383ca2..00000000 --- a/src/commands/Server Settings/toggletrustedrolerequirement.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { SteveCommand } from '@lib/structures/commands/SteveCommand'; -import { PermissionsLevels } from '@lib/types/Enums'; -import { GuildMessage } from '@lib/types/Messages'; -import { GuildSettings } from '@lib/types/settings/GuildSettings'; -import { ApplyOptions } from '@skyra/decorators'; -import { Message } from 'discord.js'; -import { CommandOptions } from 'klasa'; - -@ApplyOptions({ - description: lang => lang.tget('commandToggleTrustedRoleRequirementDescription'), - extendedHelp: lang => lang.tget('commandToggleTrustedRoleRequirementExtended'), - permissionLevel: PermissionsLevels.MODERATOR, - requiredSettings: ['roles.trusted'], - runIn: ['text'] -}) -export default class extends SteveCommand { - - public async run(msg: GuildMessage): Promise { - const required: boolean = msg.guild.settings.get(GuildSettings.Roles.RequireTrustedRoleForSelfAssign); - - if (required) { - await msg.guild.settings.update(GuildSettings.Roles.RequireTrustedRoleForSelfAssign, false); - - return msg.channel.send(msg.guild.language.tget('commandToggleTrustedRoleRequirementDisable')); - } - - await msg.guild.settings.update(GuildSettings.Roles.RequireTrustedRoleForSelfAssign, true); - - return msg.channel.send(msg.guild.language.tget('commandToggleTrustedRoleRequirementEnable')); - } - -} diff --git a/src/events/guildMemberAdd.ts b/src/events/guildMemberAdd.ts index 91b15a10..881f5184 100644 --- a/src/events/guildMemberAdd.ts +++ b/src/events/guildMemberAdd.ts @@ -3,7 +3,6 @@ import { GuildMember, Message, MessageEmbed, TextChannel } from 'discord.js'; import { GuildSettings } from '@lib/types/settings/GuildSettings'; import { friendlyDuration, getExecutor, floatPromise } from '@utils/util'; import { LogColors } from '@lib/types/Enums'; -import { TrustedRoleSetting } from './guildMemberUpdate'; export default class extends Event { @@ -12,8 +11,6 @@ export default class extends Event { const memberlog = member.guild.channels.cache.get(member.guild.settings.get(GuildSettings.Channels.Memberlog)); if (memberlog && memberlog.isGuildTextChannel()) floatPromise(this, this.handleLog(member, memberlog)); } - - this.handleTrustedRole(member); } private async handleLog(member: GuildMember, memberlog: TextChannel): Promise { @@ -41,12 +38,4 @@ export default class extends Event { return memberlog.send(embed); } - private handleTrustedRole(member: GuildMember): void { - const { guild } = member; - const trustedRole = guild.roles.cache.get(guild.settings.get(GuildSettings.Roles.Trusted)); - const trustedRoleSetting: TrustedRoleSetting = guild.settings.get(GuildSettings.Roles.GiveTrustedRoleOn); - - if (trustedRole && trustedRoleSetting === 'join') floatPromise(this, member.roles.add(trustedRole)); - } - } diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts index c0f3893a..10610816 100644 --- a/src/events/guildMemberUpdate.ts +++ b/src/events/guildMemberUpdate.ts @@ -15,8 +15,6 @@ export default class extends Event { if (!oldMember.roles.cache.equals(newMember.roles.cache)) floatPromise(this, this.logRoleUpdate(oldMember, newMember, memberlog)); } } - - if (!oldMember.roles.cache.equals(newMember.roles.cache)) floatPromise(this, this.handleTrustedRole(oldMember, newMember)); } private async logDisplayNameChange(oldMember: GuildMember, newMember: GuildMember, memberlog: TextChannel): Promise { @@ -54,29 +52,9 @@ export default class extends Event { return memberlog.send(embed); } - private async handleTrustedRole(oldMember: GuildMember, newMember: GuildMember): Promise { - const { guild } = newMember; - const role = await this.getRoleFromAuditLogs(newMember.guild); - const trustedRole = guild.roles.cache.get(guild.settings.get(GuildSettings.Roles.Trusted)); - const trustedRoleSetting: TrustedRoleSetting = guild.settings.get(GuildSettings.Roles.GiveTrustedRoleOn); - const restrictedRoles = guild.settings.get(GuildSettings.Roles.Restricted) as string[]; - - if (trustedRoleSetting === 'role') { - if (newMember.roles.cache.size === 2 && oldMember.roles.cache.size < newMember.roles.cache.size) { - if (!restrictedRoles.includes(role.id)) { - if (trustedRole && !newMember.roles.cache.has(trustedRole.id)) { - floatPromise(this, newMember.roles.add(trustedRole)); - } - } - } - } - } - private async getRoleFromAuditLogs(guild: Guild): Promise { const logs = await guild.fetchAuditLogs({ limit: 1, type: 'MEMBER_ROLE_UPDATE' }); return logs.entries.first()!.changes![0].new[0]; } } - -export type TrustedRoleSetting = 'none' | 'join' | 'role'; diff --git a/src/languages/en-US.ts b/src/languages/en-US.ts index 8c8ea1a9..f93d2515 100644 --- a/src/languages/en-US.ts +++ b/src/languages/en-US.ts @@ -756,7 +756,6 @@ export default class extends Language { commandAssignNotAssignable: role => `${Emojis.REDX} The ${role} role is not self-assignable.`, commandAssignRoleAdd: roles => `${Emojis.PLUS} Added role(s): \`${roles}\``, commandAssignRoleRemove: roles => `${Emojis.MINUS} Removed role(s): \`${roles}\``, - commandAssignRoleNeedTrusted: role => `You need to have the **${role}** role to do that!`, /** * ################################ * # MEMBER INFO # @@ -936,14 +935,6 @@ export default class extends Language { reminder: 'This command does not add any extra Discord permissions to the role, it just gives this role access to server staff commands.' }), commandSetModeratorRoleSet: role => `The ${role} role will be used as this server's moderator role.`, - commandSetTrustedRoleDescription: 'Set the server\'s trusted role', - commandSetTrustedRoleExtended: builder.display('settrustedrole', { - explainedUsage: [ - ['rolename', 'You can use the name of a role, it\'s snowflake (long id), or tag the role (if it is taggable).'] - ], - reminder: 'This command does not add any extra Discord permissions to the role.' - }), - commandSetTrustedRoleSet: role => `The ${role} role will be used as this server's trusted role.`, commandSetMutedRoleDescription: 'Set the server\'s muted role', commandSetMutedRoleExtended: builder.display('setmutedrole', { explainedUsage: [ @@ -980,7 +971,7 @@ export default class extends Language { ['reset', 'Clears the list of restricted roles.'], ['show', 'Displays the list of restricted roles.'] ], - extendedHelp: 'Restricted roles cannot be viewed with the `roleinfo` command, except for when a server staff member is the person using the command. Members who receive a restricted role as their first role will not be given the server\'s trusted role if one has been set.' + extendedHelp: 'Restricted roles cannot be viewed with the `roleinfo` command, except for when a server staff member is the person using the command.' }), commandManageRestrictedRolesManageRemoved: removedRoles => `${Emojis.MINUS} Removed roles: ${removedRoles}\n`, commandManageRestrictedRolesManageAdded: addedRoles => `${Emojis.PLUS} Added roles: ${addedRoles}`, @@ -1030,12 +1021,6 @@ export default class extends Language { extendedHelp: 'This setting defaults to being off.' }), commandToggleDeletePinMessages: disabling => `Pinned message notifications will ${disabling ? 'no longer' : 'now'} be deleted.`, - commandToggleTrustedRoleRequirementDescription: 'Choose whether the server\'s trusted role is required to self-assign roles', - commandToggleTrustedRoleRequirementExtended: builder.display('toggletrustedrolerequirement', { - extendedHelp: 'The server must have a trusted role set before this command can be used.' - }), - commandToggleTrustedRoleRequirementDisable: 'The trusted role is no longer required to self-assign roles.', - commandToggleTrustedRoleRequirementEnable: 'The trusted role is now required to self-assign roles.', /** * ################################ * # USER SETTINGS COMMANDS # @@ -1249,8 +1234,7 @@ export default class extends Language { * # SERIALIZERS # * ################################ */ - serializerColorInvalidHex: code => `${code} is not a valid hex.`, - serializerTrustedRoleSettingInvalidSetting: setting => `${setting} is not a valid setting for giveTrustedRoleOn.` + serializerColorInvalidHex: code => `${code} is not a valid hex.` }; diff --git a/src/lib/schemas/Guild.ts b/src/lib/schemas/Guild.ts index 4aa694ca..43b928e6 100644 --- a/src/lib/schemas/Guild.ts +++ b/src/lib/schemas/Guild.ts @@ -37,10 +37,7 @@ export default Client.defaultGuildSchema .add('deafened', 'Role') .add('moderator', 'Role') .add('muted', 'Role') - .add('restricted', 'Role', { array: true }) - .add('trusted', 'Role') - .add('giveTrustedRoleOn', 'TrustedRoleSetting', { 'default': 'none' }) - .add('requireTrustedRoleForSelfAssign', 'Boolean', { 'default': false })) + .add('restricted', 'Role', { array: true })) .add('roleAliases', 'any', { array: true, configurable: false }) .add('snippets', 'any', { array: true, configurable: false }) .add('wordBlacklist', wordBlacklist => wordBlacklist diff --git a/src/lib/setup/PermissionLevels.ts b/src/lib/setup/PermissionLevels.ts index 62424ebb..cebfe9f2 100644 --- a/src/lib/setup/PermissionLevels.ts +++ b/src/lib/setup/PermissionLevels.ts @@ -5,11 +5,6 @@ import { Permissions } from 'discord.js'; export default Client.defaultPermissionLevels = new PermissionLevels() .add(PermissionsLevels.EVERYONE, () => true) - .add(PermissionsLevels.TRUSTED, msg => msg.member - ? msg.guild!.settings.get(GuildSettings.Roles.Trusted) - ? msg.member.roles.cache.has(msg.guild!.settings.get(GuildSettings.Roles.Trusted)) - : false - : false, { fetch: true }) .add(PermissionsLevels.MODERATOR, msg => msg.member ? msg.guild!.settings.get(GuildSettings.Roles.Moderator) ? msg.member.roles.cache.has(msg.guild!.settings.get(GuildSettings.Roles.Moderator)) diff --git a/src/lib/types/Enums.d.ts b/src/lib/types/Enums.d.ts index ed423171..1cbfc86b 100644 --- a/src/lib/types/Enums.d.ts +++ b/src/lib/types/Enums.d.ts @@ -25,7 +25,6 @@ export const enum LogColors { export const enum PermissionsLevels { EVERYONE = 0, - TRUSTED = 1, MODERATOR = 7, ADMINISTRATOR = 8, OWNER = 10 diff --git a/src/lib/types/Languages.d.ts b/src/lib/types/Languages.d.ts index e8443587..ca98a424 100644 --- a/src/lib/types/Languages.d.ts +++ b/src/lib/types/Languages.d.ts @@ -300,7 +300,6 @@ declare module 'klasa' { commandAssignNotAssignable: (role: string) => string; commandAssignRoleAdd: (roles: string) => string; commandAssignRoleRemove: (roles: string) => string; - commandAssignRoleNeedTrusted: (role: string) => string; commandWhoIsDescription: string; commandWhoIsExtended: string; commandWhoIsDate: (duration: string, date: string) => string; @@ -382,9 +381,6 @@ declare module 'klasa' { commandSetModeratorRoleDescription: string; commandSetModeratorRoleExtended: string; commandSetModeratorRoleSet: (role: string) => string; - commandSetTrustedRoleDescription: string; - commandSetTrustedRoleExtended: string; - commandSetTrustedRoleSet: (role: string) => string; commandSetMutedRoleDescription: string; commandSetMutedRoleExtended: string; commandSetMutedRoleSet: (role: string) => string; @@ -417,10 +413,6 @@ declare module 'klasa' { commandToggleDeletePinMessagesDescription: string; commandToggleDeletePinMessagesExtended: string; commandToggleDeletePinMessages: (disabling: boolean) => string; - commandToggleTrustedRoleRequirementDescription: string; - commandToggleTrustedRoleRequirementExtended: string; - commandToggleTrustedRoleRequirementDisable: string; - commandToggleTrustedRoleRequirementEnable: string; commandSetEmbedColorDescription: string; commandSetEmbedColorExtended: string; resolverInvalidColor: (hex: string) => string; @@ -574,6 +566,5 @@ declare module 'klasa' { inhibitorPingProtectionEveryone: string; inhibitorPingprotectionEveryone: string; serializerColorInvalidHex: (code: string) => string; - serializerTrustedRoleSettingInvalidSetting: (setting: string) => string; } } diff --git a/src/lib/types/settings/GuildSettings.ts b/src/lib/types/settings/GuildSettings.ts index db920857..843a4843 100644 --- a/src/lib/types/settings/GuildSettings.ts +++ b/src/lib/types/settings/GuildSettings.ts @@ -52,9 +52,6 @@ export namespace GuildSettings { export const Moderator = 'roles.moderator'; export const Muted = 'roles.muted'; export const Restricted = 'roles.restricted'; - export const Trusted = 'roles.trusted'; - export const GiveTrustedRoleOn = 'roles.giveTrustedRoleOn'; - export const RequireTrustedRoleForSelfAssign = 'roles.requireTrustedRoleForSelfAssign'; } export namespace WordBlacklist { diff --git a/src/serializers/trustedrolesetting.ts b/src/serializers/trustedrolesetting.ts deleted file mode 100644 index 234c39d6..00000000 --- a/src/serializers/trustedrolesetting.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Language, SchemaPiece, Serializer } from 'klasa'; -export default class extends Serializer { - - // eslint-disable-next-line @typescript-eslint/require-await - public async deserialize(data: string, piece: SchemaPiece, lang: Language): Promise { - if (data === 'none' || data === 'join' || data === 'role') return data; - throw lang.tget('serializerTrustedRoleSettingInvalidSetting', data); - } - - public serialize(value: string): string { - return value; - } - -} From 323f8c8486ec91ad643985294febb9f4c76ef3e8 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 31 Jan 2021 16:13:36 -0500 Subject: [PATCH 3/4] add auto role system --- src/commands/Server Settings/setautorole.ts | 24 ++++++++++++++++++++ src/events/guildMemberAdd.ts | 13 +++++++++++ src/events/guildMemberUpdate.ts | 25 +++++++++++++++++++-- src/languages/en-US.ts | 7 ++++++ src/lib/schemas/Guild.ts | 2 ++ src/lib/types/Languages.d.ts | 4 ++++ src/lib/types/settings/GuildSettings.ts | 2 ++ src/serializers/autorole.ts | 15 +++++++++++++ 8 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/commands/Server Settings/setautorole.ts create mode 100644 src/serializers/autorole.ts diff --git a/src/commands/Server Settings/setautorole.ts b/src/commands/Server Settings/setautorole.ts new file mode 100644 index 00000000..51a46249 --- /dev/null +++ b/src/commands/Server Settings/setautorole.ts @@ -0,0 +1,24 @@ +import { SteveCommand } from '@lib/structures/commands/SteveCommand'; +import { PermissionsLevels } from '@lib/types/Enums'; +import { GuildMessage } from '@lib/types/Messages'; +import { GuildSettings } from '@lib/types/settings/GuildSettings'; +import { ApplyOptions } from '@skyra/decorators'; +import { Message, Role } from 'discord.js'; +import { CommandOptions } from 'klasa'; + +@ApplyOptions({ + description: lang => lang.tget('commandSetAutoRoleDescription'), + extendedHelp: lang => lang.tget('commandSetAutoRoleExtended'), + permissionLevel: PermissionsLevels.MODERATOR, + runIn: ['text'], + usage: '' +}) +export default class extends SteveCommand { + + public async run(msg: GuildMessage, [role]: [Role]): Promise { + await msg.guild.settings.update(GuildSettings.Roles.Auto, role.id, msg.guild.id); + + return msg.channel.send(msg.guild.language.tget('commandSetAutoRoleSet', role.name)); + } + +} diff --git a/src/events/guildMemberAdd.ts b/src/events/guildMemberAdd.ts index 881f5184..b339f8a4 100644 --- a/src/events/guildMemberAdd.ts +++ b/src/events/guildMemberAdd.ts @@ -11,6 +11,8 @@ export default class extends Event { const memberlog = member.guild.channels.cache.get(member.guild.settings.get(GuildSettings.Channels.Memberlog)); if (memberlog && memberlog.isGuildTextChannel()) floatPromise(this, this.handleLog(member, memberlog)); } + + floatPromise(this, this.handleAutoRole(member)); } private async handleLog(member: GuildMember, memberlog: TextChannel): Promise { @@ -38,4 +40,15 @@ export default class extends Event { return memberlog.send(embed); } + private async handleAutoRole(member: GuildMember) { + const autoRoleSetting = member.guild.settings.get(GuildSettings.Roles.AutoRoleSetting) as string; + + if (autoRoleSetting === 'join') { + const autoRoleID = member.guild.settings.get(GuildSettings.Roles.Auto); + const role = member.guild.roles.cache.get(autoRoleID); + + if (role) await member.roles.add(role); + } + } + } diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts index 10610816..320d6fce 100644 --- a/src/events/guildMemberUpdate.ts +++ b/src/events/guildMemberUpdate.ts @@ -1,5 +1,5 @@ import { Event } from 'klasa'; -import { GuildMember, TextChannel, Role, Guild, Message, MessageEmbed } from 'discord.js'; +import { GuildMember, TextChannel, Guild, Message, MessageEmbed } from 'discord.js'; import { GuildSettings } from '@lib/types/settings/GuildSettings'; import { floatPromise, getExecutor } from '@utils/util'; import { LogColors } from '@lib/types/Enums'; @@ -15,6 +15,8 @@ export default class extends Event { if (!oldMember.roles.cache.equals(newMember.roles.cache)) floatPromise(this, this.logRoleUpdate(oldMember, newMember, memberlog)); } } + + if (!oldMember.roles.cache.equals(newMember.roles.cache)) floatPromise(this, this.handleAutoRole(oldMember, newMember)); } private async logDisplayNameChange(oldMember: GuildMember, newMember: GuildMember, memberlog: TextChannel): Promise { @@ -52,9 +54,28 @@ export default class extends Event { return memberlog.send(embed); } - private async getRoleFromAuditLogs(guild: Guild): Promise { + private async getRoleFromAuditLogs(guild: Guild) { const logs = await guild.fetchAuditLogs({ limit: 1, type: 'MEMBER_ROLE_UPDATE' }); return logs.entries.first()!.changes![0].new[0]; } + private async handleAutoRole(oldMember: GuildMember, newMember: GuildMember) { + const { guild } = newMember; + const role = await this.getRoleFromAuditLogs(newMember.guild); + const autoRole = guild.roles.cache.get(guild.settings.get(GuildSettings.Roles.Auto)); + const autoRoleSetting = guild.settings.get(GuildSettings.Roles.AutoRoleSetting); + + const restrictedRoles = guild.settings.get(GuildSettings.Roles.Restricted) as string[]; + + if (autoRoleSetting === 'role') { + if (newMember.roles.cache.size === 2 && oldMember.roles.cache.size < newMember.roles.cache.size) { // TODO: handle multiple roles being added at once + if (!restrictedRoles.includes(role.id)) { + if (autoRole && !newMember.roles.cache.has(autoRole.id)) { + floatPromise(this, newMember.roles.add(autoRole)); + } + } + } + } + } + } diff --git a/src/languages/en-US.ts b/src/languages/en-US.ts index f93d2515..b58ef0ab 100644 --- a/src/languages/en-US.ts +++ b/src/languages/en-US.ts @@ -927,6 +927,13 @@ export default class extends Language { reminder: 'This command does not add any extra Discord permissions to the role, it just gives this role access to server staff commands.' }), commandSetAdministratorRoleSet: role => `The ${role} role will be used as this server's administrator role.`, + commandSetAutoRoleDescription: 'Set the server\'s auto role', + commandSetAutoRoleExtended: builder.display('setautorole', { + explainedUsage: [ + ['rolename', 'You can use the name of a role, it\'s snowflake (long id), or tag the role (if it is taggable).'] + ] + }), + commandSetAutoRoleSet: roleName => `The ${roleName} will be used as this server's auto role.`, commandSetModeratorRoleDescription: 'Set the server\'s moderator role', commandSetModeratorRoleExtended: builder.display('setmoderatorrole', { explainedUsage: [ diff --git a/src/lib/schemas/Guild.ts b/src/lib/schemas/Guild.ts index 43b928e6..03880760 100644 --- a/src/lib/schemas/Guild.ts +++ b/src/lib/schemas/Guild.ts @@ -34,6 +34,8 @@ export default Client.defaultGuildSchema .add('roles', roles => roles .add('administrator', 'Role') .add('assignable', 'Role', { array: true }) + .add('auto', 'Role') + .add('autoRoleSetting', 'AutoRole', { 'default': 'none' }) .add('deafened', 'Role') .add('moderator', 'Role') .add('muted', 'Role') diff --git a/src/lib/types/Languages.d.ts b/src/lib/types/Languages.d.ts index ca98a424..c8219346 100644 --- a/src/lib/types/Languages.d.ts +++ b/src/lib/types/Languages.d.ts @@ -378,6 +378,9 @@ declare module 'klasa' { commandSetAdministratorRoleDescription: string; commandSetAdministratorRoleExtended: string; commandSetAdministratorRoleSet: (role: string) => string; + commandSetAutoRoleDescription: string; + commandSetAutoRoleExtended: string; + commandSetAutoRoleSet: (roleName: string) => string; commandSetModeratorRoleDescription: string; commandSetModeratorRoleExtended: string; commandSetModeratorRoleSet: (role: string) => string; @@ -566,5 +569,6 @@ declare module 'klasa' { inhibitorPingProtectionEveryone: string; inhibitorPingprotectionEveryone: string; serializerColorInvalidHex: (code: string) => string; + serializerAutoRoleInvalid: (setting: string) => string; } } diff --git a/src/lib/types/settings/GuildSettings.ts b/src/lib/types/settings/GuildSettings.ts index 843a4843..5215f432 100644 --- a/src/lib/types/settings/GuildSettings.ts +++ b/src/lib/types/settings/GuildSettings.ts @@ -48,6 +48,8 @@ export namespace GuildSettings { export namespace Roles { export const Administrator = 'roles.administrator'; export const Assignable = 'roles.assignable'; + export const Auto = 'roles.auto'; + export const AutoRoleSetting = 'roles.autoRoleSetting'; export const Deafened = 'roles.deafened'; export const Moderator = 'roles.moderator'; export const Muted = 'roles.muted'; diff --git a/src/serializers/autorole.ts b/src/serializers/autorole.ts new file mode 100644 index 00000000..5bdb3264 --- /dev/null +++ b/src/serializers/autorole.ts @@ -0,0 +1,15 @@ +import { Language, SchemaPiece, Serializer } from 'klasa'; + +export default class extends Serializer { + + // eslint-disable-next-line @typescript-eslint/require-await + public async deserialize(data: string, piece: SchemaPiece, lang: Language): Promise { + if (data === 'none' || data === 'join' || data === 'role') return data; + throw lang.tget('serializerAutoRoleInvalid', data); + } + + public serialize(value: string): string { + return value; + } + +} From 2f19d0914c2ef6ae6274762939db1f3433a96e16 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 31 Jan 2021 16:16:26 -0500 Subject: [PATCH 4/4] gg --- src/languages/en-US.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/en-US.ts b/src/languages/en-US.ts index b58ef0ab..7b5c92cf 100644 --- a/src/languages/en-US.ts +++ b/src/languages/en-US.ts @@ -928,7 +928,7 @@ export default class extends Language { }), commandSetAdministratorRoleSet: role => `The ${role} role will be used as this server's administrator role.`, commandSetAutoRoleDescription: 'Set the server\'s auto role', - commandSetAutoRoleExtended: builder.display('setautorole', { + commandSetAutoRoleExtended: builder.display('setautorole', { // TODO: better help explainedUsage: [ ['rolename', 'You can use the name of a role, it\'s snowflake (long id), or tag the role (if it is taggable).'] ]