Skip to content

Commit cbf5d4e

Browse files
authored
refactor: switch to sapphire/*@v2 and discord.js@dev (#227)
Added `CommandPreConditions.GuildNewsThreadOnly`. Added `CommandPreConditions.GuildPrivateThreadOnly`. Added `CommandPreConditions.GuildPublicThreadOnly`. Added `CommandPreConditions.GuildThreadOnly`. Added `Identifiers.PreconditionGuildNewsThreadOnly`. Added `Identifiers.PreconditionGuildPrivateThreadOnly`. Added `Identifiers.PreconditionGuildPublicThreadOnly`. Added `Identifiers.PreconditionThreadOnly`. Added `Preconditions.GuildNewsThreadOnly`. Added `Preconditions.GuildPrivateThreadOnly`. Added `Preconditions.GuildPublicThreadOnly`. Added `Preconditions.GuildThreadOnly`. Added the `guildNewsThreadChannel` argument type. Added the `guildPrivateThreadChannel` argument type. Added the `guildPublicThreadChannel` argument type. Added the `guildStageVoiceChannel` argument type. Added the `guildThreadChannel` argument type. Changed `GuildNewsOnly` precondition to allow `GUILD_NEWS_THREAD`. Changed `GuildTextOnly` precondition to allow `GUILD_PUBLIC_THREAD` and `GUILD_PRIVATE_THREAD`. Fixed `CoreMessage` event not filtering webhooks in v13. Fixed `CoreMessageParser` event not checking for DM channel correctly in v13. Updated `Cooldown` precondition to use `@sapphire/[email protected]`. Updated `Permissions` precondition to support `USE_APPLICATION_COMMANDS`. Updated `Permissions` precondition to support `USE_PRIVATE_THREADS`. Updated `Permissions` precondition to support `USE_PUBLIC_THREADS`. BREAKING CHANGE: Changed `guildChannel` argument to return `GuildChannel | ThreadChannel`. BREAKING CHANGE: Changed `SapphireClient.id`'s type to `Snowflake | null`. BREAKING CHANGE: Changed `SapphireClientOptions.id`'s type to `Snowflake | null`. BREAKING CHANGE: Removed `Events.GuildMemberSpeaking`. BREAKING CHANGE: Removed `StoreRegistry`, it is now re-exported from `@sapphire/pieces`. BREAKING CHANGE: Renamed `ArgType.categoryChannel` to `guildCategoryChannel`. BREAKING CHANGE: Renamed `ArgType.newsChannel` to `guildNewsChannel`. BREAKING CHANGE: Renamed `ArgType.textChannel` to `guildTextChannel`. BREAKING CHANGE: Renamed `ArgType.voiceChannel` to `guildVoiceChannel`. BREAKING CHANGE: Renamed `CommandPreConditions.NewsOnly` to `GuildNewsOnly`. BREAKING CHANGE: Renamed `CommandPreConditions.TextOnly` to `GuildTextOnly`. BREAKING CHANGE: Renamed `Identifiers.PreconditionNewsOnly` to `PreconditionGuildNewsOnly`. BREAKING CHANGE: Renamed `Identifiers.PreconditionTextOnly` to `PreconditionGuildTextOnly`. BREAKING CHANGE: Renamed `Preconditions.NewsOnly` to `GuildNewsOnly`. BREAKING CHANGE: Renamed `Preconditions.TextOnly` to `GuildTextOnly`. BREAKING CHANGE: Renamed the possible values for `CommandOptionsRunType`. BREAKING CHANGE: Updated `CooldownContext.delay` to not be optional. BREAKING CHANGE: Updated `discord.js` requirement to v13.
1 parent e70ca55 commit cbf5d4e

35 files changed

+535
-352
lines changed

package.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,25 @@
2525
},
2626
"dependencies": {
2727
"@sapphire/discord-utilities": "^2.1.5",
28-
"@sapphire/discord.js-utilities": "^1.6.0",
29-
"@sapphire/pieces": "~2.0.0",
30-
"@sapphire/ratelimits": "^1.2.5",
31-
"@sapphire/utilities": "^1.6.1",
28+
"@sapphire/discord.js-utilities": "next",
29+
"@sapphire/pieces": "^2.1.0",
30+
"@sapphire/ratelimits": "^2.0.1",
31+
"@sapphire/utilities": "^2.0.1",
3232
"lexure": "^0.17.0",
3333
"tslib": "^2.3.0"
3434
},
3535
"devDependencies": {
3636
"@commitlint/cli": "^12.1.4",
3737
"@commitlint/config-conventional": "^12.1.4",
3838
"@favware/rollup-type-bundler": "^1.0.2",
39-
"@sapphire/eslint-config": "^3.2.1",
39+
"@sapphire/eslint-config": "^3.2.3",
4040
"@sapphire/prettier-config": "^1.1.6",
41-
"@sapphire/ts-config": "^2.3.1",
41+
"@sapphire/ts-config": "^3.0.0",
4242
"@types/jest": "^26.0.24",
4343
"@types/node": "^16.3.3",
4444
"@types/ws": "^7.4.6",
4545
"cz-conventional-changelog": "^3.3.0",
46-
"discord.js": "^12.5.3",
46+
"discord.js": "dev",
4747
"husky": "^7.0.1",
4848
"jest": "^27.0.6",
4949
"jest-circus": "^27.0.6",

src/arguments/CoreChannel.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { PieceContext } from '@sapphire/pieces';
2-
import type { Channel } from 'discord.js';
2+
import type { Channel, Snowflake } from 'discord.js';
33
import { Argument, ArgumentContext, ArgumentResult } from '../lib/structures/Argument';
44

55
export class CoreArgument extends Argument<Channel> {
@@ -8,7 +8,7 @@ export class CoreArgument extends Argument<Channel> {
88
}
99

1010
public run(parameter: string, context: ArgumentContext): ArgumentResult<Channel> {
11-
const channel = (context.message.guild ? context.message.guild.channels : this.container.client.channels).cache.get(parameter);
11+
const channel = (context.message.guild ? context.message.guild.channels : this.container.client.channels).cache.get(parameter as Snowflake);
1212
return channel
1313
? this.ok(channel)
1414
: this.error({

src/arguments/CoreCategoryChannel.ts renamed to src/arguments/CoreGuildCategoryChannel.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ExtendedArgument, ExtendedArgumentContext } from '../lib/structures/Ext
77
export class CoreArgument extends ExtendedArgument<'guildChannel', CategoryChannel> {
88
public constructor(context: PieceContext) {
99
super(context, {
10-
name: 'categoryChannel',
10+
name: 'guildCategoryChannel',
1111
baseArgument: 'guildChannel'
1212
});
1313
}
@@ -17,7 +17,7 @@ export class CoreArgument extends ExtendedArgument<'guildChannel', CategoryChann
1717
? this.ok(channel)
1818
: this.error({
1919
parameter: context.parameter,
20-
message: 'The argument did not resolve to a category channel.',
20+
message: 'The argument did not resolve to a server category channel.',
2121
context: { ...context, channel }
2222
});
2323
}

src/arguments/CoreGuildChannel.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { ChannelMentionRegex, SnowflakeRegex } from '@sapphire/discord-utilities';
22
import type { PieceContext } from '@sapphire/pieces';
3-
import type { Guild, GuildChannel } from 'discord.js';
3+
import type { Guild, GuildChannel, Snowflake, ThreadChannel } from 'discord.js';
44
import { Identifiers } from '../lib/errors/Identifiers';
55
import { Argument, ArgumentContext, ArgumentResult } from '../lib/structures/Argument';
66

7-
export class CoreArgument extends Argument<GuildChannel> {
7+
export class CoreArgument extends Argument<GuildChannel | ThreadChannel> {
88
public constructor(context: PieceContext) {
99
super(context, { name: 'guildChannel' });
1010
}
1111

12-
public run(parameter: string, context: ArgumentContext): ArgumentResult<GuildChannel> {
12+
public run(parameter: string, context: ArgumentContext): ArgumentResult<GuildChannel | ThreadChannel> {
1313
const { guild } = context.message;
1414
if (!guild) {
1515
return this.error({
@@ -20,7 +20,7 @@ export class CoreArgument extends Argument<GuildChannel> {
2020
});
2121
}
2222

23-
const channel = this.resolveByID(parameter, guild) ?? this.resolveByQuery(parameter, guild);
23+
const channel = this.resolveById(parameter, guild) ?? this.resolveByQuery(parameter, guild);
2424
return channel
2525
? this.ok(channel)
2626
: this.error({
@@ -30,12 +30,12 @@ export class CoreArgument extends Argument<GuildChannel> {
3030
});
3131
}
3232

33-
private resolveByID(argument: string, guild: Guild): GuildChannel | null {
34-
const channelID = ChannelMentionRegex.exec(argument) ?? SnowflakeRegex.exec(argument);
35-
return channelID ? guild.channels.cache.get(channelID[1]) ?? null : null;
33+
private resolveById(argument: string, guild: Guild): GuildChannel | ThreadChannel | null {
34+
const channelId = ChannelMentionRegex.exec(argument) ?? SnowflakeRegex.exec(argument);
35+
return channelId ? guild.channels.cache.get(channelId[1] as Snowflake) ?? null : null;
3636
}
3737

38-
private resolveByQuery(argument: string, guild: Guild): GuildChannel | null {
38+
private resolveByQuery(argument: string, guild: Guild): GuildChannel | ThreadChannel | null {
3939
const lowerCaseArgument = argument.toLowerCase();
4040
return guild.channels.cache.find((channel) => channel.name.toLowerCase() === lowerCaseArgument) ?? null;
4141
}

src/arguments/CoreNewsChannel.ts renamed to src/arguments/CoreGuildNewsChannel.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ExtendedArgument, ExtendedArgumentContext } from '../lib/structures/Ext
77
export class CoreArgument extends ExtendedArgument<'guildChannel', NewsChannel> {
88
public constructor(context: PieceContext) {
99
super(context, {
10-
name: 'newsChannel',
10+
name: 'guildNewsChannel',
1111
baseArgument: 'guildChannel'
1212
});
1313
}
@@ -17,7 +17,7 @@ export class CoreArgument extends ExtendedArgument<'guildChannel', NewsChannel>
1717
? this.ok(channel)
1818
: this.error({
1919
parameter: context.parameter,
20-
message: 'The argument did not resolve to a news channel.',
20+
message: 'The argument did not resolve to a server announcement channel.',
2121
context: { ...context, channel }
2222
});
2323
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { PieceContext } from '@sapphire/pieces';
2+
import type { ThreadChannel } from 'discord.js';
3+
import type { ArgumentResult } from '../lib/structures/Argument';
4+
import { ExtendedArgument, ExtendedArgumentContext } from '../lib/structures/ExtendedArgument';
5+
6+
export class CoreArgument extends ExtendedArgument<'guildThreadChannel', ThreadChannel> {
7+
public constructor(context: PieceContext) {
8+
super(context, {
9+
name: 'guildNewsThreadChannel',
10+
baseArgument: 'guildThreadChannel'
11+
});
12+
}
13+
14+
public handle(channel: ThreadChannel, context: ExtendedArgumentContext): ArgumentResult<ThreadChannel> {
15+
return channel.type === 'GUILD_NEWS_THREAD'
16+
? this.ok(channel)
17+
: this.error({
18+
parameter: context.parameter,
19+
message: 'The argument did not resolve to a server announcement thread channel.',
20+
context: { ...context, channel }
21+
});
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { PieceContext } from '@sapphire/pieces';
2+
import type { ThreadChannel } from 'discord.js';
3+
import type { ArgumentResult } from '../lib/structures/Argument';
4+
import { ExtendedArgument, ExtendedArgumentContext } from '../lib/structures/ExtendedArgument';
5+
6+
export class CoreArgument extends ExtendedArgument<'guildThreadChannel', ThreadChannel> {
7+
public constructor(context: PieceContext) {
8+
super(context, {
9+
name: 'guildPrivateThreadChannel',
10+
baseArgument: 'guildThreadChannel'
11+
});
12+
}
13+
14+
public handle(channel: ThreadChannel, context: ExtendedArgumentContext): ArgumentResult<ThreadChannel> {
15+
return channel.type === 'GUILD_PRIVATE_THREAD'
16+
? this.ok(channel)
17+
: this.error({
18+
parameter: context.parameter,
19+
message: 'The argument did not resolve to a private server thread channel.',
20+
context: { ...context, channel }
21+
});
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { PieceContext } from '@sapphire/pieces';
2+
import type { ThreadChannel } from 'discord.js';
3+
import type { ArgumentResult } from '../lib/structures/Argument';
4+
import { ExtendedArgument, ExtendedArgumentContext } from '../lib/structures/ExtendedArgument';
5+
6+
export class CoreArgument extends ExtendedArgument<'guildThreadChannel', ThreadChannel> {
7+
public constructor(context: PieceContext) {
8+
super(context, {
9+
name: 'guildPublicThreadChannel',
10+
baseArgument: 'guildThreadChannel'
11+
});
12+
}
13+
14+
public handle(channel: ThreadChannel, context: ExtendedArgumentContext): ArgumentResult<ThreadChannel> {
15+
return channel.type === 'GUILD_PUBLIC_THREAD'
16+
? this.ok(channel)
17+
: this.error({
18+
parameter: context.parameter,
19+
message: 'The argument did not resolve to a public server thread channel.',
20+
context: { ...context, channel }
21+
});
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { PieceContext } from '@sapphire/pieces';
2+
import type { GuildChannel, StageChannel } from 'discord.js';
3+
import type { ArgumentResult } from '../lib/structures/Argument';
4+
import { ExtendedArgument, ExtendedArgumentContext } from '../lib/structures/ExtendedArgument';
5+
6+
export class CoreArgument extends ExtendedArgument<'guildChannel', StageChannel> {
7+
public constructor(context: PieceContext) {
8+
super(context, {
9+
name: 'guildStageVoiceChannel',
10+
baseArgument: 'guildChannel'
11+
});
12+
}
13+
14+
public handle(channel: GuildChannel, context: ExtendedArgumentContext): ArgumentResult<StageChannel> {
15+
return channel.type === 'GUILD_STAGE_VOICE'
16+
? this.ok(channel as StageChannel)
17+
: this.error({
18+
parameter: context.parameter,
19+
message: 'The argument did not resolve to a server stage voice channel.',
20+
context: { ...context, channel }
21+
});
22+
}
23+
}

src/arguments/CoreTextChannel.ts renamed to src/arguments/CoreGuildTextChannel.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ExtendedArgument, ExtendedArgumentContext } from '../lib/structures/Ext
77
export class CoreArgument extends ExtendedArgument<'guildChannel', TextChannel> {
88
public constructor(context: PieceContext) {
99
super(context, {
10-
name: 'textChannel',
10+
name: 'guildTextChannel',
1111
baseArgument: 'guildChannel'
1212
});
1313
}
@@ -17,7 +17,7 @@ export class CoreArgument extends ExtendedArgument<'guildChannel', TextChannel>
1717
? this.ok(channel)
1818
: this.error({
1919
parameter: context.parameter,
20-
message: 'The argument did not resolve to a text channel.',
20+
message: 'The argument did not resolve to a server text channel.',
2121
context: { ...context, channel }
2222
});
2323
}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { PieceContext } from '@sapphire/pieces';
2+
import type { GuildChannel, ThreadChannel } from 'discord.js';
3+
import type { ArgumentResult } from '../lib/structures/Argument';
4+
import { ExtendedArgument, ExtendedArgumentContext } from '../lib/structures/ExtendedArgument';
5+
6+
export class CoreArgument extends ExtendedArgument<'guildChannel', ThreadChannel> {
7+
public constructor(context: PieceContext) {
8+
super(context, {
9+
name: 'guildThreadChannel',
10+
baseArgument: 'guildChannel'
11+
});
12+
}
13+
14+
public handle(channel: GuildChannel, context: ExtendedArgumentContext): ArgumentResult<ThreadChannel> {
15+
return channel.isThread()
16+
? this.ok(channel)
17+
: this.error({
18+
parameter: context.parameter,
19+
message: 'The argument did not resolve to a server thread channel.',
20+
context: { ...context, channel }
21+
});
22+
}
23+
}

src/arguments/CoreVoiceChannel.ts renamed to src/arguments/CoreGuildVoiceChannel.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { ExtendedArgument, ExtendedArgumentContext } from '../lib/structures/Ext
77
export class CoreArgument extends ExtendedArgument<'guildChannel', VoiceChannel> {
88
public constructor(context: PieceContext) {
99
super(context, {
10-
name: 'voiceChannel',
10+
name: 'guildVoiceChannel',
1111
baseArgument: 'guildChannel'
1212
});
1313
}
@@ -17,7 +17,7 @@ export class CoreArgument extends ExtendedArgument<'guildChannel', VoiceChannel>
1717
? this.ok(channel)
1818
: this.error({
1919
parameter: context.parameter,
20-
message: 'The argument did not resolve to a voice channel.',
20+
message: 'The argument did not resolve to a server voice channel.',
2121
context: { ...context, channel }
2222
});
2323
}

src/arguments/CoreMember.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { SnowflakeRegex, UserOrMemberMentionRegex } from '@sapphire/discord-utilities';
22
import type { PieceContext } from '@sapphire/pieces';
3-
import type { Guild, GuildMember } from 'discord.js';
3+
import type { Guild, GuildMember, Snowflake } from 'discord.js';
44
import { Identifiers } from '../lib/errors/Identifiers';
55
import { Argument, ArgumentContext, AsyncArgumentResult } from '../lib/structures/Argument';
66

@@ -20,7 +20,7 @@ export class CoreArgument extends Argument<GuildMember> {
2020
});
2121
}
2222

23-
const member = (await this.resolveByID(parameter, guild)) ?? (await this.resolveByQuery(parameter, guild));
23+
const member = (await this.resolveById(parameter, guild)) ?? (await this.resolveByQuery(parameter, guild));
2424
return member
2525
? this.ok(member)
2626
: this.error({
@@ -30,9 +30,9 @@ export class CoreArgument extends Argument<GuildMember> {
3030
});
3131
}
3232

33-
private async resolveByID(argument: string, guild: Guild): Promise<GuildMember | null> {
34-
const memberID = UserOrMemberMentionRegex.exec(argument) ?? SnowflakeRegex.exec(argument);
35-
return memberID ? guild.members.fetch(memberID[1]).catch(() => null) : null;
33+
private async resolveById(argument: string, guild: Guild): Promise<GuildMember | null> {
34+
const memberId = UserOrMemberMentionRegex.exec(argument) ?? SnowflakeRegex.exec(argument);
35+
return memberId ? guild.members.fetch(memberId[1] as Snowflake).catch(() => null) : null;
3636
}
3737

3838
private async resolveByQuery(argument: string, guild: Guild): Promise<GuildMember | null> {

src/arguments/CoreMessage.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { isNewsChannel, isTextChannel, MessageLinkRegex, SnowflakeRegex } from '@sapphire/discord.js-utilities';
22
import type { PieceContext } from '@sapphire/pieces';
3-
import { DMChannel, Message, NewsChannel, Permissions, TextChannel } from 'discord.js';
3+
import { DMChannel, Message, NewsChannel, Permissions, Snowflake, TextChannel, ThreadChannel } from 'discord.js';
44
import { Argument, ArgumentContext, AsyncArgumentResult } from '../lib/structures/Argument';
55

66
export interface MessageArgumentContext extends ArgumentContext {
@@ -14,7 +14,7 @@ export class CoreArgument extends Argument<Message> {
1414

1515
public async run(parameter: string, context: MessageArgumentContext): AsyncArgumentResult<Message> {
1616
const channel = context.channel ?? context.message.channel;
17-
const message = (await this.resolveByID(parameter, channel)) ?? (await this.resolveByLink(parameter, context));
17+
const message = (await this.resolveById(parameter as Snowflake, channel)) ?? (await this.resolveByLink(parameter, context));
1818
return message
1919
? this.ok(message)
2020
: this.error({
@@ -24,7 +24,7 @@ export class CoreArgument extends Argument<Message> {
2424
});
2525
}
2626

27-
private async resolveByID(argument: string, channel: DMChannel | NewsChannel | TextChannel): Promise<Message | null> {
27+
private resolveById(argument: Snowflake, channel: DMChannel | NewsChannel | TextChannel | ThreadChannel): Promise<Message | null> | null {
2828
return SnowflakeRegex.test(argument) ? channel.messages.fetch(argument).catch(() => null) : null;
2929
}
3030

@@ -33,17 +33,17 @@ export class CoreArgument extends Argument<Message> {
3333

3434
const matches = MessageLinkRegex.exec(argument);
3535
if (!matches) return null;
36-
const [, guildID, channelID, messageID] = matches;
36+
const [, guildId, channelId, messageId] = matches;
3737

38-
const guild = this.container.client.guilds.cache.get(guildID);
38+
const guild = this.container.client.guilds.cache.get(guildId as Snowflake);
3939
if (guild !== message.guild) return null;
4040

41-
const channel = guild.channels.cache.get(channelID);
41+
const channel = guild.channels.cache.get(channelId as Snowflake);
4242
if (!channel) return null;
4343
if (!(isNewsChannel(channel) || isTextChannel(channel))) return null;
4444
if (!channel.viewable) return null;
4545
if (!channel.permissionsFor(message.author)?.has(Permissions.FLAGS.VIEW_CHANNEL)) return null;
4646

47-
return channel.messages.fetch(messageID).catch(() => null);
47+
return channel.messages.fetch(messageId as Snowflake).catch(() => null);
4848
}
4949
}

src/arguments/CoreRole.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { RoleMentionRegex, SnowflakeRegex } from '@sapphire/discord-utilities';
22
import type { PieceContext } from '@sapphire/pieces';
3-
import type { Guild, Role } from 'discord.js';
3+
import type { Guild, Role, Snowflake } from 'discord.js';
44
import { Identifiers } from '../lib/errors/Identifiers';
55
import { Argument, ArgumentContext, AsyncArgumentResult } from '../lib/structures/Argument';
66

@@ -20,13 +20,13 @@ export class CoreArgument extends Argument<Role> {
2020
});
2121
}
2222

23-
const role = (await this.resolveByID(parameter, guild)) ?? this.resolveByQuery(parameter, guild);
23+
const role = (await this.resolveById(parameter, guild)) ?? this.resolveByQuery(parameter, guild);
2424
return role ? this.ok(role) : this.error({ parameter, message: 'The argument did not resolve to a role.', context });
2525
}
2626

27-
private async resolveByID(argument: string, guild: Guild): Promise<Role | null> {
28-
const roleID = RoleMentionRegex.exec(argument) ?? SnowflakeRegex.exec(argument);
29-
return roleID ? guild.roles.fetch(roleID[1]).catch(() => null) : null;
27+
private async resolveById(argument: string, guild: Guild): Promise<Role | null> {
28+
const roleId = RoleMentionRegex.exec(argument) ?? SnowflakeRegex.exec(argument);
29+
return roleId ? guild.roles.fetch(roleId[1] as Snowflake).catch(() => null) : null;
3030
}
3131

3232
private resolveByQuery(argument: string, guild: Guild): Role | null {

0 commit comments

Comments
 (0)