// code from goatstore // api: https://store.agi.bd const { getStreamsFromAttachment } = global.utils; const moment = require("moment-timezone"); module.exports = { config: { name: "notification", aliases: ["notify", "noti"], version: "3.0", author: "Siam Ahmed Saan", countDown: 100, role: 2, shortDescription: { en: "Premium notification sender with progress tracking" }, longDescription: { en: "Send text/media notifications to all groups with real-time progress and anti-ban delay." }, category: "owner", guide: { en: "{pn} " }, envConfig: { delayPerGroup: 250 } }, onStart: async function ({ message, api, event, args, commandName, envCommands, threadsData, usersData }) { const { delayPerGroup } = envCommands[commandName]; const { senderID, threadID } = event; const senderName = await usersData.getName(senderID) || "Admin"; const now = moment().tz("Asia/Dhaka"); const timeString = now.format("hh:mm A"); const dateString = now.format("DD/MM/YYYY"); const msgText = args.join(" ") || ""; const attachments = [ ...(event.attachments || []), ...(event.messageReply?.attachments || []) ].filter(item => ["photo", "animated_image", "video", "audio", "sticker"].includes(item.type)); if (!msgText && attachments.length === 0) return message.reply("āš ļø š—£š—¹š—²š—®š˜€š—² š—½š—æš—¼š˜ƒš—¶š—±š—² š—® š—ŗš—²š˜€š˜€š—®š—“š—² š—¼š—æ š—®š˜š˜š—®š—°š—µ š—ŗš—²š—±š—¶š—®."); let streamAttachments = []; if (attachments.length > 0) { try { streamAttachments = await getStreamsFromAttachment(attachments); } catch (err) { return message.reply("āŒ š— š—²š—±š—¶š—® š—£š—æš—¼š—°š—²š˜€š˜€š—¶š—»š—“ š—™š—®š—¶š—¹š—²š—±: Check if the file is too large."); } } const owner = "š—¦š—¶š—®š—ŗ š—”š—µš—ŗš—²š—± š—¦š—®š—®š—»"; const formSend = { body: `╭━━━〔 š—”š—¢š—§š—œš—™š—œš—–š—”š—§š—œš—¢š—” 〕━━━╮\nā”ƒ š—¢š—Ŗš—”š—˜š—„: ${owner}\nā”ƒ š—”š——š— š—œš—”: ${senderName}\n╰━━━━━━━━━━━━━━━━━━━━╯\n\nšŸ•’ š—§š—¶š—ŗš—²: ${timeString} | ${dateString}\n\nšŸ“ š— š—²š˜€š˜€š—®š—“š—²:\n───────────────────\n${msgText || "(Media Attachment)"}\n───────────────────\n\nšŸ“¢ `, attachment: streamAttachments }; const allThreads = (await threadsData.getAll()).filter( t => t.isGroup && t.members.some(m => m.userID == api.getCurrentUserID() && m.inGroup) ); const total = allThreads.length; let sent = 0, failed = 0; const statusMsg = await message.reply(`šŸš€ š—œš—»š—¶š˜š—¶š—®š˜š—¶š—»š—“ š—”š—¼š˜š—¶š—³š—¶š—°š—®š˜š—¶š—¼š—»...\nšŸ“Š š—§š—®š—æš—“š—²š˜: ${total} Groups.`); for (const thread of allThreads) { try { await api.sendMessage(formSend, thread.threadID); sent++; } catch (e) { failed++; console.error(`Error in ${thread.threadID}:`, e); } if ((sent + failed) % 5 === 0 || (sent + failed) === total) { await api.editMessage(`šŸ“” š—¦š—²š—»š—±š—¶š—»š—“ š—”š—¼š˜š—¶š—³š—¶š—°š—®š˜š—¶š—¼š—»...\n━━━━━━━━━━━━━━━━━━\nāœ… š—¦š—²š—»š˜: ${sent}\nāŒ š—™š—®š—¶š—¹š—²š—±: ${failed}\nā³ š—£š—æš—¼š—“š—æš—²š˜€š˜€: ${Math.round(((sent + failed) / total) * 100)}%`, statusMsg.messageID, threadID); } const finalDelay = attachments.length > 0 ? 1500 : delayPerGroup; await new Promise(res => setTimeout(res, finalDelay)); } const finalReport = `āœ… š—”š—¼š˜š—¶š—³š—¶š—°š—®š˜š—¶š—¼š—» š—–š—¼š—ŗš—½š—¹š—²š˜š—²š—±!\n━━━━━━━━━━━━━━━━━━\nšŸŽÆ š—§š—¼š˜š—®š—¹ š—§š—®š—æš—“š—²š˜: ${total}\n🟢 š—¦š˜‚š—°š—°š—²š˜€š˜€š—³š˜‚š—¹: ${sent}\nšŸ”“ š—™š—®š—¶š—¹š—²š—±: ${failed}\n\n✨ š—”š—¹š—¹ š—“š—æš—¼š˜‚š—½š˜€ š—µš—®š˜ƒš—² š—Æš—²š—²š—» š—½š—æš—¼š—°š—²š˜€š˜€š—²š—±.`; return api.editMessage(finalReport, statusMsg.messageID, threadID); } };