generated from nhcarrigan/template
feat: add owner-only message context menu to forward messages to DMs
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
import {
|
||||||
|
ContextMenuCommandBuilder,
|
||||||
|
ApplicationCommandType,
|
||||||
|
type MessageContextMenuCommandInteraction,
|
||||||
|
DiscordAPIError,
|
||||||
|
ButtonBuilder,
|
||||||
|
EmbedBuilder,
|
||||||
|
ActionRowBuilder,
|
||||||
|
ButtonStyle,
|
||||||
|
} from "discord.js";
|
||||||
|
import { ids } from "../config/ids.js";
|
||||||
|
|
||||||
|
export const forwardOwnerDM = {
|
||||||
|
data: new ContextMenuCommandBuilder()
|
||||||
|
.setName("Forward to Naomi")
|
||||||
|
.setType(ApplicationCommandType.Message),
|
||||||
|
|
||||||
|
async execute(interaction: MessageContextMenuCommandInteraction) {
|
||||||
|
await interaction.deferReply({ ephemeral: true });
|
||||||
|
|
||||||
|
if (interaction.user.id !== ids.users.naomi) {
|
||||||
|
await interaction.editReply("❌ Only Naomi can use this command.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = interaction.targetMessage;
|
||||||
|
|
||||||
|
if (message.author.id === ids.users.naomi) {
|
||||||
|
await interaction.editReply("No need to forward your own message to yourself 😄");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const naomi = await interaction.client.users.fetch(ids.users.naomi);
|
||||||
|
|
||||||
|
const forwardedEmbed = new EmbedBuilder()
|
||||||
|
.setColor(0x5865F2)
|
||||||
|
.setTitle(`Message from ${message.author.tag}!`)
|
||||||
|
.setDescription(
|
||||||
|
(message.attachments.size > 0 ? `**Attachments:** ${message.attachments.size} file(s)\n\n` : "\n") +
|
||||||
|
(message.embeds.length > 0 ? `**Embeds:** ${message.embeds.length}\n\n` : "") + "\n" +
|
||||||
|
(message.content || "*[No text content]*") + "\n\n");
|
||||||
|
|
||||||
|
const viewButton = new ButtonBuilder()
|
||||||
|
.setLabel("View Message")
|
||||||
|
.setURL(message.url)
|
||||||
|
.setStyle(ButtonStyle.Link);
|
||||||
|
|
||||||
|
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||||
|
.addComponents(viewButton);
|
||||||
|
await naomi.send({
|
||||||
|
embeds: [forwardedEmbed],
|
||||||
|
files: message.attachments.map((att) => att.url),
|
||||||
|
components: [row],
|
||||||
|
});
|
||||||
|
|
||||||
|
await interaction.editReply({
|
||||||
|
content: "✅ Forwarded to your DMs!",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to forward:", error);
|
||||||
|
|
||||||
|
let replyText = "❌ Failed to forward message.";
|
||||||
|
|
||||||
|
if (error instanceof DiscordAPIError && error.code === 50007) {
|
||||||
|
replyText += " (Naomi's DMs might be closed)";
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.editReply(replyText);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -70,5 +70,6 @@ export const ids = {
|
|||||||
amari: "1406431359345496255",
|
amari: "1406431359345496255",
|
||||||
naomi: "465650873650118659",
|
naomi: "465650873650118659",
|
||||||
nhcarrigan: "1382837581649150104",
|
nhcarrigan: "1382837581649150104",
|
||||||
|
teklu:"1381735115163570198",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
import { scheduleJob } from "node-schedule";
|
import { scheduleJob } from "node-schedule";
|
||||||
import { App } from "octokit";
|
import { App } from "octokit";
|
||||||
|
import { forwardOwnerDM } from "./commands/forwardToOwner.js";
|
||||||
import { ids } from "./config/ids.js";
|
import { ids } from "./config/ids.js";
|
||||||
import { handleMessageCreate } from "./events/handleMessageCreate.js";
|
import { handleMessageCreate } from "./events/handleMessageCreate.js";
|
||||||
import { cacheData } from "./modules/cacheData.js";
|
import { cacheData } from "./modules/cacheData.js";
|
||||||
@@ -41,6 +42,7 @@ const githubApp = new App({
|
|||||||
appId: process.env.GH_CLIENT_ID,
|
appId: process.env.GH_CLIENT_ID,
|
||||||
privateKey: process.env.GH_PRIVATE_KEY.replaceAll("\\n", "\n"),
|
privateKey: process.env.GH_PRIVATE_KEY.replaceAll("\\n", "\n"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const octokit = await githubApp.getInstallationOctokit(83_119_105);
|
const octokit = await githubApp.getInstallationOctokit(83_119_105);
|
||||||
const { data } = await octokit.rest.apps.getAuthenticated();
|
const { data } = await octokit.rest.apps.getAuthenticated();
|
||||||
await logger.log(
|
await logger.log(
|
||||||
@@ -105,6 +107,12 @@ amari.discord.on(Events.MessageCreate, (message) => {
|
|||||||
|
|
||||||
amari.discord.on(Events.InteractionCreate, (interaction) => {
|
amari.discord.on(Events.InteractionCreate, (interaction) => {
|
||||||
void analytics.logGatewayEvent(Events.InteractionCreate, { ...interaction });
|
void analytics.logGatewayEvent(Events.InteractionCreate, { ...interaction });
|
||||||
|
|
||||||
|
if (interaction.isMessageContextMenuCommand() && interaction.commandName === "Forward to Naomi") {
|
||||||
|
void forwardOwnerDM.execute(interaction);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (interaction.isButton() && interaction.customId === "resolve") {
|
if (interaction.isButton() && interaction.customId === "resolve") {
|
||||||
if (interaction.user.id !== ids.users.naomi) {
|
if (interaction.user.id !== ids.users.naomi) {
|
||||||
return void interaction.reply({
|
return void interaction.reply({
|
||||||
@@ -112,6 +120,7 @@ amari.discord.on(Events.InteractionCreate, (interaction) => {
|
|||||||
flags: [MessageFlags.Ephemeral],
|
flags: [MessageFlags.Ephemeral],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return void interaction.message.delete();
|
return void interaction.message.delete();
|
||||||
}
|
}
|
||||||
if (interaction.isAutocomplete()) {
|
if (interaction.isAutocomplete()) {
|
||||||
@@ -163,4 +172,8 @@ amari.discord.on(Events.GuildMemberRemove, (member) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await amari.discord.login(process.env.BOT_TOKEN);
|
await amari.discord.login(process.env.BOT_TOKEN);
|
||||||
|
amari.discord.on(Events.MessageCreate, (message) => {
|
||||||
|
const channelType = message.channel.type;
|
||||||
|
console.log(`📩 [${channelType}] ${message.author.tag}: ${message.content}`);
|
||||||
|
});
|
||||||
instantiateServer(amari);
|
instantiateServer(amari);
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { REST, Routes } from "discord.js";
|
||||||
|
import { forwardOwnerDM } from "../commands/forwardToOwner.js";
|
||||||
|
|
||||||
|
const commands = [
|
||||||
|
forwardOwnerDM.data.toJSON(),
|
||||||
|
];
|
||||||
|
|
||||||
|
const token = process.env.BOT_TOKEN;
|
||||||
|
const clientId = process.env.GH_CLIENT_ID;
|
||||||
|
|
||||||
|
if (token === undefined) {
|
||||||
|
throw new Error("BOT_TOKEN is missing from environment variables!");
|
||||||
|
}
|
||||||
|
if (clientId === undefined) {
|
||||||
|
throw new Error("CLIENT_ID is missing from environment variables!");
|
||||||
|
}
|
||||||
|
|
||||||
|
const rest = new REST({ version: "10" }).setToken(token);
|
||||||
|
(async() => {
|
||||||
|
try {
|
||||||
|
console.log("Registering GLOBAL context menu command... wait till appear everywhere.");
|
||||||
|
|
||||||
|
await rest.put(
|
||||||
|
Routes.applicationCommands(clientId),
|
||||||
|
{ body: commands },
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("Global registration sent! then check right-click on a message → Apps.");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Registration failed:", error);
|
||||||
|
}
|
||||||
|
})();
|
||||||
Reference in New Issue
Block a user