galactic-bot/structure/client/components/commands/administration/Permissions.js

273 lines
9.3 KiB
JavaScript

const { Role, MessageAttachment } = require('discord.js');
const { Command } = require('../../../../interfaces/');
const { Util } = require('../../../../../util/');
const { stripIndents } = require('common-tags');
const Constants = {
pageSize: 9
};
class PermissionsCommand extends Command {
constructor(client) {
super(client, {
name: 'permissions',
module: 'administration',
usage: "<list|role-name|user-name>",
aliases: [
'perms',
'permission',
'perm'
],
examples: [
"list",
"Server Moderators",
"@nolan#2887"
],
arguments: [
{
name: 'export',
type: 'BOOLEAN',
types: ['VERBAL', 'FLAG'],
default: true
}
],
// memberPermissions: ['ADMINISTRATOR', 'MANAGE_GUILD'],
guildOnly: true
});
}
async execute(message, { params, args }) {
const _permissions = await message.guild.permissions();
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 });
}
if(args.export) {
await this._displayRaw(message, permissions);
return undefined;
}
if(params[0] === 'list') {
await this._listAvailablePermissions(message);
return undefined;
}
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(', ')
});
}
}
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);
}
//End of displaying user/role permissions.
let currentPage = 1;
if(parameters.length > 0) {
const number = parseInt(parameters[0]);
if(!Number.isNaN(number) && number > 1) {
currentPage = number;
}
}
const size = permissions.length;
if(size === 0) {
return message.respond(message.format('C_PERMISSIONS_NOPERMISSIONS'), {
emoji: 'failure'
});
}
let { items, page, maxPage } = Util.paginate(permissions, currentPage, Constants.pageSize); //eslint-disable-line prefer-const
const embed = {
author: {
name: `Guild Permissions`,
icon_url: message.guild.iconURL() //eslint-disable-line camelcase
},
fields: [],
footer: {
text: `• Page ${page}/${maxPage} | ${size} Results`
}
};
for(const item of items) {
item.resolveable = await this._parseResolveable(message, item.id);
}
const display = (items) => {
items = items.sort((a, b) => b.resolveable.display.length - a.resolveable.display.length);
for(const item of items) {
const field = {
name: item.resolveable.display,
value: this._displayNames(item.global).map((n) => `\`${n}\``).join('\n'),
inline: true
};
const channels = Object.keys(item.channels).length;
if(channels > 0) {
field.value += `\n\`..${channels} channel${channels === 1 ? '' : 's'}\``;
}
embed.fields.push(field);
}
};
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++) {
embed.fields.push({
name: '\u200b',
value: '\u200b',
inline: true
});
}
return message.embed(embed);
}
async _listAvailablePermissions(message) {
const components = this.client.registry.components.filter((c) => c.type === 'command' || c.type === 'module' && c.components.some((c) => c.type === 'command'))
.sort((a, b) => a - b);
return message.respond(message.format('C_PERMISSIONS_LIST', {
permissions: components.map((c) => `\`${c.resolveable}\``).join(', ')
}), { emoji: 'success' });
}
async _parseResolveable(message, resolveable) {
let parsed = await this.client.resolver.resolveRole(resolveable, true, message.guild);
if(!parsed) {
parsed = await this.client.resolver.resolveMember(resolveable, true, message.guild);
if(!parsed) {
parsed = await this.client.resolver.resolveUser(resolveable, true);
if(!parsed) return null;
}
}
return parsed;
}
async _displayRaw(message, permissions) {
const string = JSON.stringify(permissions);
const attachment = new MessageAttachment(Buffer.from(string), "permissions.json");
return message.respond(message.format('C_PERMISSIONS_JSON'), {
emoji: 'success',
files: [ attachment ]
});
}
_displayNames(permissions) {
const modules = this.client.registry.components.filter((c) => c.type === 'module');
let names = [];
let temp = [];
for(const module of modules.values()) {
for(const component of module.components.filter((c) => c.type === 'command').values()) {
if(permissions.includes(component.resolveable)) {
temp.push(component.resolveable);
}
}
temp.length === module.components.filter((c) => c.type === 'command').size //eslint-disable-line no-unused-expressions
? names.push(module.resolveable)
: names = names.concat(temp);
temp = [];
}
return names;
}
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;
}
}
module.exports = PermissionsCommand;