This commit is contained in:
Erik 2022-05-10 21:41:21 +03:00
parent ea1893636f
commit 8d64fdbfc6
Signed by untrusted user: Navy.gif
GPG Key ID: 811EC0CD80E7E5FB
3 changed files with 234 additions and 0 deletions

View File

@ -0,0 +1,87 @@
const { Emojis } = require("../../../../constants");
const { EmbedLimits } = require("../../../../constants/Constants");
const { SlashCommand } = require("../../../interfaces");
class SelfroleCommand extends SlashCommand {
constructor(client) {
super(client, {
name: 'selfrole',
description: 'Manage your selfroles',
module: 'utility',
guildOnly: true,
options: [{
name: ['add', 'remove'],
type: 'SUB_COMMAND',
options: [{
name: 'roles',
type: 'ROLES',
description: 'Roles to give/take',
required: true
}]
}, {
name: ['list', 'clear'],
type: 'SUB_COMMAND'
}],
clientPermissions: ['MANAGE_ROLES']
});
}
async execute(invoker, { roles }) {
const { subcommand: { name: subcommand } } = invoker;
if (subcommand === 'list') return this._listRoles(invoker);
const { guild, member } = invoker;
const { selfrole } = await guild.settings();
if (!selfrole.roles.length) return { index: 'COMMAND_SELFROLE_NONE', emoji: 'failure' };
const memberRoles = member.roles.cache.map((r) => r.id);
const _roles = roles.value.filter((r) => selfrole.roles.includes(r.id));
if (subcommand === 'add') {
await member.roles.set([...new Set([...memberRoles, ..._roles.map((r) => r.id)])]);
return { index: 'COMMAND_SELFROLE_ADD_SUCCESS', emoji: 'success', params: { roles: _roles.map((r) => r.name).join('**, **') } };
} else if (subcommand === 'remove') {
const ids = _roles.map((r) => r.id);
const set = memberRoles.filter((r) => !ids.includes(r));
await member.roles.set([...new Set(set)]);
return { index: 'COMMAND_SELFROLE_REMOVE_SUCCESS', emoji: 'success', params: { roles: _roles.map((r) => r.name).join('**, **') } };
} else if (subcommand === 'clear') {
const set = memberRoles.filter((r) => !selfrole.roles.includes(r));
await member.roles.set([...new Set(set)]);
return { index: 'COMMAND_SELFROLE_CLEAR_SUCCESS', emoji: 'success', };
}
}
async _listRoles(invoker) {
const { guild, member } = invoker;
const { selfrole } = await guild.settings();
const memberRoles = member.roles.cache;
if (!selfrole.roles.length) return { index: 'COMMAND_SELFROLE_NONE', emoji: 'failure' };
const fields = [];
const roles = selfrole.roles.map((r) => `${memberRoles.has(r) ? Emojis.success : Emojis.failure} <@&${r}>`);
let str = '';
for (const role of roles) {
const tmp = `${str}\n${role}`;
if (tmp.length > EmbedLimits.fieldValue) {
fields.push({ name: '\u200b', value: str });
str = role;
} else str = tmp;
}
fields.push({ name: '\u200b', value: str });
return {
embed: {
title: guild.format('COMMAND_SELFROLE_LIST'),
fields
}
};
}
}
module.exports = SelfroleCommand;

View File

@ -21,6 +21,7 @@ class UtilityHook extends Observer {
['inviteCreate', this.inviteCreate.bind(this)],
['inviteDelete', this.inviteDelete.bind(this)],
// ['messageReactionAdd', this.reactionAdd.bind(this)]
['interactionCreate', this.selfrole.bind(this)]
];
}
@ -163,6 +164,7 @@ class UtilityHook extends Observer {
}
// Code for enforcing single reaction per user for polls, disabled due to rate limit issues
async reactionAdd(reaction, user) {
if (reaction.partial) reaction = await reaction.fetch();
if (user.partial) user = await user.fetch();
@ -187,6 +189,37 @@ class UtilityHook extends Observer {
}
}
async selfrole(interaction) {
if (!interaction.isSelectMenu() && !interaction.isButton()) return;
const { guild, message, customId, values, channel, member } = interaction;
if (!guild || !member || !customId.includes('selfrole')) return;
const { selfrole } = await guild.settings();
if (!selfrole.message || selfrole.message !== message.id ||
!selfrole.channel || selfrole.channel !== channel.id ||
!selfrole.roles.length) return;
const missing = guild.me.permissions.missing(['MANAGE_ROLES']);
if (missing.length)
return this.client.emit('utilityError', { guild, utility: 'selfrole', reason: 'UTILITY_SELFROLE_PERMS', params: { missing: missing.join(', ') } });
const memberRoles = member.roles.cache.map((r) => r.id);
if (interaction.isButton()) {
const assignThese = memberRoles.filter((r) => !selfrole.roles.includes(r));
await member.roles.set(assignThese);
} else {
for (const value of values) {
if (!selfrole.roles.includes(value)) continue;
const index = memberRoles.indexOf(value);
if (index >= 0) memberRoles.splice(index, 1);
else memberRoles.push(value);
}
await member.roles.set(memberRoles);
}
await interaction.update({ components: message.components });
}
}
module.exports = UtilityHook;

View File

@ -0,0 +1,114 @@
const { Emojis } = require("../../../../constants");
const { Util } = require("../../../../utilities");
const { Setting } = require("../../../interfaces");
class SelfroleSetting extends Setting {
constructor(client) {
super(client, {
name: 'selfrole',
description: 'Configure roles that users can assign to themselves',
module: 'utility',
display: 'Self Role',
default: {
roles: [],
message: null,
channel: null,
text: null
},
commandOptions: [{
name: 'roles',
description: 'Modify roles users can give themselves',
choices: [
{ name: 'add', value: 'add' },
{ name: 'remove', value: 'remove' },
{ name: 'set', value: 'set' },
{ name: 'reset', value: 'reset' },
],
}, {
name: 'channel',
description: 'Optional channel to output message for selecting roles',
type: 'TEXT_CHANNEL'
}, {
name: 'text',
description: 'Optional text to display above the select menu'
}]
});
}
async execute(invoker, { roles, channel, text }, setting) {
if (!roles && !channel && !text) return { error: true, index: 'SETTING_MISSING_ARG' };
const { guild } = invoker;
if (roles) {
const response = await this._prompt(invoker, {
index: `SETTING_PROMPT_${roles.value.toUpperCase()}`,
params: { list: 'roles' }
});
if (response.error) return response;
const params = Util.parseQuotes(response).map(([param]) => param);
const values = (await guild.resolveRoles(params)).filter((r) => !r.managed).map((r) => r.id);
this[roles.value](setting.roles, values);
if(setting.roles.length >= 25 && (setting.channel || channel)) await invoker.channel.send(guild.format('SETTING_SELFROLE_WARNING'));
}
// old channel for deleting old message if one exists
const oldChannel = await guild.resolveChannel(setting.channel);
const newChannel = channel?.value || oldChannel;
if (channel) setting.channel = channel.value.id; // Set the new channel if one is given
if (text) setting.text = text.value;
// If an old channel exists, and a message exists, and either all roles were removed or the channel changed, delete the old message
if (oldChannel && setting.message && (!setting.roles.length || newChannel !== oldChannel)) {
const message = await oldChannel.messages.fetch(setting.message).catch(() => null);
if (message) {
await message.delete();
setting.message = null;
}
}
if (setting.roles.length && setting.channel && setting.roles.length <= 25) {
const roles = await guild.resolveRoles(setting.roles);
const components = [{
type: 'ACTION_ROW',
components: [{
type: 'SELECT_MENU',
customId: 'selfrole-select',
maxValues: roles.length,
options: roles.map((r) => {
return { label: r.name, value: r.id };
})
}]
}, {
type: 'ACTION_ROW',
components: [{
type: 'BUTTON',
customId: 'selfrole-clear',
label: 'Clear',
style: 'PRIMARY',
emoji: Emojis.failure
}]
}];
const payload = {
content: setting.text || guild.format('SETTING_SELFROLE_SELECT'),
components
};
const msg = await oldChannel.messages.fetch(setting.message).catch(() => null);
if (msg && newChannel === oldChannel) {
await msg.edit(payload);
} else {
const msg = await newChannel.send(payload);
setting.message = msg.id;
}
}
return { index: 'SETTING_SUCCESS_ALT' };
}
}
module.exports = SelfroleSetting;