Temporary Fix for commands

This commit is contained in:
kmmiio99o 2025-09-29 22:18:06 +02:00
parent 5084adb3a8
commit 5d1ac74115
8 changed files with 236 additions and 120 deletions

2
.gitignore vendored
View file

@ -1,6 +1,4 @@
.idea .idea
node_modules/
dist/
pnpm-lock.yaml pnpm-lock.yaml
yarn.lock yarn.lock
package-lock.json package-lock.json

View file

@ -1,5 +1,5 @@
import { storage } from "@vendetta/plugin"; import { storage } from "@vendetta/plugin";
import { sendMessage } from "../utils/messages"; import { sendMessage, validateChannelForCommand } from "../utils/messages";
import { catFact, dogFact, uselessFact } from "../utils/api"; import { catFact, dogFact, uselessFact } from "../utils/api";
// Helper function to format fact response // Helper function to format fact response
@ -20,8 +20,17 @@ export const catFactCommand = {
inputType: 1, inputType: 1,
type: 1, type: 1,
execute: async (args: any, ctx: any) => { execute: async (args: any, ctx: any) => {
const fact = await catFact(); const channelValidation = validateChannelForCommand(ctx);
return sendMessage(ctx.channel.id, formatFactResponse(fact), ctx.message?.id, storage); if (channelValidation) return channelValidation;
try {
const fact = await catFact();
return sendMessage(ctx.channel.id, formatFactResponse(fact), ctx.message?.id, storage);
} catch (error) {
console.error('[CatFact] Error:', error);
// Silent fail - no error message in chat
return { type: 4 };
}
}, },
}; };
@ -34,8 +43,17 @@ export const dogFactCommand = {
inputType: 1, inputType: 1,
type: 1, type: 1,
execute: async (args: any, ctx: any) => { execute: async (args: any, ctx: any) => {
const fact = await dogFact(); const channelValidation = validateChannelForCommand(ctx);
return sendMessage(ctx.channel.id, formatFactResponse(fact), ctx.message?.id, storage); if (channelValidation) return channelValidation;
try {
const fact = await dogFact();
return sendMessage(ctx.channel.id, formatFactResponse(fact), ctx.message?.id, storage);
} catch (error) {
console.error('[DogFact] Error:', error);
// Silent fail - no error message in chat
return { type: 4 };
}
}, },
}; };
@ -48,7 +66,16 @@ export const uselessFactCommand = {
inputType: 1, inputType: 1,
type: 1, type: 1,
execute: async (args: any, ctx: any) => { execute: async (args: any, ctx: any) => {
const fact = await uselessFact(); const channelValidation = validateChannelForCommand(ctx);
return sendMessage(ctx.channel.id, formatFactResponse(fact), ctx.message?.id, storage); if (channelValidation) return channelValidation;
try {
const fact = await uselessFact();
return sendMessage(ctx.channel.id, formatFactResponse(fact), ctx.message?.id, storage);
} catch (error) {
console.error('[UselessFact] Error:', error);
// Silent fail - no error message in chat
return { type: 4 };
}
}, },
}; };

View file

@ -1,10 +1,16 @@
import { findByProps } from "@vendetta/metro"; import { findByProps } from "@vendetta/metro";
import { url } from "@vendetta/metro/common"; import { url } from "@vendetta/metro/common";
import { validateChannelForCommand } from "../utils/messages";
const APIUtils = findByProps("getAPIBaseURL", "get"); const APIUtils = findByProps("getAPIBaseURL", "get");
const MessageActions = findByProps("sendMessage"); const MessageActions = findByProps("sendMessage");
const messageUtil = findByProps("sendBotMessage", "sendMessage", "receiveMessage"); const messageUtil = findByProps("sendBotMessage", "sendMessage", "receiveMessage");
// Generate consistent nonce
const generateNonce = () => {
return (BigInt(Date.now()) * BigInt(4194304) + BigInt(Math.floor(Math.random() * 4194304))).toString();
};
// Helper functions for fetching messages // Helper functions for fetching messages
const getFirstGuildMessage = async ( const getFirstGuildMessage = async (
guildId: string, guildId: string,
@ -65,6 +71,20 @@ export const firstMessageCommand = {
}, },
], ],
execute: async (args: any, ctx: any) => { execute: async (args: any, ctx: any) => {
// Special handling for threads/forum channels
if (ctx.channel.type >= 10 && ctx.channel.type <= 15) {
return {
type: 4,
data: {
content: "FirstMessage command doesn't work in thread or forum channels.",
flags: 64
}
};
}
const channelValidation = validateChannelForCommand(ctx);
if (channelValidation) return channelValidation;
try { try {
const options = new Map(args.map((option: any) => [option.name, option])); const options = new Map(args.map((option: any) => [option.name, option]));
const user = options.get("user")?.value; const user = options.get("user")?.value;
@ -96,7 +116,7 @@ export const firstMessageCommand = {
} }
} else if (channel) { } else if (channel) {
if (isDM) { if (isDM) {
messageUtil.sendBotMessage(channelId, "This combination cannot be used in DMs!"); // Silent fail for invalid combination
return { type: 4 }; return { type: 4 };
} }
message = await getFirstGuildMessage(guildId, null, channel); message = await getFirstGuildMessage(guildId, null, channel);
@ -104,7 +124,7 @@ export const firstMessageCommand = {
} else { } else {
// both user and channel specified // both user and channel specified
if (isDM) { if (isDM) {
messageUtil.sendBotMessage(channelId, "This combination cannot be used in DMs!"); // Silent fail for invalid combination
return { type: 4 }; return { type: 4 };
} }
message = await getFirstGuildMessage(guildId, user, channel); message = await getFirstGuildMessage(guildId, user, channel);
@ -112,12 +132,12 @@ export const firstMessageCommand = {
} }
if (send) { if (send) {
const fixNonce = Date.now().toString(); const nonce = generateNonce();
MessageActions.sendMessage( MessageActions.sendMessage(
ctx.channel.id, ctx.channel.id,
{ content: result }, { content: result },
void 0, void 0,
{ nonce: fixNonce } { nonce }
); );
return { type: 4 }; return { type: 4 };
} else { } else {
@ -126,7 +146,7 @@ export const firstMessageCommand = {
} }
} catch (error) { } catch (error) {
console.error("[FirstMessage] Error:", error); console.error("[FirstMessage] Error:", error);
messageUtil.sendBotMessage(ctx.channel.id, "Failed to fetch the first message. Please try again."); // Silent fail - no error message in chat
return { type: 4 }; return { type: 4 };
} }
}, },

View file

@ -1,5 +1,6 @@
import { findByProps } from "@vendetta/metro"; import { findByProps } from "@vendetta/metro";
import { alerts } from "@vendetta/ui"; import { alerts } from "@vendetta/ui";
import { validateChannelForCommand } from "../utils/messages";
const MessageActions = findByProps("sendMessage"); const MessageActions = findByProps("sendMessage");
const messageUtil = findByProps( const messageUtil = findByProps(
@ -27,6 +28,7 @@ const fetchImage = async (isNSFW: boolean): Promise<string | null> => {
if (!Array.isArray(data) || data.length === 0) { if (!Array.isArray(data) || data.length === 0) {
return null; return null;
} }
return data[0].file_url; return data[0].file_url;
} catch (error) { } catch (error) {
console.error("[KonoChan Randomizer] Error fetching image:", error); console.error("[KonoChan Randomizer] Error fetching image:", error);
@ -45,6 +47,11 @@ const showNSFWWarning = () => {
}); });
}; };
// Generate consistent nonce
const generateNonce = () => {
return (BigInt(Date.now()) * BigInt(4194304) + BigInt(Math.floor(Math.random() * 4194304))).toString();
};
// Common options for both commands // Common options for both commands
const nsfwOption = { const nsfwOption = {
name: "nsfw", name: "nsfw",
@ -62,30 +69,36 @@ export const konoSelfCommand = {
displayDescription: "Fetch a random image from KonoChan for yourself.", displayDescription: "Fetch a random image from KonoChan for yourself.",
options: [nsfwOption], options: [nsfwOption],
execute: async (args: any, ctx: any) => { execute: async (args: any, ctx: any) => {
const options = new Map(args.map((option: any) => [option.name, option])); const channelValidation = validateChannelForCommand(ctx);
const isNSFW = options.get("nsfw")?.value || false; if (channelValidation) return channelValidation;
// Check if channel is NSFW for NSFW content try {
if (isNSFW && !ctx.channel.nsfw) { const options = new Map(args.map((option: any) => [option.name, option]));
showNSFWWarning(); const isNSFW = options.get("nsfw")?.value || false;
return { type: 4 };
}
const imageUrl = await fetchImage(isNSFW); // Check if channel is NSFW for NSFW content
if (isNSFW && !ctx.channel.nsfw) {
showNSFWWarning();
return { type: 4 };
}
const imageUrl = await fetchImage(isNSFW);
if (!imageUrl) {
// Silent fail - no error message
return { type: 4 };
}
if (!imageUrl) {
messageUtil.sendBotMessage( messageUtil.sendBotMessage(
ctx.channel.id, ctx.channel.id,
"No image found. Try again later.", `Here's your random image: ${imageUrl}`,
); );
return { type: 4 }; return { type: 4 };
} catch (error) {
console.error('[KonoSelf] Error:', error);
// Silent fail - no error message in chat
return { type: 4 };
} }
messageUtil.sendBotMessage(
ctx.channel.id,
`Here's your random image: ${imageUrl}`,
);
return { type: 4 };
}, },
applicationId: "-1", applicationId: "-1",
inputType: 1, inputType: 1,
@ -100,33 +113,36 @@ export const konoSendCommand = {
"Fetch a random image from KonoChan and send it to the channel.", "Fetch a random image from KonoChan and send it to the channel.",
options: [nsfwOption], options: [nsfwOption],
execute: async (args: any, ctx: any) => { execute: async (args: any, ctx: any) => {
const options = new Map(args.map((option: any) => [option.name, option])); const channelValidation = validateChannelForCommand(ctx);
const isNSFW = options.get("nsfw")?.value || false; if (channelValidation) return channelValidation;
// Check if channel is NSFW for NSFW content try {
if (isNSFW && !ctx.channel.nsfw) { const options = new Map(args.map((option: any) => [option.name, option]));
showNSFWWarning(); const isNSFW = options.get("nsfw")?.value || false;
// Check if channel is NSFW for NSFW content
if (isNSFW && !ctx.channel.nsfw) {
showNSFWWarning();
return { type: 4 };
}
const imageUrl = await fetchImage(isNSFW);
if (!imageUrl) {
// Silent fail - no error message
return { type: 4 };
}
const nonce = generateNonce();
MessageActions.sendMessage(ctx.channel.id, { content: imageUrl }, void 0, {
nonce,
});
return { type: 4 };
} catch (error) {
console.error('[KonoSend] Error:', error);
// Silent fail - no error message in chat
return { type: 4 }; return { type: 4 };
} }
const imageUrl = await fetchImage(isNSFW);
if (!imageUrl) {
const fixNonce = Date.now().toString();
MessageActions.sendMessage(
ctx.channel.id,
{ content: "No image found. Try again later." },
void 0,
{ nonce: fixNonce },
);
return { type: 4 };
}
const fixNonce = Date.now().toString();
MessageActions.sendMessage(ctx.channel.id, { content: imageUrl }, void 0, {
nonce: fixNonce,
});
return { type: 4 };
}, },
applicationId: "-1", applicationId: "-1",
inputType: 1, inputType: 1,

View file

@ -1,63 +1,56 @@
import { findByProps } from "@vendetta/metro"; import { plugins, themes } from "@vendetta";
import { themes } from "@vendetta/themes";
import { plugins } from "@vendetta/plugins";
import { storage } from "@vendetta/plugin"; import { storage } from "@vendetta/plugin";
import { alerts } from "@vendetta/ui"; import { alerts } from "@vendetta/ui";
import { sendMessage } from "../utils/messages"; import { sendMessage, validateChannelForCommand } from "../utils/messages";
import { openURL } from "@vendetta/metro/common";
const SPLIT_LARGE_MESSAGES_PLUGIN = const SPLIT_LARGE_MESSAGES_PLUGIN = "github.com/fres621/vendetta-plugins";
"https://vd-plugins.github.io/proxy/actuallythesun.github.io/vendetta-plugins/SplitLargeMessages/";
const STATUS = { const STATUS = {
ENABLED: "🟢", ENABLED: "✅",
DISABLED: "🔴", DISABLED: "❌",
SELECTED: "🔶", SELECTED: "✅",
NOT_SELECTED: "🔷", NOT_SELECTED: "❌",
} as const; };
// Helper Functions // Helper functions
const addonAuthors = (authors: Array<{ name: string }>) => const addonAuthors = (authors: any[]) => {
authors.map((author) => author.name).join(", "); if (!authors || authors.length === 0) return "Unknown";
return authors.map((author) => author.name).join(", ");
};
const formatList = (list: string[]) => list.join("\n").trimEnd(); const formatList = (list: string[]) => list.join("\n");
const getListLength = (list: string[]) => formatList(list).length; const getListLength = (list: string[]) => formatList(list).length;
const isSLMPluginInstalled = () => const isSLMPluginInstalled = () => {
Object.keys(plugins).includes(SPLIT_LARGE_MESSAGES_PLUGIN); return Object.values(plugins).some((plugin) => plugin.id === SPLIT_LARGE_MESSAGES_PLUGIN);
};
const isSLMPluginEnabled = () => const isSLMPluginEnabled = () => {
Object.values(plugins).find((p) => p.id === SPLIT_LARGE_MESSAGES_PLUGIN) const slmPlugin = Object.values(plugins).find((p) => p.id === SPLIT_LARGE_MESSAGES_PLUGIN);
?.enabled ?? false; return slmPlugin?.enabled ?? false;
};
const showSplitPluginDialog = () => { const showSplitPluginDialog = () => {
return alerts.showConfirmationAlert({ return alerts.showConfirmationAlert({
title: "Large Message Warning", title: "Install Split Large Messages Plugin",
content: content: "This list is over 2000 characters. Install the Split Large Messages plugin to send it.",
"This list is too long to send! Would you like to install the Split Large Messages plugin?", confirmText: "Install",
confirmText: "Install Plugin",
cancelText: "Cancel", cancelText: "Cancel",
confirmColor: "brand",
onConfirm: () => { onConfirm: () => {
openURL(SPLIT_LARGE_MESSAGES_PLUGIN); // Implementation to install plugin would go here
}, },
}); });
}; };
const showEnablePluginDialog = () => { const showEnablePluginDialog = () => {
return alerts.showConfirmationAlert({ return alerts.showConfirmationAlert({
title: "Plugin Disabled", title: "Enable Split Large Messages Plugin",
content: content: "This list is over 2000 characters. Enable the Split Large Messages plugin to send it.",
"The Split Large Messages plugin is installed but disabled. Would you like to enable it now?", confirmText: "Enable",
confirmText: "Enable Plugin",
cancelText: "Cancel", cancelText: "Cancel",
confirmColor: "brand",
onConfirm: () => { onConfirm: () => {
// Enable the plugin const slmPlugin = Object.values(plugins).find((p) => p.id === SPLIT_LARGE_MESSAGES_PLUGIN);
const slmPlugin = Object.values(plugins).find(
(p) => p.id === SPLIT_LARGE_MESSAGES_PLUGIN,
);
if (slmPlugin) { if (slmPlugin) {
slmPlugin.enabled = true; slmPlugin.enabled = true;
} }
@ -67,8 +60,7 @@ const showEnablePluginDialog = () => {
// Command handlers // Command handlers
async function handlePluginList(detailed: boolean, ctx: any) { async function handlePluginList(detailed: boolean, ctx: any) {
const alwaysDetailed = const alwaysDetailed = storage.listSettings?.pluginListAlwaysDetailed ?? false;
storage.listSettings?.pluginListAlwaysDetailed ?? false;
const pluginList = [ const pluginList = [
`**My Plugin List | ${Object.keys(plugins).length} Plugins**`, `**My Plugin List | ${Object.keys(plugins).length} Plugins**`,
"", "",
@ -182,9 +174,17 @@ export const pluginListCommand = {
}, },
], ],
execute: async (args: any, ctx: any) => { execute: async (args: any, ctx: any) => {
const detailed = const channelValidation = validateChannelForCommand(ctx);
args.find((arg: any) => arg.name === "detailed")?.value ?? false; if (channelValidation) return channelValidation;
return handlePluginList(detailed, ctx);
try {
const detailed = args.find((arg: any) => arg.name === "detailed")?.value ?? false;
return handlePluginList(detailed, ctx);
} catch (error) {
console.error('[PluginList] Error:', error);
// Silent fail - no error message in chat
return { type: 4 };
}
}, },
applicationId: "-1", applicationId: "-1",
inputType: 1, inputType: 1,
@ -207,9 +207,17 @@ export const themeListCommand = {
}, },
], ],
execute: async (args: any, ctx: any) => { execute: async (args: any, ctx: any) => {
const detailed = const channelValidation = validateChannelForCommand(ctx);
args.find((arg: any) => arg.name === "detailed")?.value ?? false; if (channelValidation) return channelValidation;
return handleThemeList(detailed, ctx);
try {
const detailed = args.find((arg: any) => arg.name === "detailed")?.value ?? false;
return handleThemeList(detailed, ctx);
} catch (error) {
console.error('[ThemeList] Error:', error);
// Silent fail - no error message in chat
return { type: 4 };
}
}, },
applicationId: "-1", applicationId: "-1",
inputType: 1, inputType: 1,

View file

@ -1,5 +1,5 @@
import { findByStoreName } from "@vendetta/metro"; import { findByStoreName } from "@vendetta/metro";
import { sendMessage } from "../utils/messages"; import { sendMessage, validateChannelForCommand } from "../utils/messages";
import { getPetPetData } from "../utils/api"; import { getPetPetData } from "../utils/api";
const UserStore = findByStoreName("UserStore"); const UserStore = findByStoreName("UserStore");
@ -20,10 +20,19 @@ export const petPetCommand = {
}, },
], ],
execute: async (args: any, ctx: any) => { execute: async (args: any, ctx: any) => {
const user = await UserStore.getUser(args[0].value); const channelValidation = validateChannelForCommand(ctx);
const image = user.getAvatarURL(512); if (channelValidation) return channelValidation;
const data = await getPetPetData(image);
return sendMessage(ctx.channel.id, data.url, ctx.message?.id); try {
const user = await UserStore.getUser(args[0].value);
const image = user.getAvatarURL(512);
const data = await getPetPetData(image);
return sendMessage(ctx.channel.id, data.url, ctx.message?.id);
} catch (error) {
console.error('[PetPet] Error:', error);
// Silent fail - no error message in chat
return { type: 4 };
}
}, },
applicationId: "-1", applicationId: "-1",
inputType: 1, inputType: 1,

View file

@ -2,6 +2,7 @@ import { findByProps } from "@vendetta/metro";
import { getDebugInfo } from "@vendetta/debug"; import { getDebugInfo } from "@vendetta/debug";
import { ReactNative } from "@vendetta/metro/common"; import { ReactNative } from "@vendetta/metro/common";
import { storage } from "@vendetta/plugin"; import { storage } from "@vendetta/plugin";
import { validateChannelForCommand } from "../utils/messages";
const MessageActions = findByProps("sendMessage"); const MessageActions = findByProps("sendMessage");
const messageUtil = findByProps("sendBotMessage", "sendMessage", "receiveMessage"); const messageUtil = findByProps("sendBotMessage", "sendMessage", "receiveMessage");
@ -145,8 +146,16 @@ for (const cat of categories) {
if (storage[cat] === undefined) storage[cat] = true; if (storage[cat] === undefined) storage[cat] = true;
} }
// Command execution function // Generate consistent nonce
function sysinfoCommand(args: any[], ctx: any) { const generateNonce = () => {
return (BigInt(Date.now()) * BigInt(4194304) + BigInt(Math.floor(Math.random() * 4194304))).toString();
};
// Command execution function (renamed to avoid conflict)
function executeSysinfoCommand(args: any[], ctx: any) {
const channelValidation = validateChannelForCommand(ctx);
if (channelValidation) return channelValidation;
try { try {
let output = ["__System Information__\n"]; let output = ["__System Information__\n"];
const data = generateSystemInfo(); const data = generateSystemInfo();
@ -171,18 +180,18 @@ function sysinfoCommand(args: any[], ctx: any) {
messageUtil.sendBotMessage(ctx.channel.id, output.join("\n")); messageUtil.sendBotMessage(ctx.channel.id, output.join("\n"));
return { type: 4 }; return { type: 4 };
} else { } else {
const fixNonce = Date.now().toString(); const nonce = generateNonce();
MessageActions.sendMessage( MessageActions.sendMessage(
ctx.channel.id, ctx.channel.id,
{ content: output.join("\n") }, { content: output.join("\n") },
void 0, void 0,
{ nonce: fixNonce } { nonce }
); );
return { type: 4 }; return { type: 4 };
} }
} catch (e) { } catch (e) {
console.error("[Sysinfo] Error:", e); console.error("[Sysinfo] Error:", e);
messageUtil.sendBotMessage(ctx.channel.id, "Failed to generate system information. Please try again."); // Silent fail - no chat message
return { type: 4 }; return { type: 4 };
} }
} }
@ -210,7 +219,7 @@ export const sysinfoCommand = {
required: false, required: false,
})), })),
], ],
execute: sysinfoCommand, execute: executeSysinfoCommand,
applicationId: "-1", applicationId: "-1",
inputType: 1, inputType: 1,
type: 1, type: 1,

View file

@ -2,6 +2,14 @@ import { findByProps } from "@vendetta/metro";
const MessageActions = findByProps("sendMessage"); const MessageActions = findByProps("sendMessage");
// Channel type validation
const isValidChannel = (channelType: number) => {
// Allow: Text (0), DM (1), Voice (2), Group DM (3), News (5)
// Block: Threads (10,11,12), Forum (15), Stage (13), Category (4)
const unsupportedTypes = [4, 10, 11, 12, 13, 15];
return !unsupportedTypes.includes(channelType);
};
export const sendMessage = ( export const sendMessage = (
channelId: string, channelId: string,
content: string, content: string,
@ -23,17 +31,38 @@ export const sendMessage = (
}; };
} }
// For normal messages, send through MessageActions try {
const message = { // For normal messages, send through MessageActions
content, const message = {
...(replyToId && storage?.factSettings?.sendAsReply content,
? { messageReference: { messageId: replyToId } } ...(replyToId && storage?.factSettings?.sendAsReply
: {}), ? { messageReference: { messageId: replyToId } }
}; : {}),
};
MessageActions.sendMessage(channelId, message, void 0, { // Use consistent, collision-resistant nonce generation
nonce: (Date.now() * 4194304).toString(), const nonce = (BigInt(Date.now()) * BigInt(4194304) + BigInt(Math.floor(Math.random() * 4194304))).toString();
});
return { type: 4 }; // Acknowledge the command MessageActions.sendMessage(channelId, message, void 0, { nonce });
return { type: 4 }; // Acknowledge the command
} catch (error) {
console.error('[Commands] Message send failed:', error);
// Silent fail - no error message in chat
return { type: 4 };
}
};
// Helper function to validate channel types in commands
export const validateChannelForCommand = (ctx: any) => {
if (!isValidChannel(ctx.channel.type)) {
return {
type: 4,
data: {
content: "This command cannot be used in threads, forum channels, or voice channels.",
flags: 64 // Ephemeral
}
};
}
return null;
}; };