Home Manual Reference Source Repository

src/bot/permissions.js

'use babel';
'use strict';

import Module from '../commands/module';

/** Contains methods to test whether a user has permissions in a guild */
export default class BotPermissions {
	/**
	 * @param {Client} client - The Client to use
	 * @param {ModRoleStorage} modRoles - The mod role storage to use
	 * @param {SettingStorage} settings - The setting storage to use
	 * @param {BotConfig} config - The bot config to use
	 */
	constructor(client, modRoles, settings, config) {
		if(!client || !modRoles || !settings || !config) throw new Error('A client, modRoles, settings, and config must be specified.');

		/** @type {Client} */
		this.client = client;
		/** @type {ModRoleStorage} */
		this.modRoles = modRoles;
		/** @type {SettingStorage} */
		this.settings = settings;
		/** @type {BotConfig} */
		this.config = config;
	}

	/**
	 * Tests to see if a user is a moderator in a guild.
	 * If the guild has not set any moderator roles, then they will be a moderator if any of their assigned roles contain the "Manage messages" permission.
	 * If the guild has set moderator roles, then they will instead be a moderator if they have any of the moderator roles assigned.
	 * The bot owner and users with the "Administrate" permission are always moderators.
	 * @param {Guild|string} guild - The Guild or the guild ID
	 * @param {User|string} user - The User or the user ID
	 * @return {boolean} Whether or not the user is considered a moderator
	 * @see {@link BotPermissions.isMod}
	 */
	isMod(guild, user) {
		return this.constructor.isMod(this.client, this.modRoles, this.settings, this.config, guild, user);
	}

	/**
	 * Tests to see if a user is a moderator in a guild using a specified client and config.
	 * If the guild has not set any moderator roles, then they will be a moderator if any of their assigned roles contain the "Manage messages" permission.
	 * If the guild has set moderator roles, then they will instead be a moderator if they have any of the moderator roles assigned.
	 * The bot owner and users with the "Administrate" permission are always moderators.
	 * @param {Client} client - The Client to use
	 * @param {ModRoleStorage} modRoles - The mod role storage to use
	 * @param {SettingStorage} settings - The setting storage to use
	 * @param {BotConfig} config - The bot config to use
	 * @param {Guild|string} guild - The Guild or the guild ID
	 * @param {User|string} user - The User or the user ID
	 * @return {boolean} Whether or not the user is considered a moderator
	 * @see {@link BotPermissions#isMod}
	 */
	static isMod(client, modRoles, settings, config, guild, user) {
		[guild, user] = this.resolve(client, guild, user);
		if(user.id === config.values.owner) return true;
		const member = guild.member(user);
		if(!member) return false;
		if(member.hasPermission('ADMINISTRATOR')) return true;
		if(!Module.isEnabled(settings, guild, 'mod-roles') || modRoles.isEmpty(guild)) return member.hasPermission('MANAGE_MESSAGES');
		const roles = member.roles;
		return modRoles.find(guild).some(role => roles.some(role2 => role.id === role2.id));
	}

	/**
	 * Tests to see if a user is an administrator in a guild.
	 * If the user is the bot owner or has any roles assigned with the "Administrate" permission, they are considered an administrator.
	 * @param {Guild|string} guild - The Guild or the guild ID
	 * @param {User|string} user - The User or the user ID
	 * @return {boolean} Whether or not the user is considered an administrator
	 * @see {@link BotPermissions.isAdmin}
	 */
	isAdmin(guild, user) {
		return this.constructor.isAdmin(this.client, this.config, guild, user);
	}

	/**
	 * Tests to see if a user is an administrator in a guild with a specified client.
	 * If the user is the bot owner or has any roles assigned with the "Administrate" permission, they are considered an administrator.
	 * @param {Client} client - The Client to use
	 * @param {BotConfig} config - The bot config to use
	 * @param {Guild|string} guild - The Guild or the guild ID
	 * @param {User|string} user - The User or the user ID
	 * @return {boolean} Whether or not the user is considered an administrator
	 * @see {@link BotPermissions#isAdmin}
	 */
	static isAdmin(client, config, guild, user) {
		[guild, user] = this.resolve(client, guild, user);
		if(user.id === config.values.owner) return true;
		const member = guild.member(user);
		if(!member) return false;
		return member.hasPermission('ADMINISTRATOR');
	}

	/**
	 * Tests to see if a user is the owner of the bot
	 * @param {User|string} user - The User or the user ID
	 * @return {boolean} Whether or not the user is the bot owner
	 * @see {@link BotPermissions.isOwner}
	 */
	isOwner(user) {
		return this.constructor.isOwner(this.config, user);
	}

	/**
	 * Tests to see if a user is the owner of the bot
	 * @param {BotConfig} config - The bot config to use
	 * @param {User|string} user - The User or the user ID
	 * @return {boolean} Whether or not the user is the bot owner
	 * @see {@link BotPermissions#isOwner}
	 */
	static isOwner(config, user) {
		if(!user) throw new Error('A user must be specified.');
		return (user.id || user) === config.values.owner;
	}

	/**
	 * Resolves a guild and user to Discord.js instances
	 * @param {Guild|string} guild - The Guild or the guild ID
	 * @param {User|string} user - The User or the user ID
	 * @return {[guild, user]} The Guild and User instance pair
	 * @see {@link BotPermissions.resolve}
	 */
	resolve(guild, user) {
		if(!guild || !user) throw new Error('A guild and user must be specified.');
		return this.constructor.resolve(this.client, guild, user);
	}

	/**
	 * Resolves a guild and user to Discord.js instances with a specified client
	 * @param {Client} client - The Client to use
	 * @param {Guild|string} guild - The Guild or the guild ID
	 * @param {User|string} user - The User or the user ID
	 * @return {[guild, user]} The Guild and User instance pair
	 * @see {@link BotPermissions#resolve}
	 */
	static resolve(client, guild, user) {
		if(!client || !guild || !user) throw new Error('A client, guild, and user must be specified.');
		if(typeof guild === 'string') guild = client.guilds.get(guild);
		if(!guild || !guild.id) throw new Error('Unable to identify guild.');
		if(typeof user === 'string') user = guild.members.get(user);
		if(!user || !user.id) throw new Error('Unable to identify user.');
		return [guild, user];
	}
}