Skip to content

Commit

Permalink
perm-checkify
Browse files Browse the repository at this point in the history
  • Loading branch information
Larsundso committed Dec 19, 2023
1 parent a40ee56 commit c0c311c
Show file tree
Hide file tree
Showing 67 changed files with 1,343 additions and 205 deletions.
14 changes: 7 additions & 7 deletions src/BaseClient/ClientHelperModules/mod/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,7 @@ const mod = {
}

const res = await request.guilds.editMember(
options.guild,
targetMember.id,
targetMember,
{
communication_disabled_until: new Date(
Date.now() + (options.duration > 2419200 ? 2419200000 : options.duration * 1000),
Expand Down Expand Up @@ -296,7 +295,7 @@ const mod = {
return false;
}

const res = await request.guilds.editMember(options.guild, targetMember.id, {
const res = await request.guilds.editMember(targetMember, {
communication_disabled_until: null,
});

Expand Down Expand Up @@ -333,7 +332,6 @@ const mod = {

const res = await (memberRes
? request.guilds.banMember(
options.guild,
memberRes.targetMember,
{ delete_message_seconds: options.deleteMessageSeconds },
options.reason,
Expand Down Expand Up @@ -438,13 +436,15 @@ const mod = {
return false;
}

if (!options.guild.members.cache.get(options.target.id) && !options.skipChecks) {
const member = options.guild.members.cache.get(options.target.id);

if (!member && !options.skipChecks) {
actionAlreadyApplied(cmd, message, options.target, language, type);
return false;
}

const res = await request.guilds.removeMember(options.guild, options.target.id);
if ((res as Discord.DiscordAPIError).message) {
const res = member ? await request.guilds.removeMember(member, options.reason) : false;
if (res && (res as Discord.DiscordAPIError).message) {
err(cmd, res as Discord.DiscordAPIError, language, message, options.guild);
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import error from '../../error.js';
import { API } from '../../../Client.js';
import cache from '../../cache.js';

import getBotMemberFromGuild from '../../getBotMemberFromGuild.js';
import requestHandlerError from '../../requestHandlerError.js';

/**
* Adds a role to a member in a guild.
* @param guild - The guild where the member is in.
Expand All @@ -12,10 +15,35 @@ import cache from '../../cache.js';
* @returns A promise that resolves with the updated member object if successful,
* or rejects with a DiscordAPIError if an error occurs.
*/
export default async (guild: Discord.Guild, userId: string, roleId: string, reason?: string) =>
(cache.apis.get(guild.id) ?? API).guilds
export default async (guild: Discord.Guild, userId: string, roleId: string, reason?: string) => {
if (
!canAddRoleToMember(
guild.roles.cache.get(roleId) as Discord.Role,
await getBotMemberFromGuild(guild),
)
) {
const e = requestHandlerError(`Cannot add role to member in ${guild.name} / ${guild.id}`, [
Discord.PermissionFlagsBits.ManageRoles,
]);

error(guild, e);
return e;
}

return (cache.apis.get(guild.id) ?? API).guilds
.addRoleToMember(guild.id, userId, roleId, { reason })
.catch((e) => {
error(guild, new Error((e as Discord.DiscordAPIError).message));
return e as Discord.DiscordAPIError;
});
};

/**
* Checks if a role can be added to a guild member.
* @param role - The role to be added.
* @param me - The guild member performing the action.
* @returns A boolean indicating whether the role can be added to the member.
*/
export const canAddRoleToMember = (role: Discord.Role, me: Discord.GuildMember) =>
me.permissions.has(Discord.PermissionFlagsBits.ManageRoles) &&
role.comparePositionTo(me.roles.highest) < 0;
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,23 @@ import requestHandlerError from '../../requestHandlerError.js';
* @returns A promise that resolves with the DiscordAPIError if the request fails, otherwise void.
*/
export default async (
guild: Discord.Guild,
member: Discord.GuildMember,
body?: Discord.RESTPutAPIGuildBanJSONBody,
reason?: string,
) => {
if (!canBanUser(await getBotMemberFromGuild(guild))) {
if (!canBanUser(await getBotMemberFromGuild(member.guild))) {
const e = requestHandlerError(`Cannot ban member in ${member.displayName} / ${member.id}`, [
Discord.PermissionFlagsBits.BanMembers,
]);

error(guild, e);
error(member.guild, e);
return e;
}

return (cache.apis.get(guild.id) ?? API).guilds
.banUser(guild.id, member.id, body, { reason })
return (cache.apis.get(member.guild.id) ?? API).guilds
.banUser(member.guild.id, member.id, body, { reason })
.catch((e) => {
error(guild, new Error((e as Discord.DiscordAPIError).message));
error(member.guild, new Error((e as Discord.DiscordAPIError).message));
return e as Discord.DiscordAPIError;
});
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import error from '../../error.js';
import { API } from '../../../Client.js';
import cache from '../../cache.js';

import getBotMemberFromGuild from '../../getBotMemberFromGuild.js';
import requestHandlerError from '../../requestHandlerError.js';

/**
* Bans a user from a guild.
* @param guild The guild to ban the user from.
Expand All @@ -16,8 +19,28 @@ export default async (
userId: string,
body?: Discord.RESTPutAPIGuildBanJSONBody,
reason?: string,
) =>
(cache.apis.get(guild.id) ?? API).guilds.banUser(guild.id, userId, body, { reason }).catch((e) => {
error(guild, new Error((e as Discord.DiscordAPIError).message));
return e as Discord.DiscordAPIError;
});
) => {
if (!canBanUser(await getBotMemberFromGuild(guild))) {
const e = requestHandlerError(`Cannot ban user ${userId}`, [
Discord.PermissionFlagsBits.BanMembers,
]);

error(guild, e);
return e;
}

return (cache.apis.get(guild.id) ?? API).guilds
.banUser(guild.id, userId, body, { reason })
.catch((e) => {
error(guild, new Error((e as Discord.DiscordAPIError).message));
return e as Discord.DiscordAPIError;
});
};

/**
* Checks if the given guild member has the permission to ban members.
* @param me - The guild member to check.
* @returns True if the guild member has the permission to ban members, false otherwise.
*/
export const canBanUser = (me: Discord.GuildMember) =>
me.permissions.has(Discord.PermissionFlagsBits.BanMembers);
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import error from '../../error.js';
import { API } from '../../../Client.js';
import cache from '../../cache.js';

import getBotMemberFromGuild from '../../getBotMemberFromGuild.js';
import requestHandlerError from '../../requestHandlerError.js';

/**
* Begins pruning of inactive members in a guild.
* @param guild - The guild to prune members from.
Expand All @@ -15,8 +18,27 @@ export default async (
guild: Discord.Guild,
body?: Discord.RESTPostAPIGuildPruneJSONBody,
reason?: string,
) =>
(cache.apis.get(guild.id) ?? API).guilds.beginPrune(guild.id, body, { reason }).catch((e) => {
error(guild, new Error((e as Discord.DiscordAPIError).message));
return e as Discord.DiscordAPIError;
});
) => {
if (!canPrune(await getBotMemberFromGuild(guild))) {
const e = requestHandlerError(`Cannot prune members in ${guild.name} / ${guild.id}`, [
Discord.PermissionFlagsBits.KickMembers,
]);

error(guild, e);
return e;
}

return (cache.apis.get(guild.id) ?? API).guilds
.beginPrune(guild.id, body, { reason })
.catch((e) => {
error(guild, new Error((e as Discord.DiscordAPIError).message));
return e as Discord.DiscordAPIError;
});
};
/**
* Checks if the user has the necessary permissions to prune members from a guild.
* @param me - The Discord guild member representing the user.
* @returns A boolean indicating whether the user can prune members.
*/
export const canPrune = (me: Discord.GuildMember) =>
me.permissions.has(Discord.PermissionFlagsBits.KickMembers);
24 changes: 22 additions & 2 deletions src/BaseClient/ClientHelperModules/requestHandler/guilds/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,37 @@ import { API } from '../../../Client.js';
import cache from '../../cache.js';
import * as Classes from '../../../Other/classes.js';

import getBotMemberFromGuild from '../../getBotMemberFromGuild.js';
import requestHandlerError from '../../requestHandlerError.js';

/**
* Creates a new guild.
* @param guild The guild to create the new guild in.
* @param body The JSON body of the request.
* @returns A promise that resolves with the newly created guild or rejects with a DiscordAPIError.
*/
export default async (guild: Discord.Guild, body: Discord.RESTPostAPIGuildsJSONBody) =>
(cache.apis.get(guild.id) ?? API).guilds
export default async (guild: Discord.Guild, body: Discord.RESTPostAPIGuildsJSONBody) => {
if (!canCreate(await getBotMemberFromGuild(guild))) {
const e = requestHandlerError(`Cannot create guild ${guild.name} / ${guild.id}`, [
Discord.PermissionFlagsBits.ManageGuild,
]);

error(guild, e);
return e;
}

return (cache.apis.get(guild.id) ?? API).guilds
.create(body)
.then((g) => new Classes.Guild(guild.client, g))
.catch((e) => {
error(guild, new Error((e as Discord.DiscordAPIError).message));
return e as Discord.DiscordAPIError;
});
};

/**
* Checks if the given guild member can create a new guild.
* @param me - The Discord guild member.
* @returns True if the guild member can create a new guild, false otherwise.
*/
export const canCreate = (me: Discord.GuildMember) => me.client.guilds.cache.size < 10;
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { API } from '../../../Client.js';
import cache from '../../cache.js';
import * as Classes from '../../../Other/classes.js';

import getBotMemberFromGuild from '../../getBotMemberFromGuild.js';
import requestHandlerError from '../../requestHandlerError.js';

/**
* Creates an auto-moderation rule for a guild.
* @param guild The guild to create the rule for.
Expand All @@ -15,11 +18,30 @@ export default async (
guild: Discord.Guild,
body: Discord.RESTPostAPIAutoModerationRuleJSONBody,
reason?: string,
) =>
(cache.apis.get(guild.id) ?? API).guilds
) => {
if (!canCreateAutoModerationRule(await getBotMemberFromGuild(guild))) {
const e = requestHandlerError(
`Cannot create auto-moderation rule in ${guild.name} / ${guild.id}`,
[Discord.PermissionFlagsBits.ManageGuild],
);

error(guild, e);
return e;
}

return (cache.apis.get(guild.id) ?? API).guilds
.createAutoModerationRule(guild.id, body, { reason })
.then((r) => new Classes.AutoModerationRule(guild.client, r, guild))
.catch((e) => {
error(guild, new Error((e as Discord.DiscordAPIError).message));
return e as Discord.DiscordAPIError;
});
};

/**
* Checks if the given guild member has the permission to create an auto-moderation rule.
* @param me - The guild member.
* @returns A boolean indicating whether the member can create an auto-moderation rule.
*/
export const canCreateAutoModerationRule = (me: Discord.GuildMember) =>
me.permissions.has(Discord.PermissionFlagsBits.ManageGuild);
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { API } from '../../../Client.js';
import cache from '../../cache.js';
import * as Classes from '../../../Other/classes.js';

import getBotMemberFromGuild from '../../getBotMemberFromGuild.js';
import requestHandlerError from '../../requestHandlerError.js';

/**
* Creates a new channel in the specified guild.
* @param guild The guild where the channel will be created.
Expand All @@ -15,11 +18,41 @@ export default async (
guild: Discord.Guild,
body: Discord.RESTPostAPIGuildChannelJSONBody,
reason?: string,
) =>
(cache.apis.get(guild.id) ?? API).guilds
) => {
if (!canCreateChannel(await getBotMemberFromGuild(guild), body)) {
const e = requestHandlerError(`Cannot create channel in ${guild.name} / ${guild.id}`, [
Discord.PermissionFlagsBits.ManageChannels,
]);

error(guild, e);
return e;
}

return (cache.apis.get(guild.id) ?? API).guilds
.createChannel(guild.id, body, { reason })
.then((c) => Classes.Channel(guild.client, c, guild))
.catch((e) => {
error(guild, new Error((e as Discord.DiscordAPIError).message));
return e as Discord.DiscordAPIError;
});
};

/**
* Checks if the given guild member has the necessary permissions
* to create a channel with the specified properties.
* @param me - The Discord guild member object representing the bot.
* @param body - The JSON body containing the properties of the channel to be created.
* @returns A boolean indicating whether the guild member can create the channel.
*/
export const canCreateChannel = (
me: Discord.GuildMember,
body: Discord.RESTPostAPIGuildChannelJSONBody,
) =>
me.permissions.has(Discord.PermissionFlagsBits.ManageChannels) &&
(body.permission_overwrites
? body.permission_overwrites.every(
(p) =>
me.permissions.has(Discord.PermissionFlagsBits.ManageRoles) &&
(p.id === me.id ? me.permissions.has(p.allow ? BigInt(p.allow) : 0n) : true),
)
: true);
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { API } from '../../../Client.js';
import cache from '../../cache.js';
import * as Classes from '../../../Other/classes.js';

import getBotMemberFromGuild from '../../getBotMemberFromGuild.js';
import requestHandlerError from '../../requestHandlerError.js';

/**
* Creates a new emoji for the specified guild.
* @param guild The guild to create the emoji in.
Expand All @@ -16,8 +19,17 @@ export default async (
guild: Discord.Guild,
body: Discord.RESTPostAPIGuildEmojiJSONBody,
reason?: string,
) =>
(cache.apis.get(guild.id) ?? API).guilds
) => {
if (!canCreateEmoji(await getBotMemberFromGuild(guild))) {
const e = requestHandlerError(`Cannot create emoji in ${guild.name} / ${guild.id}`, [
Discord.PermissionFlagsBits.ManageGuildExpressions,
]);

error(guild, e);
return e;
}

return (cache.apis.get(guild.id) ?? API).guilds
.createEmoji(
guild.id,
{
Expand All @@ -31,3 +43,14 @@ export default async (
error(guild, new Error((e as Discord.DiscordAPIError).message));
return e as Discord.DiscordAPIError;
});
};

// TODO: CreateGuildExpressions should be coming to D.js soon.
/**
* Checks if the given guild member has the permission to create an emoji.
* @param me - The guild member to check.
* @returns True if the guild member has the permission to create an emoji, false otherwise.
*/
export const canCreateEmoji = (me: Discord.GuildMember) =>
me.permissions.has(8796093022208n) ||
me.permissions.has(Discord.PermissionFlagsBits.ManageGuildExpressions);
Loading

0 comments on commit c0c311c

Please sign in to comment.