2020-05-17 15:07:39 +02:00
|
|
|
const { Role, MessageAttachment } = require('discord.js');
|
2020-05-08 08:50:54 +02:00
|
|
|
const { Command } = require('../../../../interfaces/');
|
|
|
|
|
2020-08-14 10:35:41 +02:00
|
|
|
const { Util, Emojis } = require('../../../../../util/');
|
2020-05-08 08:50:54 +02:00
|
|
|
const { stripIndents } = require('common-tags');
|
|
|
|
|
2020-08-14 08:29:58 +02:00
|
|
|
const Constants = {
|
|
|
|
pageSize: 9
|
|
|
|
};
|
|
|
|
|
2020-05-17 15:07:39 +02:00
|
|
|
class PermissionsCommand extends Command {
|
2020-05-08 08:50:54 +02:00
|
|
|
|
|
|
|
constructor(client) {
|
|
|
|
|
|
|
|
super(client, {
|
|
|
|
name: 'permissions',
|
|
|
|
module: 'administration',
|
2020-08-14 10:35:41 +02:00
|
|
|
usage: "['list'|role|user]",
|
2020-05-08 08:50:54 +02:00
|
|
|
aliases: [
|
|
|
|
'perms',
|
|
|
|
'permission',
|
|
|
|
'perm'
|
|
|
|
],
|
|
|
|
examples: [
|
2020-05-17 15:07:39 +02:00
|
|
|
"list",
|
2020-05-08 08:50:54 +02:00
|
|
|
"Server Moderators",
|
|
|
|
"@nolan#2887"
|
|
|
|
],
|
2020-05-17 15:07:39 +02:00
|
|
|
arguments: [
|
|
|
|
{
|
2020-08-14 08:29:58 +02:00
|
|
|
name: 'export',
|
2020-05-17 15:07:39 +02:00
|
|
|
type: 'BOOLEAN',
|
|
|
|
types: ['VERBAL', 'FLAG'],
|
|
|
|
default: true
|
|
|
|
}
|
|
|
|
],
|
|
|
|
// memberPermissions: ['ADMINISTRATOR', 'MANAGE_GUILD'],
|
2020-05-08 08:50:54 +02:00
|
|
|
guildOnly: true
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-05-17 15:07:39 +02:00
|
|
|
async execute(message, { params, args }) {
|
|
|
|
|
2020-08-14 10:35:41 +02:00
|
|
|
const permissions = await message.guild.permissions();
|
2020-08-14 08:29:58 +02:00
|
|
|
|
|
|
|
if(args.export) {
|
|
|
|
await this._displayRaw(message, permissions);
|
2020-07-25 08:02:22 +02:00
|
|
|
return undefined;
|
|
|
|
}
|
2020-06-02 12:09:28 +02:00
|
|
|
|
2020-08-14 08:29:58 +02:00
|
|
|
if(params[0] === 'list') {
|
|
|
|
await this._listAvailablePermissions(message);
|
2020-07-25 08:02:22 +02:00
|
|
|
return undefined;
|
|
|
|
}
|
2020-05-17 15:07:39 +02:00
|
|
|
|
2020-08-14 08:29:58 +02:00
|
|
|
const parameters = params.join(' ');
|
|
|
|
let resolveable = await this._parseResolveable(message, parameters);
|
|
|
|
if(resolveable) {
|
|
|
|
if(resolveable.user) resolveable = resolveable.user;
|
|
|
|
|
|
|
|
const type = resolveable.tag ? 'user' : 'role';
|
|
|
|
const permission = permissions[resolveable?.id || parameters];
|
|
|
|
|
|
|
|
if(resolveable && !permission) {
|
|
|
|
await message.respond(message.format('C_PERMISSIONS_PERMISSIONSNOTFOUND', { resolveable: resolveable.tag || resolveable.name, type, they: type === 'user' ? 'they ' : '' }), { emoji: 'failure' });
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!permission) {
|
|
|
|
await message.respond(message.format('C_PERMISSIONS_NOTFOUND'), { emoji: 'failure' });
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
const embed = {
|
|
|
|
author: {
|
|
|
|
name: `${resolveable?.user?.tag || resolveable?.tag || resolveable?.name || parameters}'s Permissions`,
|
|
|
|
icon_url: resolveable.displayAvatarURL ? resolveable.displayAvatarURL() : message.guild.iconURL() //eslint-disable-line camelcase
|
|
|
|
},
|
|
|
|
description: `${message.format('C_PERMISSIONS_GLOBAL', { permissions: permission.global.length > 0 ? this._displayNames(permission.global).map((p) => `\`${p}\``).join(', ') : "`N/A`" })} ${Object.values(permission.channels).length > 0 ? message.format('C_PERMISSIONS_GLOBALALT') : ''}`,
|
|
|
|
fields: []
|
|
|
|
};
|
|
|
|
|
|
|
|
let update = false;
|
|
|
|
for(const [channelId, perms] of Object.entries(permission.channels)) {
|
|
|
|
const channel = await this.client.resolver.resolveChannel(channelId, true, message.guild);
|
|
|
|
if(!channel) {
|
|
|
|
delete permission.channels[channelId];
|
|
|
|
update = true;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
if(embed.fields.length === 25) {
|
|
|
|
embed.description += `\n${message.format('C_PERMISSIONS_MAXFIELDS')}`;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
embed.fields.push({
|
|
|
|
name: `#${channel.name}`,
|
|
|
|
value: this._displayNames(perms).map((p) => `\`${p}\``).join(', ')
|
|
|
|
});
|
2020-05-17 15:07:39 +02:00
|
|
|
}
|
|
|
|
}
|
2020-08-14 08:29:58 +02:00
|
|
|
if(update) {
|
|
|
|
delete permissions._id;
|
|
|
|
try {
|
|
|
|
await this.client.storageManager.mongodb.permissions.updateOne(
|
|
|
|
{ guildId: message.guild.id },
|
|
|
|
permissions
|
|
|
|
);
|
|
|
|
} catch(error) {
|
|
|
|
this.client.logger.error(`Error removing channel permissions to ${message.guild.id}:\n${error.stack || error}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return message.embed(embed);
|
2020-07-25 08:02:22 +02:00
|
|
|
}
|
2020-08-14 08:29:58 +02:00
|
|
|
|
|
|
|
//End of displaying user/role permissions.
|
2020-08-14 10:35:41 +02:00
|
|
|
|
|
|
|
const _permissions = [];
|
|
|
|
for(const [key, value] of Object.entries(permissions)) {
|
|
|
|
if(value?.global?.length === 0 && Object.keys(value?.channels).length === 0) {
|
|
|
|
await this._deletePermission(message.guild, key);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!Number.isNaN(parseInt(key))) _permissions.push({ ...value, id: key });
|
|
|
|
}
|
|
|
|
|
2020-08-14 08:29:58 +02:00
|
|
|
let currentPage = 1;
|
|
|
|
if(parameters.length > 0) {
|
|
|
|
const number = parseInt(parameters[0]);
|
|
|
|
if(!Number.isNaN(number) && number > 1) {
|
|
|
|
currentPage = number;
|
2020-05-17 15:07:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-14 10:35:41 +02:00
|
|
|
const size = _permissions.length;
|
2020-08-14 08:29:58 +02:00
|
|
|
if(size === 0) {
|
|
|
|
return message.respond(message.format('C_PERMISSIONS_NOPERMISSIONS'), {
|
|
|
|
emoji: 'failure'
|
|
|
|
});
|
|
|
|
}
|
2020-07-25 08:02:22 +02:00
|
|
|
|
2020-08-14 10:35:41 +02:00
|
|
|
let { items, page, maxPage } = Util.paginate(_permissions, currentPage, Constants.pageSize); //eslint-disable-line prefer-const
|
2020-05-17 15:07:39 +02:00
|
|
|
|
|
|
|
const embed = {
|
|
|
|
author: {
|
2020-08-14 08:29:58 +02:00
|
|
|
name: `Guild Permissions`,
|
2020-07-25 08:08:47 +02:00
|
|
|
icon_url: message.guild.iconURL() //eslint-disable-line camelcase
|
2020-05-17 15:07:39 +02:00
|
|
|
},
|
2020-08-14 08:29:58 +02:00
|
|
|
fields: [],
|
|
|
|
footer: {
|
|
|
|
text: `• Page ${page}/${maxPage} | ${size} Results`
|
|
|
|
}
|
2020-05-17 15:07:39 +02:00
|
|
|
};
|
2020-08-14 08:29:58 +02:00
|
|
|
|
|
|
|
for(const item of items) {
|
|
|
|
item.resolveable = await this._parseResolveable(message, item.id);
|
2020-08-14 10:35:41 +02:00
|
|
|
item.permissions = this._displayNames(item.global);
|
2020-08-14 08:29:58 +02:00
|
|
|
}
|
2020-05-17 15:07:39 +02:00
|
|
|
|
2020-08-14 08:29:58 +02:00
|
|
|
const display = (items) => {
|
2020-08-14 10:35:41 +02:00
|
|
|
items = items.sort((a, b) => b.permissions.length - a.permissions.length);
|
2020-08-14 08:29:58 +02:00
|
|
|
for(const item of items) {
|
|
|
|
const field = {
|
2020-08-14 10:35:41 +02:00
|
|
|
name: `${item.resolveable instanceof Role ? Emojis.role : Emojis.member} ${Util.escapeMarkdown(item.resolveable.display)}`,
|
|
|
|
value: item.permissions.map((n) => `\`${n}\``).join('\n'),
|
2020-08-14 08:29:58 +02:00
|
|
|
inline: true
|
|
|
|
};
|
|
|
|
|
|
|
|
const channels = Object.keys(item.channels).length;
|
|
|
|
if(channels > 0) {
|
|
|
|
field.value += `\n\`..${channels} channel${channels === 1 ? '' : 's'}\``;
|
|
|
|
}
|
|
|
|
|
|
|
|
embed.fields.push(field);
|
2020-06-02 12:09:28 +02:00
|
|
|
}
|
2020-08-14 08:29:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
display(items.filter((i) => i.resolveable instanceof Role));
|
|
|
|
display(items.filter((i) => !(i.resolveable instanceof Role)));
|
|
|
|
|
|
|
|
const empty = items.length % 3;
|
|
|
|
for(let i = 0; i<empty; i++) {
|
2020-05-17 15:07:39 +02:00
|
|
|
embed.fields.push({
|
2020-08-14 08:29:58 +02:00
|
|
|
name: '\u200b',
|
|
|
|
value: '\u200b',
|
|
|
|
inline: true
|
2020-05-17 15:07:39 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-06-02 12:09:28 +02:00
|
|
|
return message.embed(embed);
|
2020-05-17 15:07:39 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async _listAvailablePermissions(message) {
|
|
|
|
|
2020-07-25 08:02:22 +02:00
|
|
|
const components = this.client.registry.components.filter((c) => c.type === 'command' || c.type === 'module' && c.components.some((c) => c.type === 'command'))
|
2020-05-17 15:07:39 +02:00
|
|
|
.sort((a, b) => a - b);
|
|
|
|
|
2020-08-14 08:29:58 +02:00
|
|
|
return message.respond(message.format('C_PERMISSIONS_LIST', {
|
|
|
|
permissions: components.map((c) => `\`${c.resolveable}\``).join(', ')
|
|
|
|
}), { emoji: 'success' });
|
2020-05-17 15:07:39 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async _parseResolveable(message, resolveable) {
|
2020-08-14 08:29:58 +02:00
|
|
|
let parsed = await this.client.resolver.resolveRole(resolveable, true, message.guild);
|
2020-05-17 15:07:39 +02:00
|
|
|
if(!parsed) {
|
2020-08-14 08:29:58 +02:00
|
|
|
parsed = await this.client.resolver.resolveMember(resolveable, true, message.guild);
|
2020-05-17 15:07:39 +02:00
|
|
|
if(!parsed) {
|
2020-08-14 08:29:58 +02:00
|
|
|
parsed = await this.client.resolver.resolveUser(resolveable, true);
|
2020-05-17 15:07:39 +02:00
|
|
|
if(!parsed) return null;
|
|
|
|
}
|
|
|
|
}
|
2020-06-02 12:09:28 +02:00
|
|
|
return parsed;
|
2020-05-17 15:07:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async _displayRaw(message, permissions) {
|
|
|
|
|
|
|
|
const string = JSON.stringify(permissions);
|
|
|
|
const attachment = new MessageAttachment(Buffer.from(string), "permissions.json");
|
|
|
|
|
2020-08-14 08:29:58 +02:00
|
|
|
return message.respond(message.format('C_PERMISSIONS_JSON'), {
|
|
|
|
emoji: 'success',
|
|
|
|
files: [ attachment ]
|
|
|
|
});
|
2020-05-17 15:07:39 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_displayNames(permissions) {
|
|
|
|
|
2020-07-25 08:02:22 +02:00
|
|
|
const modules = this.client.registry.components.filter((c) => c.type === 'module');
|
2020-05-17 15:07:39 +02:00
|
|
|
let names = [];
|
2020-05-08 08:50:54 +02:00
|
|
|
|
2020-05-17 15:07:39 +02:00
|
|
|
let temp = [];
|
|
|
|
for(const module of modules.values()) {
|
2020-07-25 08:02:22 +02:00
|
|
|
for(const component of module.components.filter((c) => c.type === 'command').values()) {
|
2020-05-17 15:07:39 +02:00
|
|
|
if(permissions.includes(component.resolveable)) {
|
|
|
|
temp.push(component.resolveable);
|
|
|
|
}
|
|
|
|
}
|
2020-08-14 08:29:58 +02:00
|
|
|
temp.length === module.components.filter((c) => c.type === 'command').size //eslint-disable-line no-unused-expressions
|
2020-05-17 15:07:39 +02:00
|
|
|
? names.push(module.resolveable)
|
|
|
|
: names = names.concat(temp);
|
|
|
|
temp = [];
|
|
|
|
}
|
2020-05-08 08:50:54 +02:00
|
|
|
|
2020-05-17 15:07:39 +02:00
|
|
|
return names;
|
2020-05-08 08:50:54 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-08-14 08:29:58 +02:00
|
|
|
async _deletePermission(guild, key) {
|
|
|
|
|
|
|
|
const permissions = guild._permissions;
|
|
|
|
delete permissions[key];
|
|
|
|
delete permissions._id;
|
|
|
|
|
|
|
|
try {
|
|
|
|
await this.client.storageManager.mongodb.permissions.updateOne(
|
|
|
|
{ guildId: guild.id },
|
|
|
|
permissions
|
|
|
|
);
|
|
|
|
} catch(error) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-05-08 08:50:54 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-05-17 15:07:39 +02:00
|
|
|
module.exports = PermissionsCommand;
|