diff options
Diffstat (limited to 'packages/gateway/src/commands')
| -rw-r--r-- | packages/gateway/src/commands/commandHandler.ts | 3 | ||||
| -rw-r--r-- | packages/gateway/src/commands/parseCommandDuration.ts | 25 | ||||
| -rw-r--r-- | packages/gateway/src/commands/say.ts | 1 | ||||
| -rw-r--r-- | packages/gateway/src/commands/sayd.ts | 75 | ||||
| -rw-r--r-- | packages/gateway/src/commands/timeout.ts | 30 |
5 files changed, 109 insertions, 25 deletions
diff --git a/packages/gateway/src/commands/commandHandler.ts b/packages/gateway/src/commands/commandHandler.ts index efa621a..53d021f 100644 --- a/packages/gateway/src/commands/commandHandler.ts +++ b/packages/gateway/src/commands/commandHandler.ts @@ -1,6 +1,7 @@ import { Client, Events, Message } from "discord.js"; import { handleSayCommand } from "./say"; import { handleSaycCommand } from "./sayc"; +import { handleSaydCommand } from "./sayd"; import { handleStartCommand } from "./start"; import { handleCrpCommand } from "./crp"; import { handleReactCommand } from "./react"; @@ -20,9 +21,11 @@ export const handleCommandHandler = (client: Client) => { const verbalGatesHandled = await handleVerbalGatesCommand(message); const saycHandled = await handleSaycCommand(message); + const saydHandled = await handleSaydCommand(message); (message as any).verbalGatesHandled = verbalGatesHandled; (message as any).saycHandled = saycHandled; + (message as any).saydHandled = saydHandled; await Promise.allSettled([ handleSayCommand(message), diff --git a/packages/gateway/src/commands/parseCommandDuration.ts b/packages/gateway/src/commands/parseCommandDuration.ts new file mode 100644 index 0000000..946e3cb --- /dev/null +++ b/packages/gateway/src/commands/parseCommandDuration.ts @@ -0,0 +1,25 @@ +export const parseCommandDurationToMilliseconds = ( + duration: string, +): number | null => { + const durationMatch = duration.match(/^(\d+)([smhd])$/); + + if (!durationMatch) return null; + + const durationValue = Number.parseInt(durationMatch[1], 10); + const durationUnit = durationMatch[2]; + + if (durationValue < 1) return null; + + switch (durationUnit) { + case "s": + return durationValue * 1000; + case "m": + return durationValue * 60 * 1000; + case "h": + return durationValue * 60 * 60 * 1000; + case "d": + return durationValue * 24 * 60 * 60 * 1000; + default: + return null; + } +}; diff --git a/packages/gateway/src/commands/say.ts b/packages/gateway/src/commands/say.ts index 9df7abe..70fd72e 100644 --- a/packages/gateway/src/commands/say.ts +++ b/packages/gateway/src/commands/say.ts @@ -5,6 +5,7 @@ export const handleSayCommand = async (message: Message) => { if (message.author.bot) return; if ((message as any).saycHandled) return; + if ((message as any).saydHandled) return; if (message.content.toLowerCase().startsWith("uma!say")) { const application = await message.client.application?.fetch(); diff --git a/packages/gateway/src/commands/sayd.ts b/packages/gateway/src/commands/sayd.ts new file mode 100644 index 0000000..8bb64f2 --- /dev/null +++ b/packages/gateway/src/commands/sayd.ts @@ -0,0 +1,75 @@ +import { Message } from "discord.js"; +import { logUnexpectedDiscordAPIError, replyWithCleanup } from "../utilities"; +import { parseCommandDurationToMilliseconds } from "./parseCommandDuration"; + +export const handleSaydCommand = async (message: Message): Promise<boolean> => { + if (message.author.bot) return false; + + const content = message.content.trim(); + const commandMatch = content.match(/^uma!sayd\s+(\d+)\s+(\S+)\s+(.+)$/s); + + if (!commandMatch) return false; + + const [, channelId, timeout, messageContent] = commandMatch; + const timeoutMilliseconds = parseCommandDurationToMilliseconds(timeout); + + if (!timeoutMilliseconds) { + await replyWithCleanup( + message, + "❌ Invalid timeout format. Use: `<number><s|m|h|d>`\nExamples: `10s`, `5m`, `1h`", + ); + + return true; + } + + if (!messageContent.trim()) { + await replyWithCleanup( + message, + "❌ You need to provide a message to send.", + ); + + return true; + } + + try { + const targetChannel = message.client.channels.cache.get(channelId); + + if ( + !targetChannel || + !targetChannel.isTextBased() || + targetChannel.isDMBased() + ) { + await replyWithCleanup( + message, + "❌ Channel not found or is not a text channel.", + ); + + return true; + } + + const sentMessage = await targetChannel.send(messageContent); + + setTimeout(async () => { + try { + await sentMessage.delete(); + } catch (error) { + logUnexpectedDiscordAPIError(error); + } + }, timeoutMilliseconds); + + await replyWithCleanup( + message, + `✅ Message sent to <#${channelId}> and will be deleted in ${timeout}.`, + ); + + return true; + } catch (error) { + logUnexpectedDiscordAPIError(error); + await replyWithCleanup( + message, + "❌ Failed to send message to the specified channel.", + ); + + return true; + } +}; diff --git a/packages/gateway/src/commands/timeout.ts b/packages/gateway/src/commands/timeout.ts index d43d6bd..88aa194 100644 --- a/packages/gateway/src/commands/timeout.ts +++ b/packages/gateway/src/commands/timeout.ts @@ -1,28 +1,7 @@ import { Message } from "discord.js"; import { CENTRAL_GUILD_ID, ROLEPLAY_GUILD_ID } from "../constants"; import { logUnexpectedDiscordAPIError, replyWithCleanup } from "../utilities"; - -const parseDuration = (duration: string): number | null => { - const match = duration.match(/^(\d+)([smhd])$/); - - if (!match) return null; - - const value = parseInt(match[1]); - const unit = match[2]; - - switch (unit) { - case "s": - return value * 1000; - case "m": - return value * 60 * 1000; - case "h": - return value * 60 * 60 * 1000; - case "d": - return value * 24 * 60 * 60 * 1000; - default: - return null; - } -}; +import { parseCommandDurationToMilliseconds } from "./parseCommandDuration"; const getUserId = (input: string): string | null => { const mentionMatch = input.match(/^<@(\d+)>$/); @@ -68,9 +47,10 @@ export const handleTimeoutCommand = async (message: Message) => { const [serverInput, userInput, durationInput, ...reasonParts] = parameters; const reason = reasonParts.join(" ") || undefined; - const durationMs = parseDuration(durationInput); + const durationMilliseconds = + parseCommandDurationToMilliseconds(durationInput); - if (!durationMs) { + if (!durationMilliseconds) { await replyWithCleanup( message, "❌ Invalid duration format. Use: `<number><s|m|h|d>`\nExamples: `1m`, `6h`, `1d`", @@ -104,7 +84,7 @@ export const handleTimeoutCommand = async (message: Message) => { try { const member = await guild.members.fetch(userId); - await member.timeout(durationMs, reason); + await member.timeout(durationMilliseconds, reason); await replyWithCleanup( message, `✅ Successfully timed out ${member.user.tag} in ${guild.name} for ${durationInput}${reason ? ` - ${reason}` : ""}`, |