// code from goatstore // api: https://store.agi.bd const { getStreamsFromAttachment } = global.utils; module.exports = { config: { name: "notification", aliases: ["notify", "noti", "broadcast"], version: "3.1", author: "NTKhang | NIROB", countDown: 5, role: 2, description: { vi: "Gửi thông báo từ admin đến all box (có hỗ trợ phản hồi)", en: "Send notification from admin to all boxes (with reply support)" }, category: "owner", guide: { en: "{pn} \nOr reply to a notification message to send reply to admin" }, envConfig: { delayPerGroup: 250 } }, langs: { vi: { missingMessage: "✨ 𝐕𝐮𝐢 𝐥𝐨̀𝐧𝐠 𝐧𝐡𝐚̣̂𝐩 𝐭𝐢𝐧 𝐧𝐡𝐚̆́𝐧 𝐛𝐚̣𝐧 𝐦𝐮𝐨̂́𝐧 𝐠𝐮̛̉𝐢", notification: "📢 𝐓𝐡𝐨̂𝐧𝐠 𝐛𝐚́𝐨 𝐭𝐮̛̀ 𝐀𝐝𝐦𝐢𝐧", sendingNotification: "⏳ Đ𝐚𝐧𝐠 𝐠𝐮̛̉𝐢 𝐭𝐡𝐨̂𝐧𝐠 𝐛𝐚́𝐨 đ𝐞̂́𝐧 %1 𝐧𝐡𝐨́𝐦...", sentNotification: "✅ Đ𝐚̃ 𝐠𝐮̛̉𝐢 𝐭𝐡𝐨̂𝐧𝐠 𝐛𝐚́𝐨 𝐭𝐡𝐚̀𝐧𝐡 𝐜𝐨̂𝐧𝐠 đ𝐞̂́𝐧 %1 𝐧𝐡𝐨́𝐦", errorSendingNotification: "❌ 𝐋𝐨̂̃𝐢 𝐤𝐡𝐢 𝐠𝐮̛̉𝐢 đ𝐞̂́𝐧 %1 𝐧𝐡𝐨́𝐦:\n%2", replyToAdmin: "💬 𝐑𝐞𝐩𝐥𝐢𝐞𝐝 𝐛𝐲", replySent: "✅ 𝐘𝐨𝐮𝐫 𝐫𝐞𝐩𝐥𝐲 𝐡𝐚𝐬 𝐛𝐞𝐞𝐧 𝐬𝐞𝐧𝐭 𝐭𝐨 𝐀𝐝𝐦𝐢𝐧", noOriginalMessage: "❌ 𝐂𝐨𝐮𝐥𝐝 𝐧𝐨𝐭 𝐟𝐢𝐧𝐝 𝐭𝐡𝐞 𝐨𝐫𝐢𝐠𝐢𝐧𝐚𝐥 𝐦𝐞𝐬𝐬𝐚𝐠𝐞", adminReply: "📢 𝐀𝐝𝐦𝐢𝐧 𝐫𝐞𝐩𝐥𝐲 𝐭𝐨 𝐲𝐨𝐮𝐫 𝐦𝐞𝐬𝐬𝐚𝐠𝐞:" }, en: { missingMessage: "✨ 𝐏𝐥𝐞𝐚𝐬𝐞 𝐞𝐧𝐭𝐞𝐫 𝐭𝐡𝐞 𝐦𝐞𝐬𝐬𝐚𝐠𝐞 𝐲𝐨𝐮 𝐰𝐚𝐧𝐭 𝐭𝐨 𝐬𝐞𝐧𝐝", notification: "📢 𝐍𝐨𝐭𝐢𝐟𝐢𝐜𝐚𝐭𝐢𝐨𝐧 𝐟𝐫𝐨𝐦 𝐀𝐝𝐦𝐢𝐧", sendingNotification: "⏳ 𝐒𝐞𝐧𝐝𝐢𝐧𝐠 𝐧𝐨𝐭𝐢𝐟𝐢𝐜𝐚𝐭𝐢𝐨𝐧 𝐭𝐨 %1 𝐠𝐫𝐨𝐮𝐩𝐬...", sentNotification: "✅ 𝐒𝐞𝐧𝐭 𝐧𝐨𝐭𝐢𝐟𝐢𝐜𝐚𝐭𝐢𝐨𝐧 𝐭𝐨 %1 𝐠𝐫𝐨𝐮𝐩𝐬 𝐬𝐮𝐜𝐜𝐞𝐬𝐬𝐟𝐮𝐥𝐥𝐲", errorSendingNotification: "❌ 𝐄𝐫𝐫𝐨𝐫 𝐬𝐞𝐧𝐝𝐢𝐧𝐠 𝐭𝐨 %1 𝐠𝐫𝐨𝐮𝐩𝐬:\n%2", replyToAdmin: "💬 𝐑𝐞𝐩𝐥𝐢𝐞𝐝 𝐛𝐲", replySent: "✅ 𝐘𝐨𝐮𝐫 𝐫𝐞𝐩𝐥𝐲 𝐡𝐚𝐬 𝐛𝐞𝐞𝐧 𝐬𝐞𝐧𝐭 𝐭𝐨 𝐀𝐝𝐦𝐢𝐧", noOriginalMessage: "❌ 𝐂𝐨𝐮𝐥𝐝 𝐧𝐨𝐭 𝐟𝐢𝐧𝐝 𝐭𝐡𝐞 𝐨𝐫𝐢𝐠𝐢𝐧𝐚𝐥 𝐦𝐞𝐬𝐬𝐚𝐠𝐞", adminReply: "📢 𝐀𝐝𝐦𝐢𝐧 𝐫𝐞𝐩𝐥𝐲 𝐭𝐨 𝐲𝐨𝐮𝐫 𝐦𝐞𝐬𝐬𝐚𝐠𝐞:" } }, onStart: async function ({ message, api, event, args, commandName, envCommands, threadsData, getLang, usersData }) { const { delayPerGroup } = envCommands[commandName]; const { threadID, messageID, senderID, isGroup } = event; // Store reply info if (!global.notificationReplies) { global.notificationReplies = new Map(); } // Handle user reply to notification (user → admin) if (event.messageReply) { const originalMsg = event.messageReply; if (originalMsg.body && originalMsg.body.includes("📢 𝐍𝐨𝐭𝐢𝐟𝐢𝐜𝐚𝐭𝐢𝐨𝐧 𝐟𝐫𝐨𝐦 𝐀𝐝𝐦𝐢𝐧")) { try { const adminID = global.GoatBot.config.adminBot[0]; // Get user info const userInfo = await usersData.get(senderID); const userName = userInfo.name; // Get group info const threadData = await threadsData.get(threadID); const groupName = threadData.threadName || `Group ${threadID}`; // Store for reply tracking const replyKey = `reply_${Date.now()}`; global.notificationReplies.set(replyKey, { userID: senderID, threadID: threadID, userName: userName, groupName: groupName }); // Send to admin in this exact format const replyMessage = { body: `💬 𝐑𝐞𝐩𝐥𝐢𝐞𝐝 𝐛𝐲 ${userName}:\n` + `"${args.join(" ")}"\n\n` + `𝐅𝐫𝐨𝐦: ${groupName}\n` + `𝐑𝐞𝐩𝐥𝐲 𝐤𝐞𝐲: ${replyKey}`, attachment: await getStreamsFromAttachment( [...event.attachments].filter(item => ["photo", "png", "animated_image", "video", "audio"].includes(item.type)) ) }; await api.sendMessage(replyMessage, adminID); return message.reply(getLang("replySent")); } catch (error) { console.error("Error forwarding reply:", error); return message.reply(getLang("noOriginalMessage")); } } } // Handle admin reply (admin → user's group) if (args[0] && args[0].startsWith("reply_")) { const replyKey = args[0]; const replyText = args.slice(1).join(" "); const replyInfo = global.notificationReplies.get(replyKey); if (!replyInfo) { return message.reply("❌ Reply information not found."); } try { // Send reply directly to that specific group const replyToGroup = { body: `📢 𝐀𝐝𝐦𝐢𝐧 𝐫𝐞𝐩𝐥𝐲 𝐭𝐨 ${replyInfo.userName}:\n` + `"${replyText}"`, attachment: await getStreamsFromAttachment( [...event.attachments].filter(item => ["photo", "png", "animated_image", "video", "audio"].includes(item.type)) ) }; await api.sendMessage(replyToGroup, replyInfo.threadID); // Clean up global.notificationReplies.delete(replyKey); return message.reply(`✅ Reply sent to ${replyInfo.userName}'s group`); } catch (error) { return message.reply(`❌ Failed: ${error.message}`); } } // Send notification to all groups if (!args[0]) return message.reply(getLang("missingMessage")); const formSend = { body: `${getLang("notification")}\n────────────────\n${args.join(" ")}\n\n💬 Reply to this message to send message to Admin`, attachment: await getStreamsFromAttachment( [ ...event.attachments, ...(event.messageReply?.attachments || []) ].filter(item => ["photo", "png", "animated_image", "video", "audio"].includes(item.type)) ) }; const allThreadID = (await threadsData.getAll()).filter(t => t.isGroup && t.members.find(m => m.userID == api.getCurrentUserID())?.inGroup); message.reply(getLang("sendingNotification", allThreadID.length)); let sendSucces = 0; const sendError = []; const wattingSend = []; for (const thread of allThreadID) { const tid = thread.threadID; try { wattingSend.push({ threadID: tid, pending: api.sendMessage(formSend, tid) }); await new Promise(resolve => setTimeout(resolve, delayPerGroup)); } catch (e) { sendError.push(tid); } } for (const sended of wattingSend) { try { await sended.pending; sendSucces++; } catch (e) { const { errorDescription } = e; if (!sendError.some(item => item.errorDescription == errorDescription)) sendError.push({ threadIDs: [sended.threadID], errorDescription }); else sendError.find(item => item.errorDescription == errorDescription).threadIDs.push(sended.threadID); } } let msg = ""; if (sendSucces > 0) msg += getLang("sentNotification", sendSucces) + "\n"; if (sendError.length > 0) msg += getLang("errorSendingNotification", sendError.reduce((a, b) => a + b.threadIDs.length, 0), sendError.reduce((a, b) => a + `\n - ${b.errorDescription}\n + ${b.threadIDs.join("\n + ")}`, "")); message.reply(msg); } };