yeah... I should explode...
This commit is contained in:
parent
8d2720d417
commit
ccd155e0b8
3 changed files with 391 additions and 32 deletions
|
|
@ -17,6 +17,7 @@ import {
|
|||
spotifyCoverCommand
|
||||
} from "./src/commands/spotify";
|
||||
import { garyCommand } from "./src/commands/gary";
|
||||
import { lovefemboysCommand } from "./src/commands/lovefemboys";
|
||||
import settings from "./settings";
|
||||
|
||||
// Initialize storage with default values
|
||||
|
|
@ -57,6 +58,15 @@ if (!storage.enabledCommands) {
|
|||
spotifyArtists: true,
|
||||
spotifyCover: true,
|
||||
gary: true,
|
||||
lovefemboys: false, // Hidden command - disabled by default
|
||||
};
|
||||
}
|
||||
|
||||
// Initialize hidden settings storage
|
||||
if (!storage.hiddenSettings) {
|
||||
storage.hiddenSettings = {
|
||||
enabled: false,
|
||||
visible: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +87,7 @@ const commandMap = {
|
|||
spotifyArtists: spotifyArtistsCommand,
|
||||
spotifyCover: spotifyCoverCommand,
|
||||
gary: garyCommand,
|
||||
lovefemboys: lovefemboysCommand, // Add hidden command to map
|
||||
};
|
||||
|
||||
// Store registered commands for cleanup
|
||||
|
|
@ -90,6 +101,7 @@ export default {
|
|||
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}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { semanticColors } from "@vendetta/ui";
|
|||
import { getAssetIDByName } from "@vendetta/ui/assets";
|
||||
import { Forms } from "@vendetta/ui/components";
|
||||
import { alerts } from "@vendetta/ui";
|
||||
import { showToast } from "@vendetta/ui/toasts";
|
||||
|
||||
const { ScrollView } = RN;
|
||||
const { FormRow, FormSwitchRow } = Forms;
|
||||
|
|
@ -41,20 +42,29 @@ storage.enabledCommands ??= {
|
|||
spotifyArtists: true,
|
||||
spotifyCover: true,
|
||||
gary: true,
|
||||
lovefemboys: false, // Hidden command - disabled by default
|
||||
};
|
||||
|
||||
storage.pendingRestart ??= false;
|
||||
|
||||
// Hidden settings storage
|
||||
storage.hiddenSettings ??= {
|
||||
enabled: false,
|
||||
visible: false,
|
||||
};
|
||||
|
||||
// Better Table Row Group Component
|
||||
function BetterTableRowGroup({
|
||||
title,
|
||||
icon,
|
||||
children,
|
||||
padding = false,
|
||||
onTitlePress,
|
||||
}: React.PropsWithChildren<{
|
||||
title?: string;
|
||||
icon?: number;
|
||||
padding?: boolean;
|
||||
onTitlePress?: () => void;
|
||||
}>) {
|
||||
const styles = stylesheet.createThemedStyleSheet({
|
||||
main: {
|
||||
|
|
@ -73,6 +83,11 @@ function BetterTableRowGroup({
|
|||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
},
|
||||
titlePressable: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: 4,
|
||||
},
|
||||
icon: {
|
||||
width: 16,
|
||||
height: 16,
|
||||
|
|
@ -90,16 +105,33 @@ function BetterTableRowGroup({
|
|||
<RN.View style={{ marginHorizontal: 16, marginTop: 16 }}>
|
||||
{title && (
|
||||
<RN.View style={styles.titleContainer}>
|
||||
{icon && (
|
||||
<RN.Image
|
||||
style={styles.icon}
|
||||
source={icon}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
{onTitlePress ? (
|
||||
<RN.Pressable style={styles.titlePressable} onPress={onTitlePress}>
|
||||
{icon && (
|
||||
<RN.Image
|
||||
style={styles.icon}
|
||||
source={icon}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
)}
|
||||
<RN.Text style={styles.titleText}>
|
||||
{title.toUpperCase()}
|
||||
</RN.Text>
|
||||
</RN.Pressable>
|
||||
) : (
|
||||
<>
|
||||
{icon && (
|
||||
<RN.Image
|
||||
style={styles.icon}
|
||||
source={icon}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
)}
|
||||
<RN.Text style={styles.titleText}>
|
||||
{title.toUpperCase()}
|
||||
</RN.Text>
|
||||
</>
|
||||
)}
|
||||
<RN.Text style={styles.titleText}>
|
||||
{title.toUpperCase()}
|
||||
</RN.Text>
|
||||
</RN.View>
|
||||
)}
|
||||
<RN.View style={styles.main}>
|
||||
|
|
@ -113,8 +145,11 @@ function BetterTableRowGroup({
|
|||
);
|
||||
}
|
||||
|
||||
// Header Component
|
||||
// Header Component with SILENT secret unlock
|
||||
function Header() {
|
||||
const [clickCounter, setClickCounter] = React.useState(0);
|
||||
const [clickTimeout, setClickTimeout] = React.useState<NodeJS.Timeout | null>(null);
|
||||
|
||||
const styles = stylesheet.createThemedStyleSheet({
|
||||
container: {
|
||||
flexDirection: "column",
|
||||
|
|
@ -146,20 +181,142 @@ function Header() {
|
|||
},
|
||||
});
|
||||
|
||||
const handleIconPress = () => {
|
||||
if (storage.hiddenSettings.enabled) {
|
||||
storage.hiddenSettings.visible = !storage.hiddenSettings.visible;
|
||||
showToast(
|
||||
`Hidden settings ${storage.hiddenSettings.visible ? "visible" : "hidden"}`,
|
||||
getAssetIDByName("SettingsIcon")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clickTimeout) {
|
||||
clearTimeout(clickTimeout);
|
||||
}
|
||||
|
||||
const newTimeout = setTimeout(() => {
|
||||
setClickCounter(0);
|
||||
}, 1000);
|
||||
setClickTimeout(newTimeout);
|
||||
|
||||
const newCounter = clickCounter + 1;
|
||||
setClickCounter(newCounter);
|
||||
|
||||
// Silent counting - no progress notifications
|
||||
if (newCounter < 10) {
|
||||
return; // Just count silently
|
||||
}
|
||||
|
||||
// Unlocked! Only show this notification
|
||||
showToast("🔓 Hidden settings unlocked!", getAssetIDByName("CheckmarkIcon"));
|
||||
storage.hiddenSettings.enabled = true;
|
||||
storage.hiddenSettings.visible = true;
|
||||
setClickCounter(0);
|
||||
};
|
||||
|
||||
return (
|
||||
<RN.View style={styles.container}>
|
||||
<RN.View style={styles.iconContainer}>
|
||||
<RN.Pressable style={styles.iconContainer} onPress={handleIconPress}>
|
||||
<RN.Image
|
||||
source={getAssetIDByName("SettingsIcon")}
|
||||
style={styles.icon}
|
||||
/>
|
||||
</RN.View>
|
||||
</RN.Pressable>
|
||||
<RN.Text style={styles.title}>Commands</RN.Text>
|
||||
<RN.Text style={styles.subtitle}>A collection of useful commands</RN.Text>
|
||||
</RN.View>
|
||||
);
|
||||
}
|
||||
|
||||
// Hidden Commands Settings Page
|
||||
function HiddenSettingsPage() {
|
||||
useProxy(storage);
|
||||
const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
|
||||
|
||||
const styles = stylesheet.createThemedStyleSheet({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: semanticColors.BACKGROUND_PRIMARY,
|
||||
},
|
||||
warningText: {
|
||||
fontSize: 14,
|
||||
color: semanticColors.TEXT_DANGER,
|
||||
textAlign: "center",
|
||||
lineHeight: 20,
|
||||
fontWeight: "600",
|
||||
},
|
||||
infoText: {
|
||||
fontSize: 14,
|
||||
color: semanticColors.TEXT_MUTED,
|
||||
textAlign: "center",
|
||||
lineHeight: 20,
|
||||
marginTop: 8,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ScrollView style={styles.container}>
|
||||
<RN.View style={{ paddingVertical: 16 }}>
|
||||
<BetterTableRowGroup title="⚠️ Warning" icon={getAssetIDByName("WarningIcon")} padding={true}>
|
||||
<RN.Text style={styles.warningText}>
|
||||
These are hidden commands that may contain mature content or experimental features.
|
||||
</RN.Text>
|
||||
<RN.Text style={styles.infoText}>
|
||||
Use at your own discretion. Commands in this section are disabled by default.
|
||||
</RN.Text>
|
||||
</BetterTableRowGroup>
|
||||
|
||||
<BetterTableRowGroup title="Hidden Commands" icon={getAssetIDByName("EyeIcon")}>
|
||||
<FormSwitchRow
|
||||
label="/lovefemboys"
|
||||
subLabel="Get random femboy images from r/femboys (NSFW content available)"
|
||||
leading={<FormRow.Icon source={getAssetIDByName("HeartIcon")} />}
|
||||
value={storage.enabledCommands.lovefemboys}
|
||||
onValueChange={(v) => {
|
||||
storage.enabledCommands.lovefemboys = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
|
||||
<BetterTableRowGroup title="Hidden Settings Control" icon={getAssetIDByName("SettingsIcon")}>
|
||||
<FormSwitchRow
|
||||
label="Keep Hidden Settings Visible"
|
||||
subLabel="Keep this section visible even when navigating away"
|
||||
leading={<FormRow.Icon source={getAssetIDByName("EyeIcon")} />}
|
||||
value={storage.hiddenSettings.visible}
|
||||
onValueChange={(v) => {
|
||||
storage.hiddenSettings.visible = v;
|
||||
}}
|
||||
/>
|
||||
<FormRow
|
||||
label="Reset Hidden Settings"
|
||||
subLabel="Hide this section and disable all hidden commands"
|
||||
leading={<FormRow.Icon source={getAssetIDByName("TrashIcon")} />}
|
||||
onPress={() => {
|
||||
alerts.showConfirmationAlert({
|
||||
title: "Reset Hidden Settings",
|
||||
content: "This will hide the hidden settings section and disable all hidden commands. Are you sure?",
|
||||
confirmText: "Reset",
|
||||
onConfirm: () => {
|
||||
storage.hiddenSettings.enabled = false;
|
||||
storage.hiddenSettings.visible = false;
|
||||
storage.enabledCommands.lovefemboys = false;
|
||||
storage.pendingRestart = true;
|
||||
showToast("Hidden settings reset", getAssetIDByName("CheckmarkIcon"));
|
||||
},
|
||||
cancelText: "Cancel",
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
</RN.View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
// Facts Commands Settings Page - FIXED with local force update
|
||||
function FactsSettingsPage() {
|
||||
useProxy(storage);
|
||||
|
|
@ -198,7 +355,7 @@ function FactsSettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.catfact = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
<FormSwitchRow
|
||||
|
|
@ -209,7 +366,7 @@ function FactsSettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.dogfact = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
<FormSwitchRow
|
||||
|
|
@ -220,7 +377,7 @@ function FactsSettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.useless = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
|
|
@ -267,7 +424,7 @@ function GaryAPIPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.gary = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
|
|
@ -287,7 +444,7 @@ function GaryAPIPage() {
|
|||
onValueChange={(v) => {
|
||||
if (v) {
|
||||
storage.garySettings.imageSource = "gary";
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
@ -299,7 +456,7 @@ function GaryAPIPage() {
|
|||
onValueChange={(v) => {
|
||||
if (v) {
|
||||
storage.garySettings.imageSource = "catapi";
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
@ -311,7 +468,7 @@ function GaryAPIPage() {
|
|||
onValueChange={(v) => {
|
||||
if (v) {
|
||||
storage.garySettings.imageSource = "minker";
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
@ -323,7 +480,7 @@ function GaryAPIPage() {
|
|||
onValueChange={(v) => {
|
||||
if (v) {
|
||||
storage.garySettings.imageSource = "goober";
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
|
@ -382,7 +539,7 @@ function ListSettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.pluginList = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
<FormSwitchRow
|
||||
|
|
@ -393,7 +550,7 @@ function ListSettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.themeList = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
|
|
@ -419,7 +576,7 @@ function ImageSettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.petpet = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
|
|
@ -433,7 +590,7 @@ function ImageSettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.konoself = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
<FormSwitchRow
|
||||
|
|
@ -444,7 +601,7 @@ function ImageSettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.konosend = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
|
|
@ -470,7 +627,7 @@ function SpotifySettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.spotifyTrack = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
<FormSwitchRow
|
||||
|
|
@ -481,7 +638,7 @@ function SpotifySettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.spotifyAlbum = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
<FormSwitchRow
|
||||
|
|
@ -492,7 +649,7 @@ function SpotifySettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.spotifyArtists = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
<FormSwitchRow
|
||||
|
|
@ -503,7 +660,7 @@ function SpotifySettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.spotifyCover = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
|
|
@ -540,7 +697,7 @@ function OtherSettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.firstmessage = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
|
|
@ -554,7 +711,7 @@ function OtherSettingsPage() {
|
|||
onValueChange={(v) => {
|
||||
storage.enabledCommands.sysinfo = v;
|
||||
storage.pendingRestart = true;
|
||||
forceUpdate(); // Force this page to re-render
|
||||
forceUpdate();
|
||||
}}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
|
|
@ -722,7 +879,7 @@ function CreditsPage() {
|
|||
);
|
||||
}
|
||||
|
||||
// MAIN SETTINGS COMPONENT
|
||||
// MAIN SETTINGS COMPONENT with hidden settings
|
||||
export default function Settings() {
|
||||
useProxy(storage);
|
||||
const navigation = NavigationNative.useNavigation();
|
||||
|
|
@ -814,6 +971,22 @@ export default function Settings() {
|
|||
/>
|
||||
</BetterTableRowGroup>
|
||||
|
||||
{/* Hidden Settings Section - Only visible when unlocked */}
|
||||
{storage.hiddenSettings?.enabled && storage.hiddenSettings?.visible && (
|
||||
<BetterTableRowGroup title="🔓 Hidden Settings" icon={getAssetIDByName("EyeIcon")}>
|
||||
<FormRow
|
||||
label="Hidden Commands"
|
||||
subLabel="Experimental and mature content commands"
|
||||
leading={<FormRow.Icon source={getAssetIDByName("WarningIcon")} />}
|
||||
trailing={<FormRow.Arrow />}
|
||||
onPress={() => navigation.push("VendettaCustomPage", {
|
||||
title: "Hidden Settings",
|
||||
render: HiddenSettingsPage,
|
||||
})}
|
||||
/>
|
||||
</BetterTableRowGroup>
|
||||
)}
|
||||
|
||||
{/* More Options */}
|
||||
<BetterTableRowGroup title="More Options" icon={getAssetIDByName("SettingsIcon")}>
|
||||
<FormRow
|
||||
|
|
|
|||
174
plugins/Commands/src/commands/lovefemboys.ts
Normal file
174
plugins/Commands/src/commands/lovefemboys.ts
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
import { findByProps } from "@vendetta/metro";
|
||||
|
||||
const MessageActions = findByProps("sendMessage");
|
||||
|
||||
interface RedditPost {
|
||||
data: {
|
||||
title: string;
|
||||
url: string;
|
||||
is_video: boolean;
|
||||
over_18: boolean;
|
||||
preview?: {
|
||||
images: Array<{
|
||||
source: {
|
||||
url: string;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
url_overridden_by_dest?: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface RedditResponse {
|
||||
data: {
|
||||
children: RedditPost[];
|
||||
};
|
||||
}
|
||||
|
||||
async function getFemboyImage(includeNsfw: boolean = false): Promise<string | null> {
|
||||
try {
|
||||
const response = await fetch('https://reddit.com/r/femboys.json');
|
||||
if (!response.ok) {
|
||||
console.log('[LoveFemboys] Failed to fetch from Reddit API');
|
||||
return null;
|
||||
}
|
||||
|
||||
const data: RedditResponse = await response.json();
|
||||
|
||||
// Filter posts that are images and match NSFW preference
|
||||
const imagePosts = data.data.children.filter(post => {
|
||||
const postData = post.data;
|
||||
|
||||
// Skip videos
|
||||
if (postData.is_video) return false;
|
||||
|
||||
// Check NSFW filter
|
||||
if (!includeNsfw && postData.over_18) return false;
|
||||
|
||||
// Check if it's an image URL
|
||||
const url = postData.url_overridden_by_dest || postData.url;
|
||||
return url && (
|
||||
url.includes('.jpg') ||
|
||||
url.includes('.jpeg') ||
|
||||
url.includes('.png') ||
|
||||
url.includes('.gif') ||
|
||||
url.includes('i.redd.it') ||
|
||||
url.includes('i.imgur.com')
|
||||
);
|
||||
});
|
||||
|
||||
if (imagePosts.length === 0) {
|
||||
console.log('[LoveFemboys] No suitable images found');
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get random image
|
||||
const randomPost = imagePosts[Math.floor(Math.random() * imagePosts.length)];
|
||||
const imageUrl = randomPost.data.url_overridden_by_dest || randomPost.data.url;
|
||||
|
||||
// Handle Reddit preview images
|
||||
if (imageUrl.includes('reddit.com') && randomPost.data.preview?.images?.[0]?.source?.url) {
|
||||
return randomPost.data.preview.images[0].source.url.replace(/&/g, '&');
|
||||
}
|
||||
|
||||
return imageUrl;
|
||||
} catch (error) {
|
||||
console.error('[LoveFemboys] Error fetching image:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export const lovefemboysCommand = {
|
||||
name: "lovefemboys",
|
||||
displayName: "lovefemboys",
|
||||
description: "Get a random femboy image from r/femboys",
|
||||
displayDescription: "Get a random femboy image from r/femboys",
|
||||
options: [
|
||||
{
|
||||
name: "nsfw",
|
||||
displayName: "nsfw",
|
||||
description: "Include NSFW images",
|
||||
displayDescription: "Include NSFW images",
|
||||
type: 5, // Boolean
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: "ephemeral",
|
||||
displayName: "ephemeral",
|
||||
description: "Send as ephemeral message (only you can see)",
|
||||
displayDescription: "Send as ephemeral message (only you can see)",
|
||||
type: 5, // Boolean
|
||||
required: false,
|
||||
}
|
||||
],
|
||||
execute: async (args: any, ctx: any) => {
|
||||
try {
|
||||
const includeNsfw = args.find((arg: any) => arg.name === "nsfw")?.value || false;
|
||||
const isEphemeral = args.find((arg: any) => arg.name === "ephemeral")?.value || false;
|
||||
|
||||
const imageUrl = await getFemboyImage(includeNsfw);
|
||||
|
||||
if (!imageUrl) {
|
||||
const errorMessage = "❌ Failed to fetch femboy image. Try again later!";
|
||||
|
||||
if (isEphemeral) {
|
||||
return {
|
||||
type: 4,
|
||||
data: {
|
||||
content: errorMessage,
|
||||
flags: 64, // Ephemeral flag
|
||||
},
|
||||
};
|
||||
} else {
|
||||
const fixNonce = Date.now().toString();
|
||||
MessageActions.sendMessage(ctx.channel.id, { content: errorMessage }, void 0, {
|
||||
nonce: fixNonce,
|
||||
});
|
||||
return { type: 4 };
|
||||
}
|
||||
}
|
||||
|
||||
const content = `💖 **Femboy Image** ${includeNsfw ? '(NSFW included)' : '(SFW only)'}\n${imageUrl}`;
|
||||
|
||||
if (isEphemeral) {
|
||||
return {
|
||||
type: 4,
|
||||
data: {
|
||||
content,
|
||||
flags: 64, // Ephemeral flag
|
||||
},
|
||||
};
|
||||
} else {
|
||||
const fixNonce = Date.now().toString();
|
||||
MessageActions.sendMessage(ctx.channel.id, { content }, void 0, {
|
||||
nonce: fixNonce,
|
||||
});
|
||||
return { type: 4 };
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[LoveFemboys] Command error:', error);
|
||||
const errorMessage = "❌ An error occurred while fetching femboy image.";
|
||||
|
||||
const isEphemeral = args.find((arg: any) => arg.name === "ephemeral")?.value || false;
|
||||
|
||||
if (isEphemeral) {
|
||||
return {
|
||||
type: 4,
|
||||
data: {
|
||||
content: errorMessage,
|
||||
flags: 64, // Ephemeral flag
|
||||
},
|
||||
};
|
||||
} else {
|
||||
const fixNonce = Date.now().toString();
|
||||
MessageActions.sendMessage(ctx.channel.id, { content: errorMessage }, void 0, {
|
||||
nonce: fixNonce,
|
||||
});
|
||||
return { type: 4 };
|
||||
}
|
||||
}
|
||||
},
|
||||
applicationId: "-1",
|
||||
inputType: 1,
|
||||
type: 1,
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue