Check for channel type properly
This commit is contained in:
parent
c1fee71211
commit
6fa715fb8b
@ -8,7 +8,6 @@ import {
|
|||||||
GuildMember,
|
GuildMember,
|
||||||
Role,
|
Role,
|
||||||
BaseChannel,
|
BaseChannel,
|
||||||
TextChannel,
|
|
||||||
PermissionsString,
|
PermissionsString,
|
||||||
Channel,
|
Channel,
|
||||||
APIEmbed,
|
APIEmbed,
|
||||||
@ -20,7 +19,8 @@ import {
|
|||||||
ThreadChannel,
|
ThreadChannel,
|
||||||
APIEmbedField,
|
APIEmbedField,
|
||||||
VoiceState,
|
VoiceState,
|
||||||
Invite
|
Invite,
|
||||||
|
GuildTextBasedChannel,
|
||||||
} from 'discord.js';
|
} from 'discord.js';
|
||||||
import { InvokerWrapper, MemberWrapper, UserWrapper } from '../src/client/components/wrappers/index.js';
|
import { InvokerWrapper, MemberWrapper, UserWrapper } from '../src/client/components/wrappers/index.js';
|
||||||
import GuildWrapper from '../src/client/components/wrappers/GuildWrapper.js';
|
import GuildWrapper from '../src/client/components/wrappers/GuildWrapper.js';
|
||||||
@ -384,9 +384,9 @@ export type BaseInfractionData = {
|
|||||||
arguments?: InfractionArguments,
|
arguments?: InfractionArguments,
|
||||||
targetType?: InfractionTargetType,
|
targetType?: InfractionTargetType,
|
||||||
guild: GuildWrapper,
|
guild: GuildWrapper,
|
||||||
channel?: TextChannel,
|
channel?: GuildTextBasedChannel,
|
||||||
invoker?: InvokerWrapper | null,
|
invoker?: InvokerWrapper | null,
|
||||||
target?: MemberWrapper | UserWrapper | TextChannel,
|
target?: MemberWrapper | UserWrapper | GuildTextBasedChannel,
|
||||||
executor?: MemberWrapper | UserWrapper
|
executor?: MemberWrapper | UserWrapper
|
||||||
duration?: number | null,
|
duration?: number | null,
|
||||||
reason?: string,
|
reason?: string,
|
||||||
|
8
@types/Moderation.d.ts
vendored
8
@types/Moderation.d.ts
vendored
@ -1,9 +1,9 @@
|
|||||||
import { GuildBasedChannel, Message, TextChannel } from 'discord.js';
|
import { GuildBasedChannel, Message } from 'discord.js';
|
||||||
import { GuildWrapper, InvokerWrapper, MemberWrapper, UserWrapper } from '../src/client/components/wrappers/index.ts';
|
import { GuildWrapper, InvokerWrapper, MemberWrapper, UserWrapper } from '../src/client/components/wrappers/index.ts';
|
||||||
import { CommandOption, Infraction } from '../src/client/interfaces/index.ts';
|
import { CommandOption, Infraction } from '../src/client/interfaces/index.ts';
|
||||||
import { FormatParams, InfractionType } from './Client.ts';
|
import { FormatParams, InfractionType } from './Client.ts';
|
||||||
|
|
||||||
export type ModerationTarget = UserWrapper | MemberWrapper | TextChannel
|
export type ModerationTarget = UserWrapper | MemberWrapper | GuildTextBasedChannel
|
||||||
export type ModerationTargets = ModerationTarget[]
|
export type ModerationTargets = ModerationTarget[]
|
||||||
|
|
||||||
export type InfractionHandlerOptions = {
|
export type InfractionHandlerOptions = {
|
||||||
@ -14,7 +14,7 @@ export type InfractionHandlerOptions = {
|
|||||||
|
|
||||||
export type HandleAutomodOptions = {
|
export type HandleAutomodOptions = {
|
||||||
prune: boolean,
|
prune: boolean,
|
||||||
channel: TextChannel
|
channel: GuildTextBasedChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HandleTargetData = {
|
export type HandleTargetData = {
|
||||||
@ -25,7 +25,7 @@ export type HandleTargetData = {
|
|||||||
expiration?: number | null,
|
expiration?: number | null,
|
||||||
invoker?: InvokerWrapper,
|
invoker?: InvokerWrapper,
|
||||||
arguments?: { [key: string]: CommandOption | undefined },
|
arguments?: { [key: string]: CommandOption | undefined },
|
||||||
channel: TextChannel,
|
channel: GuildTextBasedChannel,
|
||||||
executor: MemberWrapper,
|
executor: MemberWrapper,
|
||||||
duration?: number | null,
|
duration?: number | null,
|
||||||
data: object,
|
data: object,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { inspect } from 'node:util';
|
import { inspect } from 'node:util';
|
||||||
|
|
||||||
import { stripIndents } from 'common-tags';
|
import { stripIndents } from 'common-tags';
|
||||||
import { Collection, GuildTextBasedChannel, Message, TextChannel } from 'discord.js';
|
import { Collection, GuildTextBasedChannel, Message } from 'discord.js';
|
||||||
import { LoggerClient } from '@navy.gif/logger';
|
import { LoggerClient } from '@navy.gif/logger';
|
||||||
|
|
||||||
import { DiscordStruct, InfractionJSON, InfractionType, ModerationCallback } from '../../../@types/Client.js';
|
import { DiscordStruct, InfractionJSON, InfractionType, ModerationCallback } from '../../../@types/Client.js';
|
||||||
@ -172,7 +172,7 @@ class ModerationManager implements Initialisable
|
|||||||
if (!executor)
|
if (!executor)
|
||||||
throw new Error('Missing executor');
|
throw new Error('Missing executor');
|
||||||
|
|
||||||
if (!(invoker.channel instanceof TextChannel))
|
if (!invoker.channel?.isTextBased())
|
||||||
throw new Error('Invalid channel');
|
throw new Error('Invalid channel');
|
||||||
|
|
||||||
const responses = [];
|
const responses = [];
|
||||||
@ -181,7 +181,7 @@ class ModerationManager implements Initialisable
|
|||||||
const response = await this._handleTarget(Infraction, target, {
|
const response = await this._handleTarget(Infraction, target, {
|
||||||
invoker,
|
invoker,
|
||||||
guild: invoker.guild!,
|
guild: invoker.guild!,
|
||||||
channel: invoker.channel!,
|
channel: invoker.channel,
|
||||||
executor,
|
executor,
|
||||||
arguments: args,
|
arguments: args,
|
||||||
points: args.points?.asNumber,
|
points: args.points?.asNumber,
|
||||||
@ -338,7 +338,11 @@ class ModerationManager implements Initialisable
|
|||||||
* @memberof ModerationManager
|
* @memberof ModerationManager
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line max-lines-per-function
|
// eslint-disable-next-line max-lines-per-function
|
||||||
async _handleTarget (Infraction: typeof InfractionClass, target: UserWrapper | MemberWrapper | TextChannel, info: HandleTargetData)
|
async _handleTarget (
|
||||||
|
Infraction: typeof InfractionClass,
|
||||||
|
target: UserWrapper | MemberWrapper | GuildTextBasedChannel,
|
||||||
|
info: HandleTargetData
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// wrapper: guildWrapper
|
// wrapper: guildWrapper
|
||||||
const { reason, force, guild } = info;
|
const { reason, force, guild } = info;
|
||||||
@ -542,7 +546,7 @@ class ModerationManager implements Initialisable
|
|||||||
else if (i.targetType === 'CHANNEL')
|
else if (i.targetType === 'CHANNEL')
|
||||||
{
|
{
|
||||||
target = guild.channels.resolve(i.target!);
|
target = guild.channels.resolve(i.target!);
|
||||||
if (!(target instanceof TextChannel))
|
if (!target?.isTextBased())
|
||||||
throw new Error('Invalid channel');
|
throw new Error('Invalid channel');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,7 +554,7 @@ class ModerationManager implements Initialisable
|
|||||||
{
|
{
|
||||||
const executor = await guild.memberWrapper(i.executor!).catch(() => null) ?? await guild.memberWrapper(guild.me!);
|
const executor = await guild.memberWrapper(i.executor!).catch(() => null) ?? await guild.memberWrapper(guild.me!);
|
||||||
const channel = guild.channels.resolve(i.channel!);
|
const channel = guild.channels.resolve(i.channel!);
|
||||||
if (!(channel instanceof TextChannel))
|
if (!channel?.isTextBased())
|
||||||
throw new Error('Bad channel');
|
throw new Error('Bad channel');
|
||||||
if (!executor)
|
if (!executor)
|
||||||
throw new Error('Missing executor');
|
throw new Error('Missing executor');
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// const { TextChannel, Message } = require('discord.js');
|
// const { TextChannel, Message } = require('discord.js');
|
||||||
|
|
||||||
import { Message, MessageCreateOptions, TextChannel } from 'discord.js';
|
import { GuildTextBasedChannel, Message, MessageCreateOptions, TextChannel } from 'discord.js';
|
||||||
import DiscordClient from '../DiscordClient.js';
|
import DiscordClient from '../DiscordClient.js';
|
||||||
|
|
||||||
type QueueEntry = {
|
type QueueEntry = {
|
||||||
@ -58,11 +58,11 @@ class RateLimiter
|
|||||||
* @returns {Promise<Boolean>}
|
* @returns {Promise<Boolean>}
|
||||||
* @memberof RateLimiter
|
* @memberof RateLimiter
|
||||||
*/
|
*/
|
||||||
queueDelete (channel: TextChannel, message: Message)
|
queueDelete (channel: GuildTextBasedChannel, message: Message)
|
||||||
{
|
{
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
{
|
{
|
||||||
if (!channel || !(channel instanceof TextChannel))
|
if (!channel || !(channel.isTextBased()))
|
||||||
reject(new Error('Missing channel'));
|
reject(new Error('Missing channel'));
|
||||||
if (!message || !(message instanceof Message))
|
if (!message || !(message instanceof Message))
|
||||||
reject(new Error('Missing message'));
|
reject(new Error('Missing message'));
|
||||||
@ -78,7 +78,7 @@ class RateLimiter
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async #delete (channel: TextChannel)
|
async #delete (channel: GuildTextBasedChannel)
|
||||||
{
|
{
|
||||||
if (!this.#deleteQueue[channel.id] || !this.#deleteQueue[channel.id].length)
|
if (!this.#deleteQueue[channel.id] || !this.#deleteQueue[channel.id].length)
|
||||||
return;
|
return;
|
||||||
@ -142,11 +142,11 @@ class RateLimiter
|
|||||||
* @returns {Promise<Message>} Resolves when the message is sent, rejects if sending fails
|
* @returns {Promise<Message>} Resolves when the message is sent, rejects if sending fails
|
||||||
* @memberof RateLimiter
|
* @memberof RateLimiter
|
||||||
*/
|
*/
|
||||||
queueSend (channel: TextChannel, message: string)
|
queueSend (channel: GuildTextBasedChannel, message: string)
|
||||||
{
|
{
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
{
|
{
|
||||||
if (!channel || !(channel instanceof TextChannel))
|
if (!channel?.isTextBased())
|
||||||
reject(new Error('Missing channel.'));
|
reject(new Error('Missing channel.'));
|
||||||
if (!message)
|
if (!message)
|
||||||
reject(new Error('Missing message.'));
|
reject(new Error('Missing message.'));
|
||||||
@ -167,7 +167,7 @@ class RateLimiter
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async #send (channel: TextChannel)
|
async #send (channel: GuildTextBasedChannel)
|
||||||
{
|
{
|
||||||
if (!this.#sendQueue[channel.id] || !this.#sendQueue[channel.id].length)
|
if (!this.#sendQueue[channel.id] || !this.#sendQueue[channel.id].length)
|
||||||
return;
|
return;
|
||||||
@ -231,7 +231,7 @@ class RateLimiter
|
|||||||
{
|
{
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
{
|
{
|
||||||
if (!channel || !(channel instanceof TextChannel))
|
if (!channel?.isTextBased())
|
||||||
reject(new Error('Missing channel'));
|
reject(new Error('Missing channel'));
|
||||||
if (!this.#client.user || !channel.permissionsFor(this.#client.user)?.has('SendMessages'))
|
if (!this.#client.user || !channel.permissionsFor(this.#client.user)?.has('SendMessages'))
|
||||||
reject(new Error('Missing permission SendMessages'));
|
reject(new Error('Missing permission SendMessages'));
|
||||||
|
@ -418,7 +418,7 @@ class Resolver
|
|||||||
{
|
{
|
||||||
const match = resolveable.toString().match(id) || [];
|
const match = resolveable.toString().match(id) || [];
|
||||||
const [ , ch ] = match;
|
const [ , ch ] = match;
|
||||||
const channel = await CM.fetch(ch).catch(null);
|
const channel = await CM.fetch(ch).catch(() => null);
|
||||||
if (channel && filter(channel))
|
if (channel && filter(channel))
|
||||||
resolved.push(channel as unknown as T);
|
resolved.push(channel as unknown as T);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import InvokerWrapper from '../../wrappers/InvokerWrapper.js';
|
|||||||
import { CommandOptionType, CommandParams } from '../../../../../@types/Client.js';
|
import { CommandOptionType, CommandParams } from '../../../../../@types/Client.js';
|
||||||
import Util from '../../../../utilities/Util.js';
|
import Util from '../../../../utilities/Util.js';
|
||||||
import { EmbedDefaultColor, PollReactions } from '../../../../constants/Constants.js';
|
import { EmbedDefaultColor, PollReactions } from '../../../../constants/Constants.js';
|
||||||
import { TextChannel } from 'discord.js';
|
import { GuildTextBasedChannel, TextChannel } from 'discord.js';
|
||||||
import { CallbackData, PollData } from '../../../../../@types/Guild.js';
|
import { CallbackData, PollData } from '../../../../../@types/Guild.js';
|
||||||
|
|
||||||
class PollCommand extends SlashCommand
|
class PollCommand extends SlashCommand
|
||||||
@ -54,7 +54,7 @@ class PollCommand extends SlashCommand
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute (invoker: InvokerWrapper, { choices, channel, duration, multichoice, message }: CommandParams)
|
async execute (invoker: InvokerWrapper<true>, { choices, channel, duration, multichoice, message }: CommandParams)
|
||||||
{
|
{
|
||||||
const { subcommand, author } = invoker;
|
const { subcommand, author } = invoker;
|
||||||
const guild = invoker.guild!;
|
const guild = invoker.guild!;
|
||||||
@ -64,8 +64,8 @@ class PollCommand extends SlashCommand
|
|||||||
{
|
{
|
||||||
// await invoker.deferReply();
|
// await invoker.deferReply();
|
||||||
const questions = [];
|
const questions = [];
|
||||||
const _channel = channel?.asChannel || invoker.channel;
|
const _channel = (channel?.asChannel || invoker.channel) as GuildTextBasedChannel;
|
||||||
if (!(_channel instanceof TextChannel))
|
if (!_channel?.isTextBased())
|
||||||
throw new CommandError(invoker, { index: 'ERR_INVALID_CHANNEL_TYPE' });
|
throw new CommandError(invoker, { index: 'ERR_INVALID_CHANNEL_TYPE' });
|
||||||
const botMissing = _channel.permissionsFor(this.client.user!)?.missing([ 'SendMessages', 'EmbedLinks' ]);
|
const botMissing = _channel.permissionsFor(this.client.user!)?.missing([ 'SendMessages', 'EmbedLinks' ]);
|
||||||
const userMissing = _channel.permissionsFor(member).missing([ 'SendMessages' ]);
|
const userMissing = _channel.permissionsFor(member).missing([ 'SendMessages' ]);
|
||||||
|
@ -3,7 +3,7 @@ import DiscordClient from '../../../DiscordClient.js';
|
|||||||
import InvokerWrapper from '../../wrappers/InvokerWrapper.js';
|
import InvokerWrapper from '../../wrappers/InvokerWrapper.js';
|
||||||
import { CommandOptionType, CommandParams } from '../../../../../@types/Client.js';
|
import { CommandOptionType, CommandParams } from '../../../../../@types/Client.js';
|
||||||
import Util from '../../../../utilities/Util.js';
|
import Util from '../../../../utilities/Util.js';
|
||||||
import { APIEmbed, TextChannel } from 'discord.js';
|
import { APIEmbed } from 'discord.js';
|
||||||
import { CallbackData, ReminderData } from '../../../../../@types/Guild.js';
|
import { CallbackData, ReminderData } from '../../../../../@types/Guild.js';
|
||||||
import GuildWrapper from '../../wrappers/GuildWrapper.js';
|
import GuildWrapper from '../../wrappers/GuildWrapper.js';
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ class RemindCommand extends SlashCommand
|
|||||||
{
|
{
|
||||||
const { author, channel, guild, member } = invoker;
|
const { author, channel, guild, member } = invoker;
|
||||||
const subcommand = invoker.subcommand!.name;
|
const subcommand = invoker.subcommand!.name;
|
||||||
if (!channel || !(channel instanceof TextChannel))
|
if (!channel?.isTextBased())
|
||||||
throw new Error('Missing channel?');
|
throw new Error('Missing channel?');
|
||||||
|
|
||||||
if (subcommand === 'create')
|
if (subcommand === 'create')
|
||||||
|
@ -77,7 +77,7 @@ class SelfroleSetting extends Setting
|
|||||||
// old channel for deleting old message if one exists
|
// old channel for deleting old message if one exists
|
||||||
const oldChannel = await guild.resolveChannel<TextChannel>(setting.channel);
|
const oldChannel = await guild.resolveChannel<TextChannel>(setting.channel);
|
||||||
const newChannel = channel?.asChannel || oldChannel;
|
const newChannel = channel?.asChannel || oldChannel;
|
||||||
if (!(newChannel instanceof TextChannel))
|
if (!newChannel?.isTextBased())
|
||||||
throw new CommandError(invoker, { index: 'ERR_INVALID_CHANNEL_TYPE' });
|
throw new CommandError(invoker, { index: 'ERR_INVALID_CHANNEL_TYPE' });
|
||||||
if (channel)
|
if (channel)
|
||||||
setting.channel = channel.asChannel.id; // Set the new channel if one is given
|
setting.channel = channel.asChannel.id; // Set the new channel if one is given
|
||||||
|
@ -4,10 +4,8 @@ import DiscordClient from '../DiscordClient.js';
|
|||||||
import { LoggerClient } from '@navy.gif/logger';
|
import { LoggerClient } from '@navy.gif/logger';
|
||||||
import { InfractionTargetType, InfractionType } from '../../../@types/Client.js';
|
import { InfractionTargetType, InfractionType } from '../../../@types/Client.js';
|
||||||
import { PruneData } from '../../../@types/Infractions.js';
|
import { PruneData } from '../../../@types/Infractions.js';
|
||||||
import { DMChannel, GuildTextBasedChannel, Message, PartialDMChannel, Snowflake, TextBasedChannel } from 'discord.js';
|
import { BaseChannel, DMChannel, GuildTextBasedChannel, Message, PartialDMChannel, Snowflake, TextBasedChannel } from 'discord.js';
|
||||||
import { Collection } from '@discordjs/collection';
|
import { Collection } from '@discordjs/collection';
|
||||||
import pkg from 'discord.js';
|
|
||||||
const { TextBasedChannelMixin } = pkg;
|
|
||||||
|
|
||||||
|
|
||||||
const Arguments = [ 'users', 'bots', 'humans', 'contains', 'startswith', 'endswith', 'emojis', 'reactions', 'text', 'invites', 'links', 'emojis', 'reactions', 'images', 'attachments' ];
|
const Arguments = [ 'users', 'bots', 'humans', 'contains', 'startswith', 'endswith', 'emojis', 'reactions', 'text', 'invites', 'links', 'emojis', 'reactions', 'images', 'attachments' ];
|
||||||
@ -48,7 +46,7 @@ class PruneInfraction extends Infraction
|
|||||||
hyperlink: opts.hyperlink
|
hyperlink: opts.hyperlink
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!(this.target instanceof TextBasedChannelMixin))
|
if (this.target instanceof BaseChannel && !this.target.isTextBased())
|
||||||
throw new Error('Invalid channel type given');
|
throw new Error('Invalid channel type given');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { inspect } from 'node:util';
|
import { inspect } from 'node:util';
|
||||||
|
|
||||||
import { LoggerClient } from '@navy.gif/logger';
|
import { LoggerClient } from '@navy.gif/logger';
|
||||||
import { APIEmbed, GuildChannel, Message, Snowflake, TextChannel } from 'discord.js';
|
import { APIEmbed, GuildChannel, GuildTextBasedChannel, Message, Snowflake, TextChannel } from 'discord.js';
|
||||||
import { ObjectId, WithId } from 'mongodb';
|
import { ObjectId, WithId } from 'mongodb';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -60,14 +60,14 @@ class Infraction
|
|||||||
#guild: GuildWrapper;
|
#guild: GuildWrapper;
|
||||||
|
|
||||||
#channelId: Snowflake | null;
|
#channelId: Snowflake | null;
|
||||||
#channel: TextChannel | null;
|
#channel: GuildTextBasedChannel | null;
|
||||||
|
|
||||||
#messageId: Snowflake | null;
|
#messageId: Snowflake | null;
|
||||||
#message: InvokerWrapper | null;
|
#message: InvokerWrapper | null;
|
||||||
|
|
||||||
#targetType: InfractionTargetType;
|
#targetType: InfractionTargetType;
|
||||||
#targetId: Snowflake | null;
|
#targetId: Snowflake | null;
|
||||||
#target: UserWrapper | MemberWrapper | TextChannel | null;
|
#target: UserWrapper | MemberWrapper | GuildTextBasedChannel | null;
|
||||||
|
|
||||||
#executorId: Snowflake | null;
|
#executorId: Snowflake | null;
|
||||||
#executor: UserWrapper | null;
|
#executor: UserWrapper | null;
|
||||||
|
@ -12,6 +12,7 @@ type CommandUsageLimits = {
|
|||||||
usages: number,
|
usages: number,
|
||||||
duration: number
|
duration: number
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandThrottle = {
|
type CommandThrottle = {
|
||||||
usages: number,
|
usages: number,
|
||||||
start: number,
|
start: number,
|
||||||
|
Loading…
Reference in New Issue
Block a user