diff --git a/plugins/Commands/index.ts b/plugins/Commands/index.ts index 04d2be0..4b68e62 100644 --- a/plugins/Commands/index.ts +++ b/plugins/Commands/index.ts @@ -1,9 +1,9 @@ import { registerCommand } from "@vendetta/commands"; import { storage } from "@vendetta/plugin"; import { - catFactCommand, - dogFactCommand, - uselessFactCommand, + catFactCommand, + dogFactCommand, + uselessFactCommand, } from "./src/commands/facts"; import { pluginListCommand, themeListCommand } from "./src/commands/lists"; import { petPetCommand } from "./src/commands/petpet"; @@ -11,116 +11,109 @@ import { konoSelfCommand, konoSendCommand } from "./src/commands/konochan"; import { firstMessageCommand } from "./src/commands/firstmessage"; import { sysinfoCommand } from "./src/commands/sysinfo"; import { - spotifyTrackCommand, - spotifyAlbumCommand, - spotifyArtistsCommand, - spotifyCoverCommand + spotifyTrackCommand, + spotifyAlbumCommand, + spotifyArtistsCommand, + spotifyCoverCommand, } from "./src/commands/spotify"; import { garyCommand } from "./src/commands/gary"; import { lovefemboysCommand } from "./src/commands/lovefemboys"; import { ipCommand } from "./src/commands/ip"; import { nekoslifeCommand } from "./src/commands/nekoslife"; +import { + friendInviteCreateCommand, + friendInviteViewCommand, + friendInviteRevokeCommand, +} from "./src/commands/friendinvites"; import settings from "./settings"; -// Initialize storage with default values if (!storage.factSettings) { - storage.factSettings = { - sendAsReply: true, - includeCitation: false, - }; + storage.factSettings = { + sendAsReply: true, + includeCitation: false, + }; } - if (!storage.listSettings) { - storage.listSettings = { - pluginListAlwaysDetailed: false, - themeListAlwaysDetailed: false, - }; + storage.listSettings = { + pluginListAlwaysDetailed: false, + themeListAlwaysDetailed: false, + }; } - if (!storage.garySettings) { - storage.garySettings = { - imageSource: "gary", - }; + storage.garySettings = { + imageSource: "gary", + }; } - if (!storage.enabledCommands) { - storage.enabledCommands = { - catfact: true, - dogfact: true, - useless: true, - petpet: true, - pluginList: true, - themeList: true, - konoself: true, - konosend: true, - firstmessage: true, - sysinfo: true, - spotifyTrack: true, - spotifyAlbum: true, - spotifyArtists: true, - spotifyCover: true, - gary: true, - ip: true, // IP command - enabled by default - lovefemboys: false, // Hidden command - disabled by default - nekoslife: false, // Hidden command - disabled by default - }; + storage.enabledCommands = { + catfact: true, + dogfact: true, + useless: true, + petpet: true, + pluginList: true, + themeList: true, + konoself: true, + konosend: true, + firstmessage: true, + sysinfo: true, + spotifyTrack: true, + spotifyAlbum: true, + spotifyArtists: true, + spotifyCover: true, + gary: true, + ip: true, + lovefemboys: false, + nekoslife: false, + friendInviteCreate: true, + friendInviteView: true, + friendInviteRevoke: true, + }; } - -// Initialize hidden settings storage if (!storage.hiddenSettings) { - storage.hiddenSettings = { - enabled: false, - visible: false, - konochanBypassNsfw: false, // NSFW bypass option - }; + storage.hiddenSettings = { + enabled: false, + visible: false, + konochanBypassNsfw: false, + }; } -// Map commands to their storage keys const commandMap = { - catfact: catFactCommand, - dogfact: dogFactCommand, - useless: uselessFactCommand, - petpet: petPetCommand, - pluginList: pluginListCommand, - themeList: themeListCommand, - konoself: konoSelfCommand, - konosend: konoSendCommand, - firstmessage: firstMessageCommand, - sysinfo: sysinfoCommand, - spotifyTrack: spotifyTrackCommand, - spotifyAlbum: spotifyAlbumCommand, - spotifyArtists: spotifyArtistsCommand, - spotifyCover: spotifyCoverCommand, - gary: garyCommand, - ip: ipCommand, // Add IP command - lovefemboys: lovefemboysCommand, // Add hidden command to map - nekoslife: nekoslifeCommand, // Add NekosLife command + catfact: catFactCommand, + dogfact: dogFactCommand, + useless: uselessFactCommand, + petpet: petPetCommand, + pluginList: pluginListCommand, + themeList: themeListCommand, + konoself: konoSelfCommand, + konosend: konoSendCommand, + firstmessage: firstMessageCommand, + sysinfo: sysinfoCommand, + spotifyTrack: spotifyTrackCommand, + spotifyAlbum: spotifyAlbumCommand, + spotifyArtists: spotifyArtistsCommand, + spotifyCover: spotifyCoverCommand, + gary: garyCommand, + ip: ipCommand, + lovefemboys: lovefemboysCommand, + nekoslife: nekoslifeCommand, + friendInviteCreate: friendInviteCreateCommand, + friendInviteView: friendInviteViewCommand, + friendInviteRevoke: friendInviteRevokeCommand, }; -// Store registered commands for cleanup let commands: Array<() => void> = []; export default { - onLoad: () => { - console.log("[All-In-One Commands] Loading plugin..."); - - // Register only enabled commands - for (const [key, command] of Object.entries(commandMap)) { - if (storage.enabledCommands[key]) { - commands.push(registerCommand(command)); - console.log(`[All-In-One Commands] Registered command: ${key}`); - } - } - - console.log("[All-In-One Commands] Plugin loaded successfully!"); - }, - - onUnload: () => { - console.log("[All-In-One Commands] Unloading plugin..."); - commands.forEach((unregister) => unregister()); - commands = []; - console.log("[All-In-One Commands] Plugin unloaded successfully!"); - }, - - settings, + onLoad: () => { + for (const [key, command] of Object.entries(commandMap)) { + if (storage.enabledCommands[key]) { + commands.push(registerCommand(command)); + } + } + }, + onUnload: () => { + commands.forEach((unregister) => unregister()); + commands = []; + }, + settings, }; diff --git a/plugins/Commands/settings.tsx b/plugins/Commands/settings.tsx index 64617be..c9b6b5f 100644 --- a/plugins/Commands/settings.tsx +++ b/plugins/Commands/settings.tsx @@ -42,9 +42,12 @@ storage.enabledCommands ??= { spotifyArtists: true, spotifyCover: true, gary: true, - ip: true, // IP command - enabled by default - lovefemboys: false, // Hidden command - disabled by default - nekoslife: false, // Hidden command - disabled by default + ip: true, + lovefemboys: false, + nekoslife: false, + friendInviteCreate: true, + friendInviteView: true, + friendInviteRevoke: true, }; storage.pendingRestart ??= false; @@ -53,7 +56,7 @@ storage.pendingRestart ??= false; storage.hiddenSettings ??= { enabled: false, visible: false, - konochanBypassNsfw: false, // New bypass option - disabled by default + konochanBypassNsfw: false, }; // Better Table Row Group Component @@ -287,7 +290,7 @@ function NekosLifeCategoriesPage() { }, }); - // Only SFW nekos.life categories + // nekos.life categories const sfwCategories = [ { name: "Avatar", value: "avatar" }, { name: "Classic", value: "classic" }, @@ -447,7 +450,6 @@ function HiddenSettingsPage() { forceUpdate(); }, onCancel: () => { - // Do nothing - keep it disabled }, }); } else { @@ -951,7 +953,7 @@ function SpotifySettingsPage() { ); } -// Other Settings Page - Updated with IP command +// Other Settings Page - Updated with friend invite commands function OtherSettingsPage() { useProxy(storage); const [, forceUpdate] = React.useReducer((x) => x + 1, 0); @@ -994,6 +996,42 @@ function OtherSettingsPage() { }} /> + + + { + storage.enabledCommands.friendInviteCreate = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + { + storage.enabledCommands.friendInviteView = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + { + storage.enabledCommands.friendInviteRevoke = v; + storage.pendingRestart = true; + forceUpdate(); + }} + /> + ); diff --git a/plugins/Commands/src/commands/friendinvites.ts b/plugins/Commands/src/commands/friendinvites.ts new file mode 100644 index 0000000..2e0572f --- /dev/null +++ b/plugins/Commands/src/commands/friendinvites.ts @@ -0,0 +1,104 @@ +import { findByProps } from "@vendetta/metro"; + +const ClydeUtils = findByProps("sendBotMessage", "sendMessage"); +const inviteModule = findByProps("getAllFriendInvites", "createFriendInvite", "revokeFriendInvites"); +const api = findByProps("get", "post"); +const getCurrentUser = findByProps("getCurrentUser")?.getCurrentUser; +const uuidv4 = findByProps("v4")?.v4; + +function send(ctx, content) { + const fixNonce = Date.now().toString(); + ClydeUtils.sendMessage(ctx.channel.id, { content }, void 0, { nonce: fixNonce }); +} + +export const friendInviteCreateCommand = { + name: "invite create", + displayName: "invite create", + description: "Generates a friend invite link.", + displayDescription: "Generates a friend invite link.", + type: 1, + applicationId: "-1", + inputType: 1, + execute: async (_, ctx) => { + try { + if (!getCurrentUser?.().phone) { + send(ctx, "You need to have a phone number connected to your account to create a friend invite!"); + return { type: 4 }; + } + const uuid = uuidv4(); + const res = await api.post({ + url: "/friend-finder/find-friends", + body: { modified_contacts: { [uuid]: [1, "", ""] }, phone_contact_methods_count: 1 }, + }); + const code = res.body?.invite_suggestions?.[0]?.[3]; + if (!code) { + send(ctx, "Failed to generate invite code."); + return { type: 4 }; + } + const createInvite = await inviteModule.createFriendInvite({ + code, + recipient_phone_number_or_email: uuid, + contact_visibility: 1, + filter_visibilities: [], + filtered_invite_suggestions_index: 1, + }); + const expires = Math.floor(new Date(createInvite.expires_at).getTime() / 1000); + const message = `https://discord.gg/${createInvite.code} · Expires: `; + send(ctx, message); + return { type: 4 }; + } catch (e) { + send(ctx, "Error creating invite."); + console.error("[FriendInvite] create error:", e); + return { type: 4 }; + } + }, +}; + +export const friendInviteViewCommand = { + name: "view invites", + displayName: "view invites", + description: "View your current friend invite links that you've made.", + displayDescription: "View your current friend invite links that you've made.", + type: 1, + applicationId: "-1", + execute: async (_, ctx) => { + try { + const invites = await inviteModule.getAllFriendInvites(); + if (!invites?.length) { + send(ctx, "You have no active friend invites!"); + return { type: 4 }; + } + const friendInviteList = invites.map(i => { + const expires = Math.floor(new Date(i.expires_at).getTime() / 1000); + return `_https://discord.gg/${i.code}_ · Expires: · Uses: \`${i.uses}/${i.max_uses}\``; + }); + send(ctx, friendInviteList.join("\n")); + return { type: 4 }; + } catch (e) { + send(ctx, "Error viewing invites."); + console.error("[FriendInvite] view error:", e); + return { type: 4 }; + } + }, +}; + +export const friendInviteRevokeCommand = { + name: "revoke invites", + displayName: "revoke invites", + description: "Revoke all your friend invite links.", + displayDescription: "Revoke all your friend invite links.", + type: 1, + applicationId: "-1", + inputType: 1, + execute: async (_, ctx) => { + try { + await inviteModule.revokeFriendInvites(); + send(ctx, "All friend invites have been revoked."); + return { type: 4 }; + } catch (e) { + send(ctx, "Error revoking invites."); + console.error("[FriendInvite] revoke error:", e); + return { type: 4 }; + } + }, +};