goat
command
theme
Create and apply AI themes for group chats
0
views
0
likes
0
installs
Aliases: aitheme
raw source
const { getStreamFromURL } = global.utils;
module.exports = {
config: {
name: "theme",
aliases: ["aitheme"],
version: "5.0",
author: "xalman",
countDown: 5,
role: 1,
description: "Create and apply AI themes for group chats",
category: "box chat",
guide: "{pn} - Show current theme\n{pn} id - Show theme ID\n{pn} apply <themeID> - Apply theme\n{pn} <description> - Generate AI themes"
},
onReply: async function ({ message, Reply, event, api }) {
const { author, themes, threadID, messageID } = Reply;
const currentUserId = event.senderID || event.userID || (event.from && event.from.id);
if (currentUserId !== author) {
return message.reply('❌ Only the person who generated these themes can select one.');
}
const selection = parseInt((event.body || event.text || '').trim());
if (!selection || selection < 1 || selection > themes.length) {
return message.reply(`❌ Invalid selection. Please reply with a number between 1 and ${themes.length}.`);
}
const selectedTheme = themes[selection - 1];
try {
if (messageID && typeof api.unsendMessage === "function") {
try { await api.unsendMessage(messageID); } catch (e) {}
}
const themeId = selectedTheme.id || selectedTheme.themeId || selectedTheme.theme_fbid;
if (!themeId) {
return message.reply('❌ Selected theme does not have a valid theme ID.');
}
await new Promise((resolve, reject) => {
api.changeThreadColor(themeId, threadID, (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
const themeName = selectedTheme.accessibility_label || selectedTheme.name || "AI Theme";
let successMsg = `✅ Theme applied successfully!\n📝 Name: ${themeName}\n🆔 ID: ${themeId}`;
const attachments = [];
const imageUrl = selectedTheme.background_asset?.image?.url || selectedTheme.backgroundImage || selectedTheme.image || selectedTheme.images?.background;
if (imageUrl) {
try {
const stream = await getStreamFromURL(imageUrl);
if (stream) attachments.push(stream);
} catch (imgErr) {
console.log('Failed to load theme image:', imgErr);
}
}
return message.reply({
body: successMsg,
attachment: attachments.length > 0 ? attachments : undefined
});
} catch (error) {
console.error('Theme apply error:', error);
return message.reply(`❌ Failed to apply theme: ${error.message || error}`);
}
},
onStart: async function ({ args, message, event, api, commandName }) {
const { threadID, senderID } = event;
const command = String(args[0] || "").toLowerCase().trim();
if (command === "id") {
try {
const threadInfo = await api.getThreadInfo(threadID);
const theme = threadInfo?.threadTheme || {};
const themeId = theme.id || theme.theme_fbid || theme.themeId || threadInfo?.color || "Unknown";
const color = theme.accessibility_label || theme.name || threadInfo?.color || "Unknown";
return message.reply(
`╭──〔 THEME ID 〕──╮\n│\n│ 📌 ID: ${themeId}\n│ 🎨 Color: ${color}\n│\n╰─────────────────`
);
} catch (error) {
return message.reply(`❌ Failed to get current theme.\n\n${error.message || error}`);
}
}
if (command === "apply" || command === "set") {
const themeId = args.slice(1).join(" ").trim();
if (!themeId) {
return message.reply("❌ Please provide a theme ID.\n\nExample: /theme apply 739785333579430");
}
try {
await new Promise((resolve, reject) => {
api.changeThreadColor(themeId, threadID, (err, result) => {
if (err) reject(err);
else resolve(result);
});
});
return message.reply(`✅ Theme applied successfully!\n📌 ID: ${themeId}`);
} catch (error) {
return message.reply(`❌ Failed to apply theme: ${error.message || error}`);
}
}
const prompt = args.join(" ").trim();
if (!prompt) {
try {
const threadInfo = await api.getThreadInfo(threadID);
const theme = threadInfo?.threadTheme;
if (!theme) {
return message.reply(
`╭──〔 CURRENT THEME 〕──╮\n│\n│ ℹ️ Default theme\n│\n│ 💡 Use: /theme <description>\n│ to generate AI themes\n╰────────────────────`
);
}
const themeId = theme.id || theme.theme_fbid || theme.themeId || threadInfo?.color || "Unknown";
const color = theme.accessibility_label || theme.name || threadInfo?.color || "Unknown";
return message.reply(
`╭──〔 CURRENT THEME 〕──╮\n│\n│ 📌 ID: ${themeId}\n│ 🎨 Color: ${color}\n│\n│ 💡 Change: /theme apply <ID>\n│ 💡 Generate: /theme <description>\n╰────────────────────`
);
} catch (error) {
return message.reply(`❌ Failed to get current theme.\n\n${error.message || error}`);
}
}
if (typeof api.createThemeAI !== "function" && typeof api.metaTheme !== "function") {
return message.reply(
"❌ Your current FCA does not support AI theme generation.\n\nPlease update your FCA/package to a version that provides `api.createThemeAI()` or `api.metaTheme()`."
);
}
try {
await message.reply(`🎨 Generating AI themes...\n\n📝 ${prompt}`);
let themes = [];
if (typeof api.createThemeAI === "function") {
const promises = [];
for (let i = 0; i < 5; i++) {
promises.push(new Promise((resolve, reject) => {
api.createThemeAI(prompt, (err, data) => {
if (err) reject(err);
else resolve(data);
});
}));
}
const results = await Promise.allSettled(promises);
themes = results
.filter(r => r.status === "fulfilled")
.map(r => r.value)
.filter(theme => theme && (theme.id || theme.themeId || theme.theme_fbid));
if (themes.length === 0) {
return message.reply("❌ No themes were generated.\n\nTry a different description.");
}
} else {
const result = await new Promise((resolve, reject) => {
api.metaTheme(prompt, { numThemes: 5 }, (err, data) => {
if (err) reject(err);
else resolve(data);
});
});
themes = normalizeThemes(result);
}
if (!themes || themes.length === 0) {
return message.reply("❌ No themes were generated.\n\nTry a different description.");
}
let themeList = "";
const attachments = [];
for (let i = 0; i < themes.length; i++) {
const theme = themes[i];
const themeId = theme.id || theme.themeId || theme.theme_fbid || "Unknown";
const themeName = theme.accessibility_label || theme.name || theme.label || "AI Generated";
themeList += `${i + 1}. 📝 Name: ${themeName}\n`;
themeList += ` 🆔 ID: ${themeId}\n\n`;
const imageUrl = theme.background_asset?.image?.url || theme.backgroundImage || theme.image || theme.images?.background;
if (imageUrl) {
try {
const stream = await getStreamFromURL(imageUrl);
if (stream) attachments.push(stream);
} catch (err) {
console.error(`Preview ${i + 1} failed:`, err.message);
}
}
}
const replyMessage = `╭──〔 AI THEME GENERATOR 〕──╮\n│\n│ ✨ Generated ${themes.length} theme(s)!\n│ 📝 ${prompt}\n│\n${themeList}│ 💬 Reply with a number (1-${themes.length})\n│ to apply the theme.\n╰──────────────────────────`;
const replyData = { body: replyMessage };
if (attachments.length > 0) replyData.attachment = attachments;
return message.reply(replyData, (err, info) => {
if (err || !info?.messageID) return;
if (!global.GoatBot?.onReply?.set) return;
global.GoatBot.onReply.set(info.messageID, {
commandName,
messageID: info.messageID,
author: senderID,
threadID,
themes: themes,
createdAt: Date.now()
});
});
} catch (error) {
console.error("[THEME] Generation Error:", error);
return message.reply(`❌ Theme generation failed.\n\nReason: ${error.message || error}`);
}
}
};
function normalizeThemes(result) {
if (!result) return [];
if (Array.isArray(result)) return result;
if (result.themes && Array.isArray(result.themes)) return result.themes;
if (result.data?.themes && Array.isArray(result.data.themes)) return result.data.themes;
if (result.results && Array.isArray(result.results)) return result.results;
if (result.data && Array.isArray(result.data)) return result.data;
if (result.id || result.themeId || result.theme_fbid) return [result];
return [];
}