Merge branch 'main' of https://github.com/Xargana/blahaj-srv
This commit is contained in:
commit
24fdbc0fa7
295
discord/index.js
295
discord/index.js
|
@ -5,7 +5,8 @@ const {
|
||||||
REST,
|
REST,
|
||||||
Routes,
|
Routes,
|
||||||
ApplicationCommandOptionType,
|
ApplicationCommandOptionType,
|
||||||
ApplicationCommandType
|
ApplicationCommandType,
|
||||||
|
ChannelType
|
||||||
} = require("discord.js");
|
} = require("discord.js");
|
||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const ping = require("ping");
|
const ping = require("ping");
|
||||||
|
@ -25,15 +26,13 @@ const client = new Client({
|
||||||
partials: ['CHANNEL', 'MESSAGE'] // This is important for DM functionality
|
partials: ['CHANNEL', 'MESSAGE'] // This is important for DM functionality
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Commands that should work in DMs (registered globally)
|
||||||
// Original slash commands
|
const globalCommands = [
|
||||||
const slashCommands = [
|
|
||||||
{
|
{
|
||||||
name: "fetch_data",
|
name: "fetch_data",
|
||||||
description: "Fetches data from an API",
|
description: "Fetches data from an API",
|
||||||
type: ApplicationCommandType.ChatInput,
|
type: ApplicationCommandType.ChatInput,
|
||||||
dm_permission: true,
|
dm_permission: true,
|
||||||
|
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
name: "url",
|
name: "url",
|
||||||
|
@ -71,7 +70,6 @@ const slashCommands = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// Add Cody command
|
|
||||||
{
|
{
|
||||||
name: "cody",
|
name: "cody",
|
||||||
description: "Ask Cody (Sourcegraph AI) a coding question",
|
description: "Ask Cody (Sourcegraph AI) a coding question",
|
||||||
|
@ -86,7 +84,6 @@ const slashCommands = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// Add Weather command
|
|
||||||
{
|
{
|
||||||
name: "weather",
|
name: "weather",
|
||||||
description: "Get current weather for a location",
|
description: "Get current weather for a location",
|
||||||
|
@ -101,7 +98,6 @@ const slashCommands = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// Add Minecraft server status command
|
|
||||||
{
|
{
|
||||||
name: "mcstatus",
|
name: "mcstatus",
|
||||||
description: "Check the status of a Minecraft server",
|
description: "Check the status of a Minecraft server",
|
||||||
|
@ -147,7 +143,6 @@ const slashCommands = [
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// Add Anime commands
|
|
||||||
{
|
{
|
||||||
name: "anime",
|
name: "anime",
|
||||||
description: "Get anime-related content",
|
description: "Get anime-related content",
|
||||||
|
@ -236,15 +231,13 @@ const slashCommands = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
// Add to slashCommands array
|
{
|
||||||
{
|
|
||||||
name: "stats",
|
name: "stats",
|
||||||
description: "Show bot and server statistics",
|
description: "Show bot and server statistics",
|
||||||
type: ApplicationCommandType.ChatInput,
|
type: ApplicationCommandType.ChatInput,
|
||||||
dm_permission: true
|
dm_permission: true
|
||||||
},
|
},
|
||||||
// Add to slashCommands array
|
{
|
||||||
{
|
|
||||||
name: "checkport",
|
name: "checkport",
|
||||||
description: "Check if specific ports are open on a domain",
|
description: "Check if specific ports are open on a domain",
|
||||||
type: ApplicationCommandType.ChatInput,
|
type: ApplicationCommandType.ChatInput,
|
||||||
|
@ -263,12 +256,15 @@ const slashCommands = [
|
||||||
required: true,
|
required: true,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// User context menu commands
|
// Commands that only make sense in a guild context
|
||||||
|
const guildCommands = [
|
||||||
|
// Add guild-specific commands here if needed
|
||||||
|
];
|
||||||
|
|
||||||
|
// User context menu commands (should also be registered globally)
|
||||||
const userCommands = [
|
const userCommands = [
|
||||||
{
|
{
|
||||||
name: "User Info",
|
name: "User Info",
|
||||||
|
@ -276,9 +272,18 @@ const userCommands = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const commands = [...slashCommands, ...userCommands];
|
// Function to get existing commands without deleting them
|
||||||
|
async function getExistingCommands(rest, route) {
|
||||||
|
try {
|
||||||
|
return await rest.get(route);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error fetching commands from ${route}:`, error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function updateCommands() {
|
// New function to safely update commands
|
||||||
|
async function updateCommandsSafely() {
|
||||||
if (!process.env.DISCORD_TOKEN || !process.env.CLIENT_ID) {
|
if (!process.env.DISCORD_TOKEN || !process.env.CLIENT_ID) {
|
||||||
console.error("Missing required environment variables: DISCORD_TOKEN or CLIENT_ID");
|
console.error("Missing required environment variables: DISCORD_TOKEN or CLIENT_ID");
|
||||||
return;
|
return;
|
||||||
|
@ -287,26 +292,98 @@ async function updateCommands() {
|
||||||
const rest = new REST({ version: "10" }).setToken(process.env.DISCORD_TOKEN);
|
const rest = new REST({ version: "10" }).setToken(process.env.DISCORD_TOKEN);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log("Fetching existing commands...");
|
console.log("Starting command registration...");
|
||||||
const existingCommands = await rest.get(Routes.applicationCommands(process.env.CLIENT_ID));
|
|
||||||
|
|
||||||
// Delete all existing commands if needed
|
// First, get all existing global commands to check for entry point commands
|
||||||
// for (const command of existingCommands) {
|
const existingGlobalCommands = await getExistingCommands(
|
||||||
// await rest.delete(`${Routes.applicationCommands(process.env.CLIENT_ID)}/${command.id}`);
|
rest,
|
||||||
// console.log(`Deleted command: ${command.name}`);
|
Routes.applicationCommands(process.env.CLIENT_ID)
|
||||||
// }
|
);
|
||||||
|
|
||||||
// Register new commands (slash + user commands)
|
// Find any entry point or special commands we need to preserve
|
||||||
console.log("Registering new commands...");
|
const entryPointCommands = existingGlobalCommands.filter(
|
||||||
await rest.put(Routes.applicationCommands(process.env.CLIENT_ID), { body: commands });
|
cmd => cmd.integration_types && cmd.integration_types.includes(1)
|
||||||
console.log("Commands updated successfully!");
|
);
|
||||||
|
|
||||||
|
// Create a map to track command names we've already added
|
||||||
|
const commandNameMap = new Map();
|
||||||
|
|
||||||
|
// Create a filtered array of commands without duplicates
|
||||||
|
const allGlobalCommands = [];
|
||||||
|
|
||||||
|
// First add global commands
|
||||||
|
for (const cmd of globalCommands) {
|
||||||
|
if (!commandNameMap.has(cmd.name)) {
|
||||||
|
commandNameMap.set(cmd.name, true);
|
||||||
|
allGlobalCommands.push(cmd);
|
||||||
|
} else {
|
||||||
|
console.warn(`Skipping duplicate global command: ${cmd.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then add user commands
|
||||||
|
for (const cmd of userCommands) {
|
||||||
|
if (!commandNameMap.has(cmd.name)) {
|
||||||
|
commandNameMap.set(cmd.name, true);
|
||||||
|
allGlobalCommands.push(cmd);
|
||||||
|
} else {
|
||||||
|
console.warn(`Skipping duplicate user command: ${cmd.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, add entry point commands that don't duplicate existing names
|
||||||
|
for (const cmd of entryPointCommands) {
|
||||||
|
if (!commandNameMap.has(cmd.name)) {
|
||||||
|
commandNameMap.set(cmd.name, true);
|
||||||
|
allGlobalCommands.push(cmd);
|
||||||
|
} else {
|
||||||
|
console.log(`Entry point command "${cmd.name}" already exists, keeping existing definition`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Registering ${allGlobalCommands.length} unique global commands...`);
|
||||||
|
|
||||||
|
// Update global commands (including DM-compatible commands)
|
||||||
|
await rest.put(
|
||||||
|
Routes.applicationCommands(process.env.CLIENT_ID),
|
||||||
|
{ body: allGlobalCommands }
|
||||||
|
);
|
||||||
|
console.log(`Successfully registered ${allGlobalCommands.length} global commands`);
|
||||||
|
|
||||||
|
// If we have guild-specific commands, register them for each guild
|
||||||
|
if (guildCommands.length > 0) {
|
||||||
|
// Wait for client to be ready to access guilds
|
||||||
|
if (!client.isReady()) {
|
||||||
|
await new Promise(resolve => {
|
||||||
|
client.once('ready', resolve);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register guild commands for each guild the bot is in
|
||||||
|
for (const guild of client.guilds.cache.values()) {
|
||||||
|
console.log(`Registering guild commands for ${guild.name} (${guild.id})...`);
|
||||||
|
await rest.put(
|
||||||
|
Routes.applicationGuildCommands(process.env.CLIENT_ID, guild.id),
|
||||||
|
{ body: guildCommands }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
console.log(`Successfully registered ${guildCommands.length} guild commands per server`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("All commands registered successfully!");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error updating commands:", error);
|
console.error("Error updating commands:", error);
|
||||||
|
if (error.code === 50240) {
|
||||||
|
console.error("This error suggests you need to include all Entry Point commands in your update.");
|
||||||
|
console.error("Try using the updateCommandsSafely function which preserves Entry Point commands.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Function to ask Cody a question and parse the streaming response
|
// Function to ask Cody a question and parse the streaming response
|
||||||
async function askCody(question) {
|
async function askCody(question) {
|
||||||
|
// [Function implementation remains the same]
|
||||||
if (!process.env.SOURCEGRAPH_API_KEY) {
|
if (!process.env.SOURCEGRAPH_API_KEY) {
|
||||||
throw new Error("SOURCEGRAPH_API_KEY is not set in environment variables");
|
throw new Error("SOURCEGRAPH_API_KEY is not set in environment variables");
|
||||||
}
|
}
|
||||||
|
@ -338,7 +415,6 @@ async function askCody(question) {
|
||||||
responseType: 'text'
|
responseType: 'text'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Parse the streaming response
|
|
||||||
const events = response.data.split('\n\n').filter(line => line.trim() !== '');
|
const events = response.data.split('\n\n').filter(line => line.trim() !== '');
|
||||||
|
|
||||||
let fullCompletion = '';
|
let fullCompletion = '';
|
||||||
|
@ -353,7 +429,6 @@ async function askCody(question) {
|
||||||
try {
|
try {
|
||||||
const jsonData = JSON.parse(dataLine.substring(6));
|
const jsonData = JSON.parse(dataLine.substring(6));
|
||||||
if (jsonData.completion) {
|
if (jsonData.completion) {
|
||||||
// This is the full completion up to this point, not just an increment
|
|
||||||
fullCompletion = jsonData.completion;
|
fullCompletion = jsonData.completion;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -373,10 +448,16 @@ async function askCody(question) {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.once("ready", async () => {
|
client.once("ready", async () => {
|
||||||
console.log(`Logged in as ${client.user.tag}`);
|
console.log(`Logged in as ${client.user.tag}`);
|
||||||
await updateCommands();
|
|
||||||
|
|
||||||
|
// Register commands after the bot is ready
|
||||||
|
await updateCommandsSafely();
|
||||||
|
|
||||||
|
// Send startup notification
|
||||||
|
if (process.env.OWNER_ID) {
|
||||||
|
try {
|
||||||
const ownerId = process.env.OWNER_ID;
|
const ownerId = process.env.OWNER_ID;
|
||||||
const owner = await client.users.fetch(ownerId);
|
const owner = await client.users.fetch(ownerId);
|
||||||
const startupEmbed = {
|
const startupEmbed = {
|
||||||
|
@ -401,14 +482,19 @@ client.once("ready", async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
await owner.send({ embeds: [startupEmbed] });
|
await owner.send({ embeds: [startupEmbed] });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to send startup notification:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
client.on("interactionCreate", async (interaction) => {
|
client.on("interactionCreate", async (interaction) => {
|
||||||
|
// Add debug logging to help diagnose DM issues
|
||||||
|
console.log(`Received interaction: ${interaction.commandName} | Channel type: ${interaction.channel.type} | DM: ${interaction.channel.type === ChannelType.DM}`);
|
||||||
|
|
||||||
// Handle slash commands
|
// Handle slash commands
|
||||||
if (interaction.isChatInputCommand()) {
|
if (interaction.isChatInputCommand()) {
|
||||||
|
try {
|
||||||
switch (interaction.commandName) {
|
switch (interaction.commandName) {
|
||||||
case "fetch_data":
|
case "fetch_data":
|
||||||
try {
|
try {
|
||||||
|
@ -464,6 +550,7 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
await interaction.editReply({ content: "Failed to ping.", ephemeral: true });
|
await interaction.editReply({ content: "Failed to ping.", ephemeral: true });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "server_status":
|
case "server_status":
|
||||||
try {
|
try {
|
||||||
const response = await axios.get("https://blahaj.tr:2589/status");
|
const response = await axios.get("https://blahaj.tr:2589/status");
|
||||||
|
@ -503,6 +590,7 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
await interaction.reply({ content: "Failed to get status.", ephemeral: true });
|
await interaction.reply({ content: "Failed to get status.", ephemeral: true });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "cody":
|
case "cody":
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
@ -543,7 +631,8 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
content: "Sorry, I couldn't get an answer from Cody. Please try again later.",
|
content: "Sorry, I couldn't get an answer from Cody. Please try again later.",
|
||||||
ephemeral: true
|
ephemeral: true
|
||||||
});
|
});
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case "weather":
|
case "weather":
|
||||||
try {
|
try {
|
||||||
|
@ -599,14 +688,13 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// In the mcstatus command handler, replace the thumbnail section with this:
|
// Handle all the other commands the same way as in the original code
|
||||||
case "mcstatus":
|
case "mcstatus":
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
const serverAddress = interaction.options.getString("server");
|
const serverAddress = interaction.options.getString("server");
|
||||||
const isBedrock = interaction.options.getBoolean("bedrock") ?? false;
|
const isBedrock = interaction.options.getBoolean("bedrock") ?? false;
|
||||||
|
|
||||||
// Determine which API endpoint to use based on server type
|
|
||||||
const apiUrl = isBedrock
|
const apiUrl = isBedrock
|
||||||
? `https://api.mcsrvstat.us/bedrock/2/${encodeURIComponent(serverAddress)}`
|
? `https://api.mcsrvstat.us/bedrock/2/${encodeURIComponent(serverAddress)}`
|
||||||
: `https://api.mcsrvstat.us/2/${encodeURIComponent(serverAddress)}`;
|
: `https://api.mcsrvstat.us/2/${encodeURIComponent(serverAddress)}`;
|
||||||
|
@ -621,11 +709,9 @@ case "mcstatus":
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a rich embed for the server status
|
|
||||||
const serverEmbed = {
|
const serverEmbed = {
|
||||||
title: `Minecraft Server Status: ${serverAddress}`,
|
title: `Minecraft Server Status: ${serverAddress}`,
|
||||||
color: 0x44FF44, // Green color
|
color: 0x44FF44,
|
||||||
// Use a default Minecraft image instead of trying to use the base64 icon
|
|
||||||
thumbnail: {
|
thumbnail: {
|
||||||
url: 'https://www.minecraft.net/content/dam/games/minecraft/key-art/MC_The-Wild-Update_540x300.jpg'
|
url: 'https://www.minecraft.net/content/dam/games/minecraft/key-art/MC_The-Wild-Update_540x300.jpg'
|
||||||
},
|
},
|
||||||
|
@ -638,14 +724,11 @@ case "mcstatus":
|
||||||
timestamp: new Date()
|
timestamp: new Date()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add MOTD if available
|
|
||||||
if (data.motd && data.motd.clean && data.motd.clean.length > 0) {
|
if (data.motd && data.motd.clean && data.motd.clean.length > 0) {
|
||||||
serverEmbed.description = `**MOTD:**\n${data.motd.clean.join('\n')}`;
|
serverEmbed.description = `**MOTD:**\n${data.motd.clean.join('\n')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add player list if available and not empty
|
|
||||||
if (data.players && data.players.list && data.players.list.length > 0) {
|
if (data.players && data.players.list && data.players.list.length > 0) {
|
||||||
// Limit to first 20 players to avoid hitting Discord's limits
|
|
||||||
const playerList = data.players.list.slice(0, 20).join(', ');
|
const playerList = data.players.list.slice(0, 20).join(', ');
|
||||||
const hasMore = data.players.list.length > 20;
|
const hasMore = data.players.list.length > 20;
|
||||||
|
|
||||||
|
@ -670,7 +753,6 @@ case "mcstatus":
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
const animalType = interaction.options.getString("type");
|
const animalType = interaction.options.getString("type");
|
||||||
|
|
||||||
// Get animal image
|
|
||||||
const imageResponse = await axios.get(`https://some-random-api.com/animal/${animalType}`);
|
const imageResponse = await axios.get(`https://some-random-api.com/animal/${animalType}`);
|
||||||
const imageUrl = imageResponse.data.image;
|
const imageUrl = imageResponse.data.image;
|
||||||
|
|
||||||
|
@ -691,25 +773,24 @@ case "mcstatus":
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "anime":
|
case "anime":
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
const action = interaction.options.getString("action");
|
const type = interaction.options.getString("type");
|
||||||
|
|
||||||
let apiUrl;
|
let apiUrl;
|
||||||
let isQuote = false;
|
let isQuote = false;
|
||||||
|
|
||||||
if (action === "quote") {
|
if (type === "quote") {
|
||||||
apiUrl = "https://some-random-api.ml/animu/quote";
|
apiUrl = "https://some-random-api.ml/animu/quote";
|
||||||
isQuote = true;
|
isQuote = true;
|
||||||
} else {
|
} else {
|
||||||
apiUrl = `https://some-random-api.ml/animu/${action}`;
|
apiUrl = `https://some-random-api.ml/animu/${type}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await axios.get(apiUrl);
|
const response = await axios.get(apiUrl);
|
||||||
|
|
||||||
if (isQuote) {
|
if (isQuote) {
|
||||||
// Handle quote response
|
|
||||||
const quote = response.data.sentence;
|
const quote = response.data.sentence;
|
||||||
const character = response.data.character;
|
const character = response.data.character;
|
||||||
const anime = response.data.anime;
|
const anime = response.data.anime;
|
||||||
|
@ -728,10 +809,9 @@ case "anime":
|
||||||
|
|
||||||
await interaction.editReply({ embeds: [quoteEmbed] });
|
await interaction.editReply({ embeds: [quoteEmbed] });
|
||||||
} else {
|
} else {
|
||||||
// Handle GIF response
|
|
||||||
const gifUrl = response.data.link;
|
const gifUrl = response.data.link;
|
||||||
|
|
||||||
const actionTitle = action.charAt(0).toUpperCase() + action.slice(1).replace('-', ' ');
|
const actionTitle = type.charAt(0).toUpperCase() + type.slice(1).replace('-', ' ');
|
||||||
|
|
||||||
const gifEmbed = {
|
const gifEmbed = {
|
||||||
title: `Anime ${actionTitle}`,
|
title: `Anime ${actionTitle}`,
|
||||||
|
@ -751,6 +831,7 @@ case "anime":
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "checkdns":
|
case "checkdns":
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
@ -814,6 +895,7 @@ case "anime":
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "traceroute":
|
case "traceroute":
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
@ -869,6 +951,7 @@ case "anime":
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "whois":
|
case "whois":
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
@ -917,6 +1000,7 @@ case "anime":
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "stats":
|
case "stats":
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
@ -942,7 +1026,7 @@ case "anime":
|
||||||
`**Servers:** ${client.guilds.cache.size}`,
|
`**Servers:** ${client.guilds.cache.size}`,
|
||||||
`**Users:** ${client.users.cache.size}`,
|
`**Users:** ${client.users.cache.size}`,
|
||||||
`**Channels:** ${client.channels.cache.size}`,
|
`**Channels:** ${client.channels.cache.size}`,
|
||||||
`**Commands:** ${slashCommands.length}`
|
`**Commands:** ${globalCommands.length}`
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
inline: true
|
inline: true
|
||||||
},
|
},
|
||||||
|
@ -975,6 +1059,7 @@ case "anime":
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "checkport":
|
case "checkport":
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply();
|
await interaction.deferReply();
|
||||||
|
@ -1030,6 +1115,98 @@ case "anime":
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
default:
|
||||||
}});
|
await interaction.reply({
|
||||||
client.login(process.env.DISCORD_TOKEN);
|
content: `Command '${interaction.commandName}' not implemented yet.`,
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error executing command ${interaction.commandName}:`, error);
|
||||||
|
|
||||||
|
// Try to respond if we haven't already
|
||||||
|
try {
|
||||||
|
const replyMethod = interaction.deferred ? interaction.editReply : interaction.reply;
|
||||||
|
await replyMethod.call(interaction, {
|
||||||
|
content: "An error occurred while executing this command.",
|
||||||
|
ephemeral: true
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Could not send error response:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (interaction.isUserContextMenuCommand()) {
|
||||||
|
// Handle user context menu commands
|
||||||
|
if (interaction.commandName === "User Info") {
|
||||||
|
const user = interaction.targetUser;
|
||||||
|
|
||||||
|
const userInfoEmbed = {
|
||||||
|
title: "User Information",
|
||||||
|
color: 0x9B59B6,
|
||||||
|
thumbnail: { url: user.displayAvatarURL({ dynamic: true }) },
|
||||||
|
fields: [
|
||||||
|
{ name: "Username", value: user.username, inline: true },
|
||||||
|
{ name: "User ID", value: user.id, inline: true },
|
||||||
|
{ name: "Account Created", value: `<t:${Math.floor(user.createdTimestamp / 1000)}:R>`, inline: true }
|
||||||
|
],
|
||||||
|
footer: { text: "User Information" },
|
||||||
|
timestamp: new Date()
|
||||||
|
};
|
||||||
|
|
||||||
|
await interaction.reply({ embeds: [userInfoEmbed], ephemeral: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle guild join events to register guild-specific commands if needed
|
||||||
|
client.on("guildCreate", async (guild) => {
|
||||||
|
console.log(`Joined new guild: ${guild.name} (${guild.id})`);
|
||||||
|
|
||||||
|
if (guildCommands.length > 0) {
|
||||||
|
try {
|
||||||
|
console.log(`Registering guild commands for ${guild.name}...`);
|
||||||
|
const rest = new REST({ version: "10" }).setToken(process.env.DISCORD_TOKEN);
|
||||||
|
|
||||||
|
await rest.put(
|
||||||
|
Routes.applicationGuildCommands(process.env.CLIENT_ID, guild.id),
|
||||||
|
{ body: guildCommands }
|
||||||
|
);
|
||||||
|
console.log(`Successfully registered guild commands for ${guild.name}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error registering guild commands for ${guild.name}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify owner if configured
|
||||||
|
if (process.env.OWNER_ID) {
|
||||||
|
try {
|
||||||
|
const owner = await client.users.fetch(process.env.OWNER_ID);
|
||||||
|
const guildJoinEmbed = {
|
||||||
|
title: "New Guild Joined",
|
||||||
|
color: 0x00ff00,
|
||||||
|
fields: [
|
||||||
|
{ name: "Guild Name", value: guild.name, inline: true },
|
||||||
|
{ name: "Guild ID", value: guild.id, inline: true },
|
||||||
|
{ name: "Member Count", value: guild.memberCount.toString(), inline: true }
|
||||||
|
],
|
||||||
|
timestamp: new Date(),
|
||||||
|
footer: { text: "Guild Join Event" }
|
||||||
|
};
|
||||||
|
|
||||||
|
await owner.send({ embeds: [guildJoinEmbed] });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to notify owner of guild join:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
process.on('unhandledRejection', error => {
|
||||||
|
console.error('Unhandled promise rejection:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start the bot
|
||||||
|
client.login(process.env.DISCORD_TOKEN).catch(error => {
|
||||||
|
console.error("Failed to login:", error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue