From d52106d9d27d6b31d8f79db8bd20238b077f5cf6 Mon Sep 17 00:00:00 2001 From: "Win8.1VMUser" <78744628+Win81VMUser@users.noreply.github.com> Date: Sat, 19 Jul 2025 10:44:43 +0200 Subject: [PATCH] Create index.ts --- plugins/messageScheduler/src/index.ts | 162 ++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 plugins/messageScheduler/src/index.ts diff --git a/plugins/messageScheduler/src/index.ts b/plugins/messageScheduler/src/index.ts new file mode 100644 index 0000000..0022d92 --- /dev/null +++ b/plugins/messageScheduler/src/index.ts @@ -0,0 +1,162 @@ +import { registerCommand, unregisterCommand } from "@vendetta/commands"; +import { showToast } from "@vendetta/ui/toasts"; +import { findByProps } from "@vendetta/metro"; +import { logger } from "@vendetta"; + +const MessageActions = findByProps("sendMessage", "receiveMessage"); +const Clyde = findByProps("sendBotMessage"); + +let timeoutIds: Record = {}; +let messageQueue: Record = {}; +let commandSchedule, commandScheduled, commandCancelScheduled; + +function schedule(channelId: string, content: string, at: number): string { + const id = `${channelId}:${at}`; + const delay = at - Date.now(); + messageQueue[id] = { content, at }; + + timeoutIds[id] = setTimeout(() => { + const realMessage = content; + MessageActions.sendMessage(channelId, { content: realMessage }); + delete timeoutIds[id]; + delete messageQueue[id]; + showToast("📤 Scheduled message sent."); + }, delay); + + return id; +} + +function cancelAll() { + Object.values(timeoutIds).forEach(clearTimeout); + timeoutIds = {}; + messageQueue = {}; +} + +function parseScheduledTimeExtended(timeStr: string): number { + const now = new Date(); + timeStr = timeStr.toLowerCase(); + + // Parsowanie formatu typu 1h30m, 2h, 45m, 10s + const durRegex = /(\d+)(h|m|s)/g; + let durationMs = 0; + let durMatch; + while ((durMatch = durRegex.exec(timeStr)) !== null) { + const val = parseInt(durMatch[1]); + const unit = durMatch[2]; + if (unit === "h") durationMs += val * 3600 * 1000; + else if (unit === "m") durationMs += val * 60 * 1000; + else if (unit === "s") durationMs += val * 1000; + } + if (durationMs > 0) return Date.now() + durationMs; + + // Parsowanie formatu godziny typu 3:30pm, 15:30 + const timeRegex = /^(\d{1,2}):(\d{2})(am|pm)?$/; + const timeMatch = timeStr.match(timeRegex); + if (timeMatch) { + let hours = parseInt(timeMatch[1]); + const minutes = parseInt(timeMatch[2]); + const ampm = timeMatch[3]; + + if (ampm) { + if (ampm === "pm" && hours < 12) hours += 12; + else if (ampm === "am" && hours === 12) hours = 0; + } + + const scheduled = new Date(now); + scheduled.setHours(hours, minutes, 0, 0); + + // Jeśli czas już minął, ustaw na jutro + if (scheduled.getTime() <= now.getTime()) { + scheduled.setDate(scheduled.getDate() + 1); + } + + return scheduled.getTime(); + } + + // Jeśli nic nie pasuje, zwróć 0 + return 0; +} + +export function onLoad() { + // REJESTRACJA /schedule + commandSchedule = registerCommand({ + name: "schedule", + displayName: "schedule", + description: "Schedule a message after a delay or at a time", + options: [ + { + name: "time", + description: "Delay (e.g. 10s, 1h30m) or time (3:30pm, 15:30)", + type: 3, + required: true, + }, + { + name: "message", + description: "Message to send", + type: 3, + required: true, + }, + ], + execute: (args, ctx) => { + const channelId = ctx.channel.id; + const timeStr = args[0]?.value; + const message = args[1]?.value; + + if (typeof timeStr !== "string" || timeStr.trim() === "") { + return Clyde.sendBotMessage(channelId, "⛔ Invalid time value!"); + } + + if (typeof message !== "string" || message.trim() === "") { + return Clyde.sendBotMessage(channelId, "⛔ Message cannot be empty!"); + } + + const at = parseScheduledTimeExtended(timeStr); + if (at === 0 || at <= Date.now()) { + return Clyde.sendBotMessage(channelId, "⛔ Invalid or past time specified!"); + } + + schedule(channelId, message, at); + const secondsLeft = Math.round((at - Date.now()) / 1000); + Clyde.sendBotMessage(channelId, `🕓 Scheduled message in ${secondsLeft}s.`); + }, + }); + + // REJESTRACJA /scheduled + commandScheduled = registerCommand({ + name: "scheduled", + displayName: "scheduled", + description: "List scheduled messages", + execute: (_args, ctx) => { + const channelId = ctx.channel.id; + const list = Object.entries(messageQueue).map(([id, val]) => { + const secondsLeft = Math.round((val.at - Date.now()) / 1000); + return `• **In ${secondsLeft}s** → ${val.content}`; + }); + if (list.length === 0) { + Clyde.sendBotMessage(channelId, "No scheduled messages."); + } else { + Clyde.sendBotMessage(channelId, `Scheduled messages:\n${list.join("\n")}`); + } + }, + }); + + // REJESTRACJA /cancel-scheduled + commandCancelScheduled = registerCommand({ + name: "cancel-scheduled", + displayName: "cancel-scheduled", + description: "Cancel all scheduled messages", + execute: (_args, ctx) => { + const channelId = ctx.channel.id; + cancelAll(); + Clyde.sendBotMessage(channelId, "All scheduled messages cancelled."); + }, + }); + +} + +export function onUnload() { + cancelAll(); + unregisterCommand(commandSchedule); + unregisterCommand(commandScheduled); + unregisterCommand(commandCancelScheduled); +}