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 };
+ }
+ },
+};