aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIRONM00N <64110067+IRONM00N@users.noreply.github.com>2021-12-29 22:12:02 -0500
committerIRONM00N <64110067+IRONM00N@users.noreply.github.com>2021-12-29 22:12:02 -0500
commita540b4083b7a5662ec49b7576b215fe5d3153358 (patch)
tree8383d3a1337eabfd69e30fb95687691b6e6cc7f7 /src
parent602329510e11165aef42b3c6071bb1118e4d95c3 (diff)
downloadtanzanite-a540b4083b7a5662ec49b7576b215fe5d3153358.tar.gz
tanzanite-a540b4083b7a5662ec49b7576b215fe5d3153358.tar.bz2
tanzanite-a540b4083b7a5662ec49b7576b215fe5d3153358.zip
block and unblock command
Diffstat (limited to 'src')
-rw-r--r--src/commands/moderation/_block.ts0
-rw-r--r--src/commands/moderation/_unblock.ts0
-rw-r--r--src/commands/moderation/block.ts122
-rw-r--r--src/commands/moderation/unblock.ts108
-rw-r--r--src/lib/extensions/discord.js/BushGuildMember.ts267
5 files changed, 470 insertions, 27 deletions
diff --git a/src/commands/moderation/_block.ts b/src/commands/moderation/_block.ts
deleted file mode 100644
index e69de29..0000000
--- a/src/commands/moderation/_block.ts
+++ /dev/null
diff --git a/src/commands/moderation/_unblock.ts b/src/commands/moderation/_unblock.ts
deleted file mode 100644
index e69de29..0000000
--- a/src/commands/moderation/_unblock.ts
+++ /dev/null
diff --git a/src/commands/moderation/block.ts b/src/commands/moderation/block.ts
new file mode 100644
index 0000000..371975b
--- /dev/null
+++ b/src/commands/moderation/block.ts
@@ -0,0 +1,122 @@
+import {
+ AllowedMentions,
+ BushCommand,
+ BushTextChannel,
+ BushThreadChannel,
+ Moderation,
+ type ArgType,
+ type BushMessage,
+ type BushSlashMessage,
+ type OptionalArgType
+} from '#lib';
+import assert from 'assert';
+
+export default class BlockCommand extends BushCommand {
+ public constructor() {
+ super('block', {
+ aliases: ['block'],
+ category: 'moderation',
+ description: 'Prevent a user from using a channel.',
+ usage: ['block <member> [reason] [duration]'],
+ examples: ['block IRONM00N 2h bad jokes'],
+ args: [
+ {
+ id: 'user',
+ description: 'The user to block.',
+ type: 'user',
+ prompt: 'What user would you like to block?',
+ retry: '{error} Choose a valid user to block.',
+ slashType: 'USER'
+ },
+ {
+ id: 'reason',
+ description: 'The reason and duration of the block.',
+ type: 'contentWithDuration',
+ match: 'rest',
+ prompt: 'Why should this user be blocked and for how long?',
+ retry: '{error} Choose a valid block reason and duration.',
+ optional: true,
+ slashType: 'STRING'
+ },
+ {
+ id: 'force',
+ description: 'Override permission checks.',
+ flag: '--force',
+ match: 'flag',
+ optional: true,
+ slashType: false,
+ only: 'text',
+ ownerOnly: true
+ }
+ ],
+ slash: true,
+ channel: 'guild',
+ clientPermissions: (m) => util.clientSendAndPermCheck(m, 'MANAGE_CHANNELS'),
+ userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES'])
+ });
+ }
+
+ public override async exec(
+ message: BushMessage | BushSlashMessage,
+ args: { user: ArgType<'user'>; reason: OptionalArgType<'contentWithDuration'> | string; force?: ArgType<'boolean'> }
+ ) {
+ assert(message.inGuild());
+ if (!(message.channel instanceof BushTextChannel || message.channel instanceof BushThreadChannel))
+ return message.util.send(`${util.emojis.error} This command can only be used in text and thread channels.`);
+
+ const reason = args.reason
+ ? typeof args.reason === 'string'
+ ? await util.arg.cast('contentWithDuration', message, args.reason)
+ : args.reason
+ : { duration: null, contentWithoutTime: '' };
+
+ if (reason.duration === null) reason.duration = 0;
+ const member = await message.guild!.members.fetch(args.user.id).catch(() => null);
+ if (!member)
+ return await message.util.reply(`${util.emojis.error} The user you selected is not in the server or is not a valid user.`);
+
+ assert(message.member);
+ const useForce = args.force && message.author.isOwner();
+ const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'block', true, useForce);
+
+ if (canModerateResponse !== true) {
+ return message.util.reply(canModerateResponse);
+ }
+
+ const time = reason
+ ? typeof reason === 'string'
+ ? ((await util.arg.cast('duration', message, reason)) as number)
+ : reason.duration
+ : undefined;
+
+ const parsedReason = reason?.contentWithoutTime ?? '';
+
+ const responseCode = await member.block({
+ reason: parsedReason,
+ moderator: message.member,
+ duration: time ?? 0,
+ channel: message.channel
+ });
+
+ const responseMessage = () => {
+ const victim = util.format.input(member.user.tag);
+ switch (responseCode) {
+ case 'missing permissions':
+ return `${util.emojis.error} Could not block ${victim} because I am missing the **Manage Channel** permission.`;
+ case 'invalid channel':
+ return `${util.emojis.error} Could not block ${victim}, you can only block users in text or thread channels.`;
+ case 'error blocking':
+ return `${util.emojis.error} An unknown error occurred while trying to block ${victim}.`;
+ case 'error creating modlog entry':
+ return `${util.emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
+ case 'error creating block entry':
+ return `${util.emojis.error} There was an error creating a punishment entry, please report this to my developers.`;
+ case 'failed to dm':
+ return `${util.emojis.warn} Blocked ${victim} however I could not send them a dm.`;
+ case 'success':
+ return `${util.emojis.success} Successfully blocked ${victim}.`;
+ }
+ };
+ return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
+ }
+}
diff --git a/src/commands/moderation/unblock.ts b/src/commands/moderation/unblock.ts
new file mode 100644
index 0000000..f9f069b
--- /dev/null
+++ b/src/commands/moderation/unblock.ts
@@ -0,0 +1,108 @@
+import {
+ AllowedMentions,
+ BushCommand,
+ BushTextChannel,
+ BushThreadChannel,
+ Moderation,
+ type ArgType,
+ type BushMessage,
+ type BushSlashMessage,
+ type OptionalArgType
+} from '#lib';
+import assert from 'assert';
+
+export default class UnblockCommand extends BushCommand {
+ public constructor() {
+ super('unblock', {
+ aliases: ['unblock'],
+ category: 'moderation',
+ description: 'Allows a user to use a channel.',
+ usage: ['unblock <member> [reason]'],
+ examples: ['unblock IRONM00N 2h bad jokes'],
+ args: [
+ {
+ id: 'user',
+ description: 'The user to unblock.',
+ type: 'user',
+ prompt: 'What user would you like to unblock?',
+ retry: '{error} Choose a valid user to unblock.',
+ slashType: 'USER'
+ },
+ {
+ id: 'reason',
+ description: 'The reason and duration of the unblock.',
+ type: 'string',
+ match: 'rest',
+ prompt: 'Why should this user be blocked and for how long?',
+ retry: '{error} Choose a valid block reason and duration.',
+ optional: true,
+ slashType: 'STRING'
+ },
+ {
+ id: 'force',
+ description: 'Override permission checks.',
+ flag: '--force',
+ match: 'flag',
+ optional: true,
+ slashType: false,
+ only: 'text',
+ ownerOnly: true
+ }
+ ],
+ slash: true,
+ channel: 'guild',
+ clientPermissions: (m) => util.clientSendAndPermCheck(m, 'MANAGE_CHANNELS'),
+ userPermissions: (m) => util.userGuildPermCheck(m, ['MANAGE_MESSAGES'])
+ });
+ }
+
+ public override async exec(
+ message: BushMessage | BushSlashMessage,
+ args: { user: ArgType<'user'>; reason: OptionalArgType<'string'>; force?: ArgType<'boolean'> }
+ ) {
+ assert(message.inGuild());
+ if (!(message.channel instanceof BushTextChannel || message.channel instanceof BushThreadChannel))
+ return message.util.send(`${util.emojis.error} This command can only be used in text and thread channels.`);
+
+ const member = await message.guild!.members.fetch(args.user.id).catch(() => null);
+ if (!member)
+ return await message.util.reply(`${util.emojis.error} The user you selected is not in the server or is not a valid user.`);
+
+ assert(message.member);
+ const useForce = args.force && message.author.isOwner();
+ const canModerateResponse = await Moderation.permissionCheck(message.member, member, 'unblock', true, useForce);
+
+ if (canModerateResponse !== true) {
+ return message.util.reply(canModerateResponse);
+ }
+
+ const parsedReason = args.reason ?? '';
+
+ const responseCode = await member.unblock({
+ reason: parsedReason,
+ moderator: message.member,
+ channel: message.channel
+ });
+
+ const responseMessage = () => {
+ const victim = util.format.input(member.user.tag);
+ switch (responseCode) {
+ case 'missing permissions':
+ return `${util.emojis.error} Could not unblock ${victim} because I am missing the **Manage Channel** permission.`;
+ case 'invalid channel':
+ return `${util.emojis.error} Could not unblock ${victim}, you can only unblock users in text or thread channels.`;
+ case 'error unblocking':
+ return `${util.emojis.error} An unknown error occurred while trying to unblock ${victim}.`;
+ case 'error creating modlog entry':
+ return `${util.emojis.error} There was an error creating a modlog entry, please report this to my developers.`;
+ case 'error removing block entry':
+ return `${util.emojis.error} There was an error creating a punishment entry, please report this to my developers.`;
+ case 'failed to dm':
+ return `${util.emojis.warn} Unblocked ${victim} however I could not send them a dm.`;
+ case 'success':
+ return `${util.emojis.success} Successfully unblocked ${victim}.`;
+ }
+ };
+ return await message.util.reply({ content: responseMessage(), allowedMentions: AllowedMentions.none() });
+ }
+}
diff --git a/src/lib/extensions/discord.js/BushGuildMember.ts b/src/lib/extensions/discord.js/BushGuildMember.ts
index 1908f12..ac8fb54 100644
--- a/src/lib/extensions/discord.js/BushGuildMember.ts
+++ b/src/lib/extensions/discord.js/BushGuildMember.ts
@@ -1,7 +1,19 @@
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { BushClientEvents, Moderation, ModLogType, type BushClient, type BushGuild, type BushRole, type BushUser } from '#lib';
+/* eslint-disable @typescript-eslint/no-unused-vars */
+import {
+ BushClientEvents,
+ BushGuildTextBasedChannel,
+ BushGuildTextChannelResolvable,
+ BushThreadChannelResolvable,
+ Moderation,
+ ModLogType,
+ type BushClient,
+ type BushGuild,
+ type BushRole,
+ type BushUser
+} from '#lib';
import { GuildMember, MessageEmbed, type Partialize, type Role } from 'discord.js';
import type { RawGuildMemberData } from 'discord.js/typings/rawDataTypes';
+/* eslint-enable @typescript-eslint/no-unused-vars */
/**
* Represents a member of a guild on Discord.
@@ -72,7 +84,7 @@ export class BushGuildMember extends GuildMember {
return { result: 'success', caseNum: result.caseNum };
})();
- if (!['error creating modlog entry'].includes(ret.result))
+ if (!(['error creating modlog entry'] as const).includes(ret.result))
client.emit('bushWarn', this, moderator, this.guild, options.reason ?? undefined, caseID!, dmSuccessEvent!);
return ret as { result: WarnResponse | null; caseNum: number | null };
}
@@ -123,7 +135,10 @@ export class BushGuildMember extends GuildMember {
return 'success';
})();
- if (!['error adding role', 'error creating modlog entry', 'error creating role entry'].includes(ret) && options.addToModlog)
+ if (
+ !(['error adding role', 'error creating modlog entry', 'error creating role entry'] as const).includes(ret) &&
+ options.addToModlog
+ )
client.emit(
'bushPunishRole',
this,
@@ -181,7 +196,10 @@ export class BushGuildMember extends GuildMember {
return 'success';
})();
- if (!['error removing role', 'error creating modlog entry', 'error removing role entry'].includes(ret) && options.addToModlog)
+ if (
+ !(['error removing role', 'error creating modlog entry', 'error removing role entry'] as const).includes(ret) &&
+ options.addToModlog
+ )
client.emit(
'bushPunishRoleRemove',
this,
@@ -280,7 +298,7 @@ export class BushGuildMember extends GuildMember {
return 'success';
})();
- if (!['error giving mute role', 'error creating modlog entry', 'error creating mute entry'].includes(ret))
+ if (!(['error giving mute role', 'error creating modlog entry', 'error creating mute entry'] as const).includes(ret))
client.emit(
'bushMute',
this,
@@ -302,7 +320,7 @@ export class BushGuildMember extends GuildMember {
* @emits {@link BushClientEvents.bushUnmute}
*/
public async unmute(options: BushPunishmentOptions): Promise<UnmuteResponse> {
- //checks
+ // checks
if (!this.guild.me!.permissions.has('MANAGE_ROLES')) return 'missing permissions';
const muteRoleID = await this.guild.getSetting('muteRole');
if (!muteRoleID) return 'no mute role';
@@ -315,7 +333,7 @@ export class BushGuildMember extends GuildMember {
const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!;
const ret = await (async () => {
- //remove role
+ // remove role
const muteSuccess = await this.roles
.remove(muteRole, `[Unmute] ${moderator.tag} | ${options.reason ?? 'No reason provided.'}`)
.catch(async (e) => {
@@ -324,7 +342,7 @@ export class BushGuildMember extends GuildMember {
});
if (!muteSuccess) return 'error removing mute role';
- //remove modlog entry
+ // add modlog entry
const { log: modlog } = await Moderation.createModLogEntry({
type: ModLogType.UNMUTE,
user: this,
@@ -346,7 +364,7 @@ export class BushGuildMember extends GuildMember {
if (!removePunishmentEntrySuccess) return 'error removing mute entry';
- //dm user
+ // dm user
const dmSuccess = await this.punishDM('unmuted', options.reason, undefined, false);
dmSuccessEvent = dmSuccess;
@@ -355,7 +373,7 @@ export class BushGuildMember extends GuildMember {
return 'success';
})();
- if (!['error removing mute role', 'error creating modlog entry', 'error removing mute entry'].includes(ret))
+ if (!(['error removing mute role', 'error creating modlog entry', 'error removing mute entry'] as const).includes(ret))
client.emit(
'bushUnmute',
this,
@@ -405,7 +423,7 @@ export class BushGuildMember extends GuildMember {
if (!dmSuccess) return 'failed to dm';
return 'success';
})();
- if (!['error kicking', 'error creating modlog entry'].includes(ret))
+ if (!(['error kicking', 'error creating modlog entry'] as const).includes(ret))
client.emit(
'bushKick',
this,
@@ -470,7 +488,7 @@ export class BushGuildMember extends GuildMember {
if (!dmSuccess) return 'failed to dm';
return 'success';
})();
- if (!['error banning', 'error creating modlog entry', 'error creating ban entry'].includes(ret))
+ if (!(['error banning', 'error creating modlog entry', 'error creating ban entry'] as const).includes(ret))
client.emit(
'bushBan',
this,
@@ -486,6 +504,161 @@ export class BushGuildMember extends GuildMember {
}
/**
+ * Prevents a user from speaking in a channel.
+ * @param options Options for blocking the user.
+ */
+ public async block(options: BlockOptions): Promise<BlockResponse> {
+ const _channel = this.guild.channels.resolve(options.channel);
+ if (!_channel || (!_channel.isText() && !_channel.isThread())) return 'invalid channel';
+ const channel = _channel as BushGuildTextBasedChannel;
+
+ // checks
+ if (!channel.permissionsFor(this.guild.me!)!.has('MANAGE_CHANNELS')) return 'missing permissions';
+
+ let caseID: string | undefined = undefined;
+ let dmSuccessEvent: boolean | undefined = undefined;
+ const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!;
+
+ const ret = await (async () => {
+ // change channel permissions
+ const channelToUse = channel.isThread() ? channel.parent! : channel;
+ const perm = channel.isThread() ? { SEND_MESSAGES_IN_THREADS: false } : { SEND_MESSAGES: false };
+ const blockSuccess = await channelToUse.permissionOverwrites
+ .edit(this, perm, { reason: `[Block] ${moderator.tag} | ${options.reason ?? 'No reason provided.'}` })
+ .catch(() => false);
+ if (!blockSuccess) return 'error blocking';
+
+ // add modlog entry
+ const { log: modlog } = await Moderation.createModLogEntry({
+ type: options.duration ? ModLogType.TEMP_CHANNEL_BLOCK : ModLogType.PERM_CHANNEL_BLOCK,
+ user: this,
+ moderator: moderator.id,
+ reason: options.reason,
+ guild: this.guild,
+ evidence: options.evidence
+ });
+ if (!modlog) return 'error creating modlog entry';
+ caseID = modlog.id;
+
+ // add punishment entry so they can be unblocked later
+ const punishmentEntrySuccess = await Moderation.createPunishmentEntry({
+ type: 'block',
+ user: this,
+ guild: this.guild,
+ duration: options.duration,
+ modlog: modlog.id,
+ extraInfo: channel.id
+ });
+ if (!punishmentEntrySuccess) return 'error creating block entry';
+
+ // dm user
+ const dmSuccess = await this.send({
+ content: `You have been blocked from <#${channel.id}> in **${this.guild.name}** ${
+ options.duration !== null && options.duration !== undefined
+ ? options.duration
+ ? `for ${util.humanizeDuration(options.duration)} `
+ : 'permanently '
+ : ''
+ }for **${options.reason?.trim() ?? 'No reason provided'}**.`
+ }).catch(() => false);
+ dmSuccessEvent = !!dmSuccess;
+
+ if (!dmSuccess) return 'failed to dm';
+
+ return 'success';
+ })();
+
+ if (!(['error creating modlog entry', 'error creating block entry', 'error blocking'] as const).includes(ret))
+ client.emit(
+ 'bushBlock',
+ this,
+ moderator,
+ this.guild,
+ options.reason ?? undefined,
+ caseID!,
+ options.duration ?? 0,
+ dmSuccessEvent!,
+ channel,
+ options.evidence
+ );
+ return ret;
+ }
+
+ /**
+ * Allows a user to speak in a channel.
+ * @param options Options for unblocking the user.
+ */
+ public async unblock(options: UnblockOptions): Promise<UnblockResponse> {
+ const _channel = this.guild.channels.resolve(options.channel);
+ if (!_channel || (!_channel.isText() && !_channel.isThread())) return 'invalid channel';
+ const channel = _channel as BushGuildTextBasedChannel;
+
+ // checks
+ if (!channel.permissionsFor(this.guild.me!)!.has('MANAGE_CHANNELS')) return 'missing permissions';
+
+ let caseID: string | undefined = undefined;
+ let dmSuccessEvent: boolean | undefined = undefined;
+ const moderator = (await util.resolveNonCachedUser(options.moderator ?? this.guild.me))!;
+
+ const ret = await (async () => {
+ // change channel permissions
+ const channelToUse = channel.isThread() ? channel.parent! : channel;
+ const perm = channel.isThread() ? { SEND_MESSAGES_IN_THREADS: null } : { SEND_MESSAGES: null };
+ const blockSuccess = await channelToUse.permissionOverwrites
+ .edit(this, perm, { reason: `[Unblock] ${moderator.tag} | ${options.reason ?? 'No reason provided.'}` })
+ .catch(() => false);
+ if (!blockSuccess) return 'error unblocking';
+
+ // add modlog entry
+ const { log: modlog } = await Moderation.createModLogEntry({
+ type: ModLogType.CHANNEL_UNBLOCK,
+ user: this,
+ moderator: moderator.id,
+ reason: options.reason,
+ guild: this.guild,
+ evidence: options.evidence
+ });
+ if (!modlog) return 'error creating modlog entry';
+ caseID = modlog.id;
+
+ // remove punishment entry
+ const punishmentEntrySuccess = await Moderation.removePunishmentEntry({
+ type: 'block',
+ user: this,
+ guild: this.guild,
+ extraInfo: channel.id
+ });
+ if (!punishmentEntrySuccess) return 'error removing block entry';
+
+ // dm user
+ const dmSuccess = await this.send({
+ content: `You have been unblocked from <#${channel.id}> in **${this.guild.name}** for **${
+ options.reason?.trim() ?? 'No reason provided'
+ }**.`
+ }).catch(() => false);
+ dmSuccessEvent = !!dmSuccess;
+
+ if (!dmSuccess) return 'failed to dm';
+
+ return 'success';
+ })();
+
+ if (!(['error creating modlog entry', 'error removing block entry', 'error unblocking'] as const).includes(ret))
+ client.emit(
+ 'bushUnblock',
+ this,
+ moderator,
+ this.guild,
+ options.reason ?? undefined,
+ caseID!,
+ dmSuccessEvent!,
+ channel,
+ options.evidence
+ );
+ return ret;
+ }
+
+ /**
* Whether or not the user is an owner of the bot.
*/
public isOwner(): boolean {
@@ -503,7 +676,7 @@ export class BushGuildMember extends GuildMember {
/**
* Options for punishing a user.
*/
-interface BushPunishmentOptions {
+export interface BushPunishmentOptions {
/**
* The reason for the punishment.
*/
@@ -523,7 +696,7 @@ interface BushPunishmentOptions {
/**
* Punishment options for punishments that can be temporary.
*/
-interface BushTimedPunishmentOptions extends BushPunishmentOptions {
+export interface BushTimedPunishmentOptions extends BushPunishmentOptions {
/**
* The duration of the punishment.
*/
@@ -533,7 +706,7 @@ interface BushTimedPunishmentOptions extends BushPunishmentOptions {
/**
* Options for a role add punishment.
*/
-interface AddRoleOptions extends BushTimedPunishmentOptions {
+export interface AddRoleOptions extends BushTimedPunishmentOptions {
/**
* The role to add to the user.
*/
@@ -548,7 +721,7 @@ interface AddRoleOptions extends BushTimedPunishmentOptions {
/**
* Options for a role remove punishment.
*/
-interface RemoveRoleOptions extends BushTimedPunishmentOptions {
+export interface RemoveRoleOptions extends BushTimedPunishmentOptions {
/**
* The role to remove from the user.
*/
@@ -563,24 +736,44 @@ interface RemoveRoleOptions extends BushTimedPunishmentOptions {
/**
* Options for banning a user.
*/
-interface BushBanOptions extends BushTimedPunishmentOptions {
+export interface BushBanOptions extends BushTimedPunishmentOptions {
/**
* The number of days to delete the user's messages for.
*/
deleteDays?: number;
}
-type PunishmentResponse = 'success' | 'error creating modlog entry' | 'failed to dm';
+/**
+ * Options for blocking a user from a channel.
+ */
+export interface BlockOptions extends BushTimedPunishmentOptions {
+ /**
+ * The channel to block the user from.
+ */
+ channel: BushGuildTextChannelResolvable | BushThreadChannelResolvable;
+}
+
+/**
+ * Options for unblocking a user from a channel.
+ */
+export interface UnblockOptions extends BushPunishmentOptions {
+ /**
+ * The channel to unblock the user from.
+ */
+ channel: BushGuildTextChannelResolvable | BushThreadChannelResolvable;
+}
+
+export type PunishmentResponse = 'success' | 'error creating modlog entry' | 'failed to dm';
/**
* Response returned when warning a user.
*/
-type WarnResponse = PunishmentResponse;
+export type WarnResponse = PunishmentResponse;
/**
* Response returned when adding a role to a user.
*/
-type AddRoleResponse =
+export type AddRoleResponse =
| PunishmentResponse
| 'user hierarchy'
| 'role managed'
@@ -591,7 +784,7 @@ type AddRoleResponse =
/**
* Response returned when removing a role from a user.
*/
-type RemoveRoleResponse =
+export type RemoveRoleResponse =
| PunishmentResponse
| 'user hierarchy'
| 'role managed'
@@ -602,7 +795,7 @@ type RemoveRoleResponse =
/**
* Response returned when muting a user.
*/
-type MuteResponse =
+export type MuteResponse =
| PunishmentResponse
| 'missing permissions'
| 'no mute role'
@@ -614,7 +807,7 @@ type MuteResponse =
/**
* Response returned when unmuting a user.
*/
-type UnmuteResponse =
+export type UnmuteResponse =
| PunishmentResponse
| 'missing permissions'
| 'no mute role'
@@ -626,17 +819,37 @@ type UnmuteResponse =
/**
* Response returned when kicking a user.
*/
-type KickResponse = PunishmentResponse | 'missing permissions' | 'error kicking';
+export type KickResponse = PunishmentResponse | 'missing permissions' | 'error kicking';
/**
* Response returned when banning a user.
*/
-type BanResponse = PunishmentResponse | 'missing permissions' | 'error creating ban entry' | 'error banning';
+export type BanResponse = PunishmentResponse | 'missing permissions' | 'error creating ban entry' | 'error banning';
+
+/**
+ * Response returned when blocking a user.
+ */
+export type BlockResponse =
+ | PunishmentResponse
+ | 'invalid channel'
+ | 'error creating block entry'
+ | 'missing permissions'
+ | 'error blocking';
+
+/**
+ * Response returned when unblocking a user.
+ */
+export type UnblockResponse =
+ | PunishmentResponse
+ | 'invalid channel'
+ | 'error removing block entry'
+ | 'missing permissions'
+ | 'error unblocking';
export type PartialBushGuildMember = Partialize<
BushGuildMember,
'joinedAt' | 'joinedTimestamp',
- 'warn' | 'addRole' | 'removeRole' | 'mute' | 'unmute' | 'bushKick' | 'bushBan' | 'isOwner' | 'isSuperUser'
+ 'warn' | 'addRole' | 'removeRole' | 'mute' | 'unmute' | 'bushKick' | 'bushBan' | 'isOwner' | 'isSuperUser' | 'block'
>;
/**