Add KonoChan image commands and improve list handling
- Add konoself and konosend commands for fetching images from KonoChan - Improve plugin/theme list commands to use showAlert for long lists - Refactor sendMessage to handle async and prevent double sending - Add showAlert utility for error toasts
This commit is contained in:
parent
07261a2df4
commit
cd4d414a0c
4 changed files with 130 additions and 28 deletions
|
|
@ -7,6 +7,7 @@ import {
|
|||
} from "./src/commands/facts";
|
||||
import { pluginListCommand, themeListCommand } from "./src/commands/lists";
|
||||
import { petPetCommand } from "./src/commands/petpet";
|
||||
import { konoSelfCommand, konoSendCommand } from "./src/commands/konochan";
|
||||
import settings from "./settings";
|
||||
|
||||
// Initialize storage with default values
|
||||
|
|
@ -39,6 +40,8 @@ export default {
|
|||
registerCommand(petPetCommand),
|
||||
registerCommand(pluginListCommand),
|
||||
registerCommand(themeListCommand),
|
||||
registerCommand(konoSelfCommand),
|
||||
registerCommand(konoSendCommand),
|
||||
];
|
||||
|
||||
console.log("[All-In-One Commands] Plugin loaded successfully!");
|
||||
|
|
|
|||
92
plugins/all-in-one/src/commands/konochan.ts
Normal file
92
plugins/all-in-one/src/commands/konochan.ts
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import { findByProps } from "@vendetta/metro";
|
||||
import { sendMessage } from "../utils/messages";
|
||||
|
||||
/**
|
||||
* Fetches a random image from KonoChan.
|
||||
* @param isNSFW - Whether to include NSFW content.
|
||||
* @returns The URL of the fetched image or null if none are found.
|
||||
*/
|
||||
const fetchImage = async (isNSFW: boolean): Promise<string | null> => {
|
||||
const baseURL = "https://konachan.com/post.json";
|
||||
const tag = isNSFW ? "rating:explicit" : "rating:safe";
|
||||
const randomPage = Math.floor(Math.random() * 100);
|
||||
|
||||
try {
|
||||
const response = await fetch(
|
||||
`${baseURL}?tags=${tag}&limit=1&page=${randomPage}`,
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
if (!Array.isArray(data) || data.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return data[0].file_url;
|
||||
} catch (error) {
|
||||
console.error("[KonoChan Randomizer] Error fetching image:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Common options for both commands
|
||||
const nsfwOption = {
|
||||
name: "nsfw",
|
||||
description: "Include NSFW content?",
|
||||
type: 5,
|
||||
required: false,
|
||||
displayName: "nsfw",
|
||||
displayDescription: "Include NSFW content?",
|
||||
};
|
||||
|
||||
export const konoSelfCommand = {
|
||||
name: "konoself",
|
||||
displayName: "konoself",
|
||||
description: "Fetch a random image from KonoChan for yourself.",
|
||||
displayDescription: "Fetch a random image from KonoChan for yourself.",
|
||||
options: [nsfwOption],
|
||||
execute: async (args: any, ctx: any) => {
|
||||
const options = new Map(args.map((option: any) => [option.name, option]));
|
||||
const isNSFW = options.get("nsfw")?.value || false;
|
||||
|
||||
const imageUrl = await fetchImage(isNSFW);
|
||||
|
||||
if (!imageUrl) {
|
||||
return sendMessage(ctx.channel.id, "No image found. Try again later.");
|
||||
}
|
||||
|
||||
return sendMessage(ctx.channel.id, `Here's your random image: ${imageUrl}`);
|
||||
},
|
||||
applicationId: "-1",
|
||||
inputType: 1,
|
||||
type: 1,
|
||||
};
|
||||
|
||||
export const konoSendCommand = {
|
||||
name: "konosend",
|
||||
displayName: "konosend",
|
||||
description: "Fetch a random image from KonoChan and send it to the channel.",
|
||||
displayDescription: "Fetch a random image from KonoChan and send it to the channel.",
|
||||
options: [nsfwOption],
|
||||
execute: async (args: any, ctx: any) => {
|
||||
const options = new Map(args.map((option: any) => [option.name, option]));
|
||||
const isNSFW = options.get("nsfw")?.value || false;
|
||||
|
||||
// Check if NSFW images are allowed in the channel
|
||||
if (isNSFW && !ctx.channel.nsfw) {
|
||||
return sendMessage(
|
||||
ctx.channel.id,
|
||||
"This channel is not marked as NSFW. Use an NSFW channel instead."
|
||||
);
|
||||
}
|
||||
|
||||
const imageUrl = await fetchImage(isNSFW);
|
||||
|
||||
if (!imageUrl) {
|
||||
return sendMessage(ctx.channel.id, "No image found. Try again later.");
|
||||
}
|
||||
|
||||
return sendMessage(ctx.channel.id, imageUrl);
|
||||
},
|
||||
applicationId: "-1",
|
||||
inputType: 1,
|
||||
type: 1,
|
||||
};
|
||||
|
|
@ -3,9 +3,10 @@ import { themes } from "@vendetta/themes";
|
|||
import { plugins } from "@vendetta/plugins";
|
||||
import { storage } from "@vendetta/plugin";
|
||||
import { alerts } from "@vendetta/ui";
|
||||
import { sendMessage } from "../utils/messages";
|
||||
import { showAlert } from "../utils/messages";
|
||||
|
||||
const SPLIT_LARGE_MESSAGES_PLUGIN = "https://vd-plugins.github.io/proxy/actuallythesun.github.io/vendetta-plugins/SplitLargeMessages/";
|
||||
const SPLIT_LARGE_MESSAGES_PLUGIN =
|
||||
"https://vd-plugins.github.io/proxy/actuallythesun.github.io/vendetta-plugins/SplitLargeMessages/";
|
||||
|
||||
const STATUS = {
|
||||
ENABLED: "🟢",
|
||||
|
|
@ -31,7 +32,8 @@ const isSLMPluginEnabled = () =>
|
|||
|
||||
// Command handlers
|
||||
async function handlePluginList(detailed: boolean, ctx: any) {
|
||||
const alwaysDetailed = storage.listSettings?.pluginListAlwaysDetailed ?? false;
|
||||
const alwaysDetailed =
|
||||
storage.listSettings?.pluginListAlwaysDetailed ?? false;
|
||||
const pluginList = [
|
||||
`**My Plugin List | ${Object.keys(plugins).length} Plugins**`,
|
||||
"",
|
||||
|
|
@ -59,20 +61,16 @@ async function handlePluginList(detailed: boolean, ctx: any) {
|
|||
|
||||
if (getListLength(pluginList) > 2000) {
|
||||
if (!isSLMPluginInstalled()) {
|
||||
return sendMessage(
|
||||
ctx.channel.id,
|
||||
`Your list is too long to send it! Please install the [Split Large Messages](${SPLIT_LARGE_MESSAGES_PLUGIN}) plugin.`,
|
||||
);
|
||||
showAlert("List too long! Install Split Large Messages plugin");
|
||||
return { type: 4 };
|
||||
}
|
||||
if (!isSLMPluginEnabled()) {
|
||||
return sendMessage(
|
||||
ctx.channel.id,
|
||||
"Your list is too long to send it! You have the Split Large Messages plugin installed, but it's not enabled!\n> Please enable it in order to send the list.",
|
||||
);
|
||||
showAlert("Enable Split Large Messages plugin to send long lists!");
|
||||
return { type: 4 };
|
||||
}
|
||||
|
||||
return alerts.showConfirmationAlert({
|
||||
content: "Your list is over than 2000 characters. Are you sure?",
|
||||
content: "Your list is over 2000 characters. Send anyway?",
|
||||
confirmText: "Yes",
|
||||
cancelText: "No",
|
||||
onConfirm: () => sendMessage(ctx.channel.id, formatList(pluginList)),
|
||||
|
|
@ -116,20 +114,16 @@ async function handleThemeList(detailed: boolean, ctx: any) {
|
|||
|
||||
if (getListLength(themeList) > 2000) {
|
||||
if (!isSLMPluginInstalled()) {
|
||||
return sendMessage(
|
||||
ctx.channel.id,
|
||||
`Your list is too long to send it! Please install the [Split Large Messages](${SPLIT_LARGE_MESSAGES_PLUGIN}) plugin.`,
|
||||
);
|
||||
showAlert("List too long! Install Split Large Messages plugin");
|
||||
return { type: 4 };
|
||||
}
|
||||
if (!isSLMPluginEnabled()) {
|
||||
return sendMessage(
|
||||
ctx.channel.id,
|
||||
"Your list is too long to send it! You have the Split Large Messages plugin installed, but it's not enabled!\n> Please enable it in order to send the list.",
|
||||
);
|
||||
showAlert("Enable Split Large Messages plugin to send long lists!");
|
||||
return { type: 4 };
|
||||
}
|
||||
|
||||
return alerts.showConfirmationAlert({
|
||||
content: "Your list is over than 2000 characters. Are you sure?",
|
||||
content: "Your list is over 2000 characters. Send anyway?",
|
||||
confirmText: "Yes",
|
||||
cancelText: "No",
|
||||
onConfirm: () => sendMessage(ctx.channel.id, formatList(themeList)),
|
||||
|
|
@ -155,7 +149,8 @@ export const pluginListCommand = {
|
|||
},
|
||||
],
|
||||
execute: async (args: any, ctx: any) => {
|
||||
const detailed = args.find((arg: any) => arg.name === "detailed")?.value ?? false;
|
||||
const detailed =
|
||||
args.find((arg: any) => arg.name === "detailed")?.value ?? false;
|
||||
return handlePluginList(detailed, ctx);
|
||||
},
|
||||
applicationId: "-1",
|
||||
|
|
@ -179,7 +174,8 @@ export const themeListCommand = {
|
|||
},
|
||||
],
|
||||
execute: async (args: any, ctx: any) => {
|
||||
const detailed = args.find((arg: any) => arg.name === "detailed")?.value ?? false;
|
||||
const detailed =
|
||||
args.find((arg: any) => arg.name === "detailed")?.value ?? false;
|
||||
return handleThemeList(detailed, ctx);
|
||||
},
|
||||
applicationId: "-1",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
import { findByProps } from "@vendetta/metro";
|
||||
import { showToast } from "@vendetta/ui/toasts";
|
||||
|
||||
const MessageActions = findByProps("sendMessage");
|
||||
|
||||
export const sendMessage = (
|
||||
export const sendMessage = async (
|
||||
channelId: string,
|
||||
content: string,
|
||||
replyToId?: string,
|
||||
storage?: any
|
||||
storage?: any,
|
||||
) => {
|
||||
// Only return acknowledgment for slash command
|
||||
if (!content) return { type: 4 };
|
||||
|
||||
const message = {
|
||||
content,
|
||||
...(replyToId && storage?.factSettings?.sendAsReply
|
||||
|
|
@ -15,8 +19,15 @@ export const sendMessage = (
|
|||
: {}),
|
||||
};
|
||||
|
||||
MessageActions.sendMessage(channelId, message, void 0, {
|
||||
nonce: BigInt(Date.now()) << 22n,
|
||||
// Use a promise to ensure message is sent before returning
|
||||
await MessageActions.sendMessage(channelId, message, void 0, {
|
||||
nonce: (Date.now() * 4194304).toString(),
|
||||
});
|
||||
return { type: 4 }; // Acknowledge the command
|
||||
|
||||
// Return acknowledgment without content to prevent double sending
|
||||
return { type: 4 };
|
||||
};
|
||||
|
||||
export const showAlert = (message: string) => {
|
||||
showToast(message, findByProps("Alerts").Alerts.ERROR);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue