all repos — stealth-developers @ 6bb17a8faa466982ae7085638f89778869d56644

feat: codes command
vi v@vt3e.cat
Sun, 01 Mar 2026 00:45:15 +0000
commit

6bb17a8faa466982ae7085638f89778869d56644

parent

1e965c6fd5d5899f87df016caf45fdd1f2e6474e

M src/events/messageCreate.tssrc/events/messageCreate.ts

@@ -6,6 +6,7 @@ ButtonBuilder,

ButtonStyle, type Client, Events, + type GuildMember, type Message, } from "discord.js"; import { and, eq } from "drizzle-orm";

@@ -13,14 +14,15 @@ import { nanoid } from "nanoid";

import config from "@/config"; import { loggers } from "@/utils/logging"; +import { hasManagerPermissions } from "@/utils/permissions"; const logger = loggers.events.child({ name: "messageCreate" }); type UploadStatus = "queued" | "uploading" | "done" | "failed"; export default { event: Events.MessageCreate, - async execute(_client: Client, message: Message) { - if (message.author.bot) return; + async execute(client: Client, message: Message) { + if (!client.user) return; if (message.content.includes("grok is this true")) { if (message.channel.isSendable()) await message.channel.send("yeh");

@@ -40,12 +42,19 @@

if (!ticket) return; try { + const isSystem = message.author.id === client.user.id; + const isReporter = message.author.id === ticket.authorId; + const isModerator = await hasManagerPermissions( + message?.member as GuildMember, + ); + const authorType = isSystem ? "system" : isModerator ? "staff" : "user"; + const savedMessage = db .insert(ticketMessages) .values({ ticketId: ticket.id, authorId: message.author.id, - authorType: "user", + authorType: authorType, content: message.content, createdAt: message.createdAt, })
A src/interactions/commands/codes.ts

@@ -0,0 +1,73 @@

+import config from "@/config"; +import { text } from "@/utils/components"; +import { tsExact, tsRelative } from "@/utils/profile"; +import { + type ChatInputCommandInteraction, + type Client, + ContainerBuilder, + SlashCommandBuilder, +} from "discord.js"; + +const commandData = new SlashCommandBuilder() + .setName("codes") + .setDescription(`Get the codes for all ${config.terminology}s`) + .addUserOption((option) => + option + .setName("user") + .setDescription("Optional user to mention") + .setRequired(false), + ); + +async function execute( + _client: Client, + interaction: ChatInputCommandInteraction, +) { + const user = interaction.options.getUser("user"); + + const container = new ContainerBuilder(); + const containerTextArr = ["## Codes"]; + + for (const project of Object.values(config.projects)) { + containerTextArr.push(`### ${project.displayName}`); + if (!project.codes || project.codes.length === 0) { + containerTextArr.push("No codes available."); + continue; + } + for (const code of project.codes) { + const codeText = code.expired ? `~~${code.code}~~` : `**${code.code}**`; + const addedString = code.addedAt + ? `added ${tsRelative(code.addedAt)}` + : undefined; + const lineParts = [ + `- ${codeText}`, + addedString ? `(${addedString})` : undefined, + ].filter(Boolean); + + containerTextArr.push(lineParts.join(" ")); + } + } + + const containerText = text(containerTextArr.join("\n")); + const footerText = text( + [ + `\n-# Please tell <@${config.developerId}> if this is incorrect`, + user ? `<@${user.id}>` : undefined, + ] + .filter(Boolean) + .join(" • "), + ); + + container.addTextDisplayComponents(containerText, footerText); + await interaction.reply({ + components: [container], + flags: ["IsComponentsV2"], + ...(user + ? { allowedMentions: { users: [user?.id] } } + : { allowedMentions: { users: [] } }), + }); +} + +export default { + data: commandData, + execute, +};
A src/interactions/menus/highlight.ts

@@ -0,0 +1,125 @@

+import { getGuild } from "@/utils/queries"; +import { + ApplicationCommandType, + type Attachment, + type Client, + ContextMenuCommandBuilder, + type GuildTextBasedChannel, + type MessageContextMenuCommandInteraction, +} from "discord.js"; + +const commandData = new ContextMenuCommandBuilder() + .setName("Highlight Clip") + .setType(ApplicationCommandType.Message); + +function extractVideoLinks(message: { content: string }): string[] { + const urlRegex = + /https?:\/\/(?:www\.)?(?:youtube\.com\/watch\?v=[\w-]+|youtu\.be\/[\w-]+|medal\.tv\/(?:games\/[\w-]+\/clips\/[\w-]+|g\/[\w-]+|clips\/[\w-]+))/gi; + return Array.from(message.content.matchAll(urlRegex)).map((m) => m[0]); +} + +function isVideoAttachment(attachment: Attachment): boolean { + return ( + typeof attachment.contentType === "string" && + attachment.contentType.startsWith("video/") + ); +} + +async function execute( + client: Client, + interaction: MessageContextMenuCommandInteraction, +) { + if (!interaction.guild) { + await interaction.reply({ + content: "❌ This command can only be used in a server.", + ephemeral: true, + }); + return; + } + + await interaction.deferReply({ flags: ["Ephemeral"] }); + const { data: guildConfig, exists } = await getGuild(interaction.guild.id); + if (!exists) { + await interaction.editReply({ + content: "❌ No guild configuration found.", + }); + return; + } + + if (!guildConfig.highlights_channel_id) { + await interaction.editReply({ + content: + "❌ No highlights channel configured. Use `/config highlight-channel`.", + }); + return; + } + + const targetMessage = interaction.targetMessage; + if (!targetMessage) { + await interaction.editReply({ + content: "❌ Couldn't find the target message.", + }); + return; + } + + const videoAttachments = targetMessage.attachments.filter(isVideoAttachment); + const videoLinks = extractVideoLinks(targetMessage); + + if (videoAttachments.size === 0 && videoLinks.length === 0) { + await interaction.editReply({ + content: + "❌ No video attachments or supported links found in this message.", + }); + return; + } + + let highlightsChannel: GuildTextBasedChannel | null = null; + try { + highlightsChannel = (await client.channels.fetch( + guildConfig.highlights_channel_id, + )) as GuildTextBasedChannel | null; + } catch (e) { + await interaction.editReply({ + content: "❌ Could not access the highlights channel.", + }); + return; + } + + if (!highlightsChannel) { + await interaction.editReply({ + content: "❌ Highlights channel not found.", + }); + return; + } + + const files = Array.from(videoAttachments.values()).map((a) => a.url); + const author = `<@${targetMessage.author.id}>`; + const jumpUrl = targetMessage.url; + + const videoLinksText = videoLinks + .map((link) => `• [Video Link](${link})`) + .join(" "); + const description = `:star: New highlight from ${author}!\n-# [Jump to message](${jumpUrl}) ${videoLinksText}`; + + try { + const msg = await highlightsChannel.send({ + content: description, + files: files.length > 0 ? files : undefined, + allowedMentions: { users: [targetMessage.author.id] }, + }); + + await msg.react("⭐"); + await interaction.editReply({ + content: "✅ Highlight sent!", + }); + } catch (error) { + await interaction.editReply({ + content: "❌ Failed to send highlight.", + }); + } +} + +export default { + data: commandData, + execute, +};
M src/utils/transcripts.tssrc/utils/transcripts.ts

@@ -38,8 +38,9 @@ const lines = messages.map((msg) => {

const msgAttachments = attachmentMap.get(msg.id) ?? []; const time = new Date(msg.createdAt).toISOString(); - const author = - msg.authorType === "user" ? "reporter" : `<@${msg.authorId}>`; + let author = "reporter"; + if (msg.authorType === "system") author = "system"; + if (msg.authorType === "staff") author = `<@${msg.authorId}>`; let text = `[${time}] ${author}: ${msg.content}`;