diff --git a/src/arguments/boolean.ts b/src/arguments/boolean.ts index 8c9546e1284..118d97ebe5e 100644 --- a/src/arguments/boolean.ts +++ b/src/arguments/boolean.ts @@ -28,10 +28,10 @@ export class CoreArgument extends Argument { } private get getDefaultTruthValues() { - return (this.defaultTruthValues ??= getT('en-US')(LanguageKeys.Arguments.BooleanTrueOptions).filter(filterNullish)); + return (this.defaultTruthValues ??= getT()(LanguageKeys.Arguments.BooleanTrueOptions).filter(filterNullish)); } private get getDefaultFalseValues() { - return (this.defaultFalseValues ??= getT('en-US')(LanguageKeys.Arguments.BooleanFalseOptions).filter(filterNullish)); + return (this.defaultFalseValues ??= getT()(LanguageKeys.Arguments.BooleanFalseOptions).filter(filterNullish)); } } diff --git a/src/arguments/channelName.ts b/src/arguments/channelName.ts index dceb1c20a58..91febfd2035 100644 --- a/src/arguments/channelName.ts +++ b/src/arguments/channelName.ts @@ -9,7 +9,7 @@ import type { Guild, GuildChannel, ThreadChannel, User } from 'discord.js'; export class UserArgument extends Argument { public resolveChannel(query: string, guild: Guild) { const channelId = ChannelMentionRegex.exec(query) ?? SnowflakeRegex.exec(query); - return (channelId !== null && guild.channels.cache.get(channelId[1])) ?? null; + return (channelId !== null && guild.channels.cache.get(channelId.groups!.id)) ?? null; } public async run(parameter: string, { message, minimum, context, filter }: ChannelArgumentContext) { @@ -17,7 +17,10 @@ export class UserArgument extends Argument { filter = this.getFilter(message.author, filter); const resChannel = this.resolveChannel(parameter, message.guild); - if (resChannel && filter(resChannel)) return this.ok(resChannel); + if (resChannel) { + if (filter(resChannel)) return this.ok(resChannel); + return this.error({ parameter, identifier: LanguageKeys.Arguments.GuildChannelMismatchingError, context }); + } const result = await new FuzzySearch(message.guild.channels.cache, (entry) => entry.name, filter).run(message, parameter, minimum); if (result) return this.ok(result[1]); diff --git a/src/languages/en-US/arguments.json b/src/languages/en-US/arguments.json index fed5e3184cc..ae32b6a15ee 100644 --- a/src/languages/en-US/arguments.json +++ b/src/languages/en-US/arguments.json @@ -46,6 +46,7 @@ "floatTooLarge": "The parameter `{{parameter}}` is too high! It needs to be less than {{maximum}}!", "floatTooSmall": "The parameter `{{parameter}}` is too low! It needs to be at least {{minimum}}!", "guildChannelError": "I could not resolve `{{parameter}}` to a channel from this server, please make sure you typed its name or ID correctly!", + "guildChannelMismatchingError": "The parameter `{{parameter}}` resolved to an incompatible channel type in this server, please try another channel!", "guildChannelMissingGuildError": "I was not able to resolve `{{parameter}}` because this argument requires to be run in a server channel.", "guildPrivateThreadChannelError": "I could not resolve `{{parameter}}` to a private thread channel, please make sure you typed its name or ID correctly!", "guildPublicThreadChannelError": "I could not resolve `{{parameter}}` to a public thread channel, please make sure you typed its name or ID correctly!", diff --git a/src/lib/database/entities/GuildEntity.ts b/src/lib/database/entities/GuildEntity.ts index 953b66faeb0..caa959f68e7 100644 --- a/src/lib/database/entities/GuildEntity.ts +++ b/src/lib/database/entities/GuildEntity.ts @@ -26,7 +26,7 @@ export class GuildEntity extends BaseEntity implements IBaseEntity { @ConfigurableKey({ description: LanguageKeys.Settings.Language, type: 'language' }) @Column('varchar', { name: 'language', default: 'en-US' }) - public language = 'en-US'; + public language: LocaleString = 'en-US'; @ConfigurableKey({ description: LanguageKeys.Settings.DisableNaturalPrefix }) @Column('boolean', { name: 'disable-natural-prefix', default: false }) @@ -672,7 +672,7 @@ export class GuildEntity extends BaseEntity implements IBaseEntity { * Gets the [[Language]] for this entity. */ public getLanguage(): TFunction { - return getT(this.language as LocaleString); + return getT(this.language); } /** diff --git a/src/lib/i18n/languageKeys/keys/Arguments.ts b/src/lib/i18n/languageKeys/keys/Arguments.ts index c3a6c3676cd..4d4099fa3c9 100644 --- a/src/lib/i18n/languageKeys/keys/Arguments.ts +++ b/src/lib/i18n/languageKeys/keys/Arguments.ts @@ -20,6 +20,7 @@ export const FloatError = FT<{ parameter: string }>('arguments:floatError'); export const FloatTooLarge = FT<{ parameter: string; maximum: number }>('arguments:floatTooLarge'); export const FloatTooSmall = FT<{ parameter: string; minimum: number }>('arguments:floatTooSmall'); export const GuildChannelError = FT<{ parameter: string }>('arguments:guildChannelError'); +export const GuildChannelMismatchingError = FT<{ parameter: string }>('arguments:guildChannelMismatchingError'); export const GuildChannelMissingGuildError = FT<{ parameter: string }>('arguments:guildChannelMissingGuildError'); export const GuildPrivateThreadChannelError = FT<{ parameter: string }>('arguments:guildPrivateThreadChannelError'); export const GuildPublicThreadChannelError = FT<{ parameter: string }>('arguments:guildPublicThreadChannelError'); diff --git a/src/lib/i18n/translate.ts b/src/lib/i18n/translate.ts index f3167225585..dc34d5347b8 100644 --- a/src/lib/i18n/translate.ts +++ b/src/lib/i18n/translate.ts @@ -131,7 +131,7 @@ export function getT(locale?: LocaleString | Nullish) { * @returns The fetched language as a {@link LocaleString}. */ export async function fetchLanguage(context: InternationalizationContext) { - return ((await container.i18n.fetchLanguage(context)) ?? 'en-US') as LocaleString; + return (await container.i18n.fetchLanguage(context))! as LocaleString; } /** diff --git a/src/lib/structures/SettingsMenu.ts b/src/lib/structures/SettingsMenu.ts index 181d68cd8ec..73d3c0c9df2 100644 --- a/src/lib/structures/SettingsMenu.ts +++ b/src/lib/structures/SettingsMenu.ts @@ -141,7 +141,12 @@ export class SettingsMenu { } private async onReaction(reaction: LLRCData): Promise { + // If the message is not the menu's message, ignore: + if (!this.response || reaction.messageId !== this.response.id) return; + + // If the user is not the author, ignore: if (reaction.userId !== this.message.author.id) return; + this.llrc?.setTime(TIMEOUT); if (reaction.emoji.name === EMOJIS.STOP) { this.llrc?.end(); @@ -160,11 +165,10 @@ export class SettingsMenu { const channelId = this.response.channel.id; const messageId = this.response.id; - const reactionId = encodeURIComponent(reaction); try { return await (userId === this.message.client.user!.id - ? api().channels.deleteUserMessageReaction(channelId, messageId, reactionId, userId) - : api().channels.deleteOwnMessageReaction(channelId, messageId, reactionId)); + ? api().channels.deleteUserMessageReaction(channelId, messageId, reaction, userId) + : api().channels.deleteOwnMessageReaction(channelId, messageId, reaction)); } catch (error) { if (error instanceof DiscordAPIError) { if (error.code === RESTJSONErrorCodes.UnknownMessage) { diff --git a/src/tasks/reminder.ts b/src/tasks/reminder.ts index 96ccf58cf2d..9787972d7a9 100644 --- a/src/tasks/reminder.ts +++ b/src/tasks/reminder.ts @@ -12,7 +12,7 @@ export class UserTask extends Task { if (user) { const timestamp = time(new Date(), TimestampStyles.ShortDateTime); - const reminderHeader = getT('en-US')(LanguageKeys.System.ReminderHeader, { timestamp }); + const reminderHeader = getT()(LanguageKeys.System.ReminderHeader, { timestamp }); await resolveOnErrorCodes( // diff --git a/tests/lib/util.test.ts b/tests/lib/util.test.ts index c0415d16244..61964f6c232 100644 --- a/tests/lib/util.test.ts +++ b/tests/lib/util.test.ts @@ -262,7 +262,7 @@ describe('Utils', () => { ${AttachmentText} | ${ExpectedReturn} | ${ExpectedEmbedImageURL} | ${'non-image attachment'} ${AttachmentImage} | ${'attachment URL'} | ${AttachmentImage.proxyURL} | ${'image attachment'} `(`AND $description THEN returns $returns`, ({ attachment, expected }) => { - const message: DeepPartial = { attachments: createAttachments(attachment), embeds }; + const message: DeepPartial = { attachments: createAttachments(attachment), embeds, stickers: new Collection() }; expect(getImage(message)).toEqual(expected); }); diff --git a/tests/lib/util/functions/emojis/getEmojiReactionFormat.test.ts b/tests/lib/util/functions/emojis/getEmojiReactionFormat.test.ts index 004371a6f3c..23f98c6e19a 100644 --- a/tests/lib/util/functions/emojis/getEmojiReactionFormat.test.ts +++ b/tests/lib/util/functions/emojis/getEmojiReactionFormat.test.ts @@ -1,9 +1,9 @@ import { getEmojiReactionFormat } from '#utils/functions'; -import { encodedBunnyTwemoji, serializedAnimatedSkyraGlasses, serializedStaticSkyra } from '../../../../mocks/constants.js'; +import { bunnyTwemoji, encodedBunnyTwemoji, serializedAnimatedSkyraGlasses, serializedStaticSkyra } from '../../../../mocks/constants.js'; describe('getEmojiReactionFormat', () => { test('GIVEN encoded twemoji THEN returns encoded twemoji', () => { - expect(getEmojiReactionFormat(encodedBunnyTwemoji)).toBe(encodedBunnyTwemoji); + expect(getEmojiReactionFormat(encodedBunnyTwemoji)).toBe(bunnyTwemoji); }); test('GIVEN custom serialized static emoji THEN returns :_:819227046453444620>', () => {