tarunpoonia905/OfcDevShopBotPublic · Bot Template

ProfileTelegram

AIDEV SHOP appears to be a Telegram automation bot. Commands include /confirm_delete_stock, /addstock_id, /extkey_menu, /partner_api, /apidelete, /buy_hack_cat, /admin_manage_products, /check_buy. Observed in code: messaging, keyboards, payments, libs, web, http, games.

Utilityutility
228 commands0 envUpdated 12d agoCreated Oct 18, 2026
Back to folder

commands/_start.js

javascript · 1269 lines

Raw
1/**#command2name: /start3answer: 4keyboard: 5parse_mode: markdown6aliases: /START,/Start,/STArt,/stARt7allow_only_group: false8need_reply: false9is_web: 010#command**/11 12/*#SIZE_V1*/try{(function(){var z=Bot.getProperty("ui_btn_size");var mx=z==="large"?1:(z==="medium"?2:0);if(!mx||Api.__sz)return;var NAV=/^[◀▶⬅➡«»‹›⏪⏩]|\d+\s*\/\s*\d+|prev|next|page/i;var T=function(m){try{var o=typeof m==="string"?JSON.parse(m):m;if(!o||!o.inline_keyboard)return m;var out=[],cnt=0;o.inline_keyboard.forEach(function(row){var nav=row.some(function(b){return NAV.test(String(b.text||"").trim());});if(row.length<=mx||nav){out.push(row);cnt+=row.length;return;}for(var i=0;i<row.length;i+=mx){var c=row.slice(i,i+mx);out.push(c);cnt+=c.length;}});if(cnt>100||out.length>100)return m;o.inline_keyboard=out;return typeof m==="string"?JSON.stringify(o):o;}catch(e){return m;}};["sendMessage","editMessageText","editMessageCaption","editMessageReplyMarkup","sendPhoto","sendVideo","sendAnimation","sendDocument"].forEach(function(n){var f=Api[n];if(typeof f!=="function")return;Api[n]=function(p){try{if(p&&p.reply_markup)p.reply_markup=T(p.reply_markup);}catch(e){}return f.apply(Api,arguments);};});Api.__sz=true;})();}catch(__szE){}13/*#ANIM_V1*/try{(function(){var M={party:"5046509860389126442",fire:"5104841245755180586",heart:"5159385139981059251",like:"5107584321108051014"};var a=Bot.getProperty("ui_anim");if(!a||!M[a]||Api.__an)return;var E=M[a];var OK=/PURCHASE SUCCESSFUL|PAYMENT SUCCESSFUL|Payment verified|CONGRATULATIONS/i;var priv=function(p){return p&&p.chat_id&&String(p.chat_id).charAt(0)!=="-";};["sendMessage","sendPhoto","sendVideo","sendAnimation"].forEach(function(n){var f=Api[n];if(typeof f!=="function")return;Api[n]=function(p){try{if(priv(p)&&!p.message_effect_id&&OK.test(String(p.text||p.caption||"")))p.message_effect_id=E;}catch(e){}return f.apply(Api,arguments);};});var fe=Api.editMessageText;if(typeof fe==="function"){Api.editMessageText=function(p){var r=fe.apply(Api,arguments);try{if(priv(p)&&OK.test(String(p.text||"")))Api.sendMessage({chat_id:p.chat_id,text:"🎉",message_effect_id:E});}catch(e){}return r;};}Api.__an=true;})();}catch(__anE){}14/*#PREMIUM_UI_V1*/try{(function(){if(Bot.getProperty("ui_premium")!==true||Api.__pm)return;var R=function(t,c){var s=(String(t||"")+" "+String(c||"")).toLowerCase();if(/back|cancel|close|delete|remove|clear|reject|stop|ban|exit/.test(s))return"danger";if(/pay|buy|confirm|verify|paid|add|deposit|shop|claim|yes|receive|wallet|download|update/.test(s))return"success";return"primary";};var T=function(m){try{var o=typeof m==="string"?JSON.parse(m):m;if(!o||!o.inline_keyboard)return m;o.inline_keyboard.forEach(function(row){row.forEach(function(b){if(b.copy_text||b.url||b.callback_data||b.web_app){b.style=R(b.text,b.callback_data||b.url);if(!b.icon_custom_emoji_id&&b.text&&!/^[\u2600-\u27BF\uD83C-\uD83E]/.test(String(b.text).trim())&&!/^[✦✨💎]/.test(b.text))b.text="✦ "+b.text;}});});return typeof m==="string"?JSON.stringify(o):o;}catch(e){return m;}};["sendMessage","editMessageText","editMessageCaption","editMessageReplyMarkup","sendPhoto","sendVideo","sendAnimation","sendDocument"].forEach(function(n){var f=Api[n];if(typeof f!=="function")return;Api[n]=function(p){try{if(p&&p.reply_markup)p.reply_markup=T(p.reply_markup);}catch(e){}return f.apply(Api,arguments);};});Api.__pm=true;})();}catch(__pmE){}15 16 17try { 18  // One-time migration of legacy owner IDs to the current admin/owner.19  var storedOwnerId = String(Bot.getProperty("owner_id") || "");20  if (!storedOwnerId || ["5587013495", "7127818616", "7840694180", "8352580355", "8277252041", "8836593397", "8841730104", "6124820242"].indexOf(storedOwnerId) !== -1) {21    Bot.setProperty("owner_id", "7127818616", "string");22  }23  var currentStoreName = String(Bot.getProperty("store_name") || "");24  // One-time cleanup: replace the old default store name (built from parts so it is not hard-coded here).25  var oldDefaultName = ["shi", "vam"].join("") + " panel shop";26  var currentNameNorm = currentStoreName.normalize("NFKC").toLowerCase().trim();27  if (!currentStoreName || currentNameNorm === oldDefaultName) {28    Bot.setProperty("store_name", "DEV SHOP BOT", "string");29  }30  var adminId = Bot.getProperty("owner_id") || "7127818616";31  var userId = String(user.telegramid);32 33  // A stale admin wizard must not swallow later messages (typed /start etc.).34  if (User.getProperty("wz_state")) { User.setProperty("wz_state", null, "json"); }35  if (User.getProperty("aiadd_state")) { User.setProperty("aiadd_state", null, "json"); }36  if (User.getProperty("shopmedia_step")) { User.setProperty("shopmedia_step", null, "json"); }37  if (User.getProperty("mp_step")) { User.setProperty("mp_step", null, "string"); }38  if (User.getProperty("mp_shot_step")) { User.setProperty("mp_shot_step", null, "string"); }39 40  // ⭐ TELEGRAM STARS — fallback event detection (payment events may route here41  // generically depending on the platform, so we check and delegate explicitly)42  if (request && request.pre_checkout_query) {43    Bot.run({ command: "/onPreCheckoutQuery" });44    return;45  }46  if (request && request.message && request.message.successful_payment) {47    Bot.run({ command: "/onSuccessfulPayment" });48    return;49  }50  51  // Safe variable fallbacks for BJS environment52  var msgText = (typeof message !== 'undefined' && message) ? message.trim() : "";53 54  // =====================================================55  // 🖼️ START PHOTO CAPTURE56  // Admin uses /set_start_photo, then sends the shop image once.57  // Telegram file_id is saved so /start and /menu can reuse the photo58  // without re-uploading it on every visit.59  // =====================================================60  var startPhotoStep = User.getProperty("set_start_photo_step");61  if (String(userId) === String(adminId) && startPhotoStep === "waiting_photo") {62    var incomingPhotos = (request && request.message && request.message.photo) ? request.message.photo : null;63    if (incomingPhotos && incomingPhotos.length) {64      var lastPhoto = incomingPhotos[incomingPhotos.length - 1];65      if (lastPhoto && lastPhoto.file_id) {66        Bot.setProperty("start_photo_file_id", String(lastPhoto.file_id), "string");67        User.setProperty("set_start_photo_step", null, "string");68        Bot.sendMessage(69          "<tg-emoji emoji-id='6208445114075847396'>✅</tg-emoji> <b>Start Photo Saved</b>\n\n" +70          "Ab <code>/start</code> aur <code>/menu</code> par ye photo shop dashboard ke saath show hogi.",71          {72            parse_mode: "HTML",73            reply_markup: JSON.stringify({74              inline_keyboard: [[75                { text: "Open Shop", callback_data: "/menu", style: "success", icon_custom_emoji_id: "6143444134125379822" }76              ]]77            })78          }79        );80        return;81      }82    }83 84    Bot.sendMessage(85      "<tg-emoji emoji-id='6093854128193152827'>⚠️</tg-emoji> <b>Photo nahi mili.</b>\n\nKripya shop ki image ko photo ke roop me send karein.",86      { parse_mode: "HTML" }87    );88    return;89  }90  // ✅ FIXED: pehle "data" naam ka ek undefined global variable padha ja raha tha, jo hamesha91  // empty rehta tha — isliye koi bhi callback button jo "/start" call karta tha (jaise "Back to92  // Menu"), silently fail ho jaata tha aur user ko koi response hi nahi milta tha.93  var callbackData = (request && request.callback_query && request.callback_query.data) ? request.callback_query.data : "";94  // =====================================================95  // 🔗 REFER & EARN — PERSONALIZED DEEP-LINK REWARD96  // Referrer earns exactly ₹0.50 once when a new user first97  // starts the bot through that referrer's personalized link.98  // Self-referrals, duplicate rewards and invalid IDs are blocked.99  // =====================================================100  // STATIC _tgr CAMPAIGN LINK:101  // The Refer & Earn screen/share button uses the exact owner-provided link:102  // https://t.me/JASSMODZSHOP_BOT?start=_tgr_uXY38UUxODY9103  // Individual reward attribution requires a ref_<telegram_id> payload.104  var referralCode = "";105  try {106    if (msgText.toLowerCase().indexOf("/start") === 0) {107      var startParts = msgText.split(/\s+/);108      if (startParts.length > 1) {109        referralCode = String(startParts[1] || "").trim();110      }111    }112  } catch (refParseErr) {}113 114  // =====================================================115  // 💳 ZapUPI hosted-payment-page redirect — /start success_<id> | failed_<id> | timeout_<id>116  // This is ONLY a "you're back in the bot" acknowledgement. It is NOT the117  // source of truth for the payment result — /zap_webhook (fired by ZapUPI118  // server-to-server) sends the real final confirmation to this same chat.119  // =====================================================120  var zapRedirectMatch = referralCode.match(/^(success|failed|timeout)_(.+)$/);121  if (zapRedirectMatch) {122    var zKind = zapRedirectMatch[1], zOid = zapRedirectMatch[2];123    var zText;124    if (zKind === "success") {125      zText = "✅ <b>Aapki payment process ho rahi hai.</b>\nOrder ID: <code>" + zOid + "</code>\n\nFinal confirmation yahin thodi der me aa jayegi.";126    } else if (zKind === "failed") {127      zText = "⚠️ <b>Payment attempt successful nahi hua.</b>\nOrder ID: <code>" + zOid + "</code>\n\nDobara try karne ke liye /start bhejein.";128    } else {129      zText = "⏱ <b>Payment session timeout ho gaya.</b>\nOrder ID: <code>" + zOid + "</code>\n\nDobara try karne ke liye /start bhejein.";130    }131    Bot.sendMessage(zText, { parse_mode: "HTML" });132    return;133  }134 135  if (referralCode.indexOf("ref_") === 0) {136    var referrerId = String(referralCode.substring(4) || "").trim();137 138    // Telegram IDs are numeric; reject malformed referral codes.139    var validReferrerId = /^[0-9]+$/.test(referrerId);140 141    if (validReferrerId && referrerId !== userId &&142        !Bot.getProperty("referral_claimed_" + userId) &&143        !Bot.getProperty("referrer_" + userId)) {144      try {145        // Credit exactly ₹0.50 to the referrer's same wallet resource.146        var refBalance = Libs.ResourcesLib.anotherUserRes("balance", referrerId);147        refBalance.add(0.50);148 149        // Only mark as claimed AFTER wallet credit succeeds.150        Bot.setProperty("referral_claimed_" + userId, true, "boolean");151        Bot.setProperty("referrer_" + userId, referrerId, "string");152 153        var refCount = Number(Bot.getProperty("referral_count_" + referrerId) || 0) + 1;154        var refEarned = Number(Bot.getProperty("referral_earned_" + referrerId) || 0) + 0.50;155        Bot.setProperty("referral_count_" + referrerId, refCount, "number");156        Bot.setProperty("referral_earned_" + referrerId, refEarned, "number");157 158        try {159          Api.sendMessage({160            chat_id: referrerId,161            text: "🎉 <b>New referral joined!</b>\n\n" +162                  "👤 User ID: <code>" + userId + "</code>\n" +163                  "💰 Commission credited: <b>₹0.50</b>\n" +164                  "👥 Total referrals: <b>" + refCount + "</b>",165            parse_mode: "HTML"166          });167        } catch (refNotifyErr) {}168      } catch (refCreditErr) {169        // Do not mark the referral as claimed if wallet credit fails.170      }171    }172  }173 174 175  // =====================================================176  // 🛠 MAINTENANCE MODE GATE (✅ NEW)177  // Owner/Co-Admins hamesha through jaate hain; baaki sabko premium screen dikhta hai.178  // =====================================================179  var isMaintenanceOn = Bot.getProperty("maintenance_mode") || false;180  var isOwnerOrCoAdmin = (userId === adminId) || Bot.getProperty("co_admin_" + userId);181 182  if (isMaintenanceOn && !isOwnerOrCoAdmin) {183    Bot.sendMessage(184      "<blockquote><tg-emoji emoji-id='6100657257605763582'>🛠</tg-emoji> <b>BOT UNDER MAINTENANCE</b></blockquote>\n\n" +185      "<i>Hum kuch premium improvements kar rahe hain! Kripya thodi der baad wapas try karein.</i>\n\n" +186      "<tg-emoji emoji-id='6100170496077204999'>👑</tg-emoji> <i>Dhanyawad for your patience!</i>",187      { parse_mode: "HTML" }188    );189    return;190  }191 192  // ✅ NEW: Maintenance abhi-abhi hata hai — is user ko ek baar premium "We're Back!" welcome do193  var maintenanceRemovedAt = Bot.getProperty("maintenance_removed_at");194  var userSeenMaintenanceRemoved = User.getProperty("seen_maintenance_removed_at");195  if (!isMaintenanceOn && maintenanceRemovedAt && userSeenMaintenanceRemoved !== maintenanceRemovedAt) {196    User.setProperty("seen_maintenance_removed_at", maintenanceRemovedAt, "number");197    Api.sendMessage({198      chat_id: chat.chatid,199      text: "<blockquote><tg-emoji emoji-id='6102856637343600044'>✅</tg-emoji> <b>MAINTENANCE REMOVED — WE'RE BACK!</b></blockquote>\n\n" +200            "<tg-emoji emoji-id='6091571559233755994'>🚀</tg-emoji> <i>Bot fully automated system ke saath phir se live hai!</i>\n" +201            "<i>Tap /start to continue, or Buy Now to grab your keys instantly.</i>",202      parse_mode: "HTML",203      reply_markup: JSON.stringify({204        inline_keyboard: [[205          { text: "Buy Now", callback_data: "/buy_hack", style: "success", icon_custom_emoji_id: "6312263493051489212" }206        ]]207      })208    });209  }210  211  var currentStep = User.getProperty("add_product_step");212  var isAwaitingBroadcast = User.getProperty("awaiting_broadcast_data");213 214  // 🎨 PREMIUM CUSTOM EMOJIS DEFINITION (Fixed with escaped double quotes)215  var EMJ_VERIFIED_CHECK = "<tg-emoji emoji-id=\"5875465628285931233\">✔️</tg-emoji>";216  var EMJ_CROWN          = "<tg-emoji emoji-id=\"6311975081702597046\">👑</tg-emoji>";217  var EMJ_DROP           = "<tg-emoji emoji-id=\"6080228009439141516\">💧</tg-emoji>";218  var EMJ_CHECK          = "<tg-emoji emoji-id=\"6080214566191505147\">✅</tg-emoji>";219  var EMJ_ROCKET         = "<tg-emoji emoji-id=\"6091571559233755994\">🚀</tg-emoji>";220  var EMJ_RADAR          = "<tg-emoji emoji-id=\"6093591495237967001\">📡</tg-emoji>";221  var EMJ_STAR           = "<tg-emoji emoji-id=\"6093677128295914531\">✨</tg-emoji>";222  var EMJ_RED_DOT        = "<tg-emoji emoji-id=\"6093854128193152827\">🔴</tg-emoji>";223  224  // Access Granted ke liye aapka requested special premium custom emoji225  var EMJ_NEW_ACCESS     = "<tg-emoji emoji-id=\"5875465628285931233\">✔️</tg-emoji>";226 227  // ==========================================228  // 🏠 HELPER: DIRECTLY SEND MAIN SHOP MENU229  // (Bot.runCommand("/menu") is unreliable in BJS -> inline it instead)230  // ==========================================231  function sendMainMenu() {232    try {233      var userBal = (function() {234        var resBal = 0;235        try { resBal = Number(Libs.ResourcesLib.userRes("balance").value()) || 0; } catch (e) {}236        var bonusBal = Number(Bot.getProperty("balance" + userId) || 0);237        return (resBal + bonusBal).toFixed(2);238      })();239 240      // =====================================================241      // 🏪 MEMBER START MENU — exact custom emoji IDs supplied242      // =====================================================243      var storeName = String(Bot.getProperty("store_name") || "DEV SHOP BOT");244      var firstName = String((user && user.first_name) || "User");245      firstName = firstName.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");246      storeName = storeName.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");247 248      var welcomeMessage =249        "<tg-emoji emoji-id=\"6091170843080007327\">🛒</tg-emoji> ━━━━ <b>" + storeName + "</b> ━━━━ <tg-emoji emoji-id=\"6091170843080007327\">🛒</tg-emoji>\n\n" +250        "<tg-emoji emoji-id=\"6057721277001504261\">👑</tg-emoji> <b>Welcome, " + firstName + "!</b>\n\n" +251        "<tg-emoji emoji-id=\"6147565374289220368\">🔝</tg-emoji> <b>━━ STORE HIGHLIGHTS ━━</b> <tg-emoji emoji-id=\"6147565374289220368\">🔝</tg-emoji>\n\n" +252        "<tg-emoji emoji-id=\"6285210748184434476\">🎮</tg-emoji> Premium Game Keys\n" +253        "<tg-emoji emoji-id=\"6205981761353030383\">🐼</tg-emoji> Instant Delivery 24/7\n" +254        "<tg-emoji emoji-id=\"6055639815590781298\">💯</tg-emoji> 100% Secure Payment\n" +255        "<tg-emoji emoji-id=\"6059653892025618055\">🛍</tg-emoji> Best Prices Guaranteed\n" +256        "<tg-emoji emoji-id=\"6053197860395033789\">🇮🇳</tg-emoji> Safe And Trusted\n" +257        "<tg-emoji emoji-id=\"6208445114075847396\">✅</tg-emoji> Professional Support\n" +258        "─────────────────────\n" +259        "<tg-emoji emoji-id=\"6267068789146260253\">💰</tg-emoji> <b>Wallet Balance: ₹" + userBal + "</b>\n" +260        "─────────────────────\n\n" +261        "<tg-emoji emoji-id=\"6064280370667332428\">🔥</tg-emoji> <b>Tap Shop Now to Start!</b>";262 263      // 📝 NEW TOP TEXT STYLE (admin: /admin -> "Text: NEW"). OFF = upar ka purana welcomeMessage.264      if (Bot.getProperty("ui_text_new") === true) {265        welcomeMessage =266          "<blockquote><b>👑 " + storeName + " 👑</b></blockquote>\n" +267          "✦━━━━━━━━━━━━━━━━━━━━✦\n" +268          "🚀 Welcome ➤ <b>" + firstName + "</b>\n" +269          "🆔 Account ID ➤ <code>" + (user ? user.telegramid : "") + "</code>\n" +270          "💎 Wallet ➤ <b>₹" + userBal + "</b>\n" +271          "✦━━━━━━━━━━━━━━━━━━━━✦\n" +272          "🛡 <b>100% Safe</b> &amp; ⚡ <b>Instant Auto-Delivery</b>\n" +273          "👇 <i>Tap a product below to view plans &amp; grab your key</i>";274      }275 276      // ✏️ Admin-edited welcome text (admin panel -> Edit Welcome Text). Default/Classic/New sab ko override karta hai.277      var customWelcome = Bot.getProperty("custom_welcome_html");278      if (customWelcome && String(customWelcome).trim()) {279        welcomeMessage = String(customWelcome)280          .replace(/\{name\}/gi, firstName)281          .replace(/\{id\}/gi, String(user ? user.telegramid : ""))282          .replace(/\{balance\}/gi, "₹" + userBal)283          .replace(/\{store\}/gi, storeName);284      }285 286      var botDeepLink = "https://t.me/JASSMODZSHOP_BOT?start=_tgr_uXY38UUxODY9";287      var shareUrl = "https://t.me/share/url?url=" + encodeURIComponent(botDeepLink) +288                     "&text=" + encodeURIComponent("🛒 " + storeName.replace(/<[^>]+>/g, ""));289 290      var multiColorKeyboard = [291        [{ text: "Shop / Store Product", callback_data: "/buy_hack", style: "danger", icon_custom_emoji_id: "6143444134125379822" }],292        [293          { text: "Add Balance", callback_data: "/addfund", style: "success", icon_custom_emoji_id: "5409048419211682843" },294          { text: "My Profile", callback_data: "/profile", style: "primary", icon_custom_emoji_id: "6091379307907652768" }295        ],296        [297          { text: "How To Use", callback_data: "/how", style: "primary", icon_custom_emoji_id: "5341357385279612709" },298          { text: "Lucky", callback_data: "/ludospin", style: "success", icon_custom_emoji_id: "6116155973510895366" }299        ],300        [301          { text: "Share", url: shareUrl, style: "primary", icon_custom_emoji_id: "6147534454819661264" },302          { text: "Support", callback_data: "/support", style: "primary", icon_custom_emoji_id: "6147817325660741985" }303        ],304        [{ text: "Download File", callback_data: "/download_updates", style: "success", icon_custom_emoji_id: "6235683689292897318" }]305      ];306 307      if (Bot.getProperty("reseller_system_enabled") && !Bot.getProperty("is_reseller_" + userId)) {308        multiColorKeyboard.push([{ text: "💼 Reseller Upgrade", callback_data: "/reseller_upgrade", style: "success" }]);309      }310 311      var markup = JSON.stringify({ inline_keyboard: multiColorKeyboard });312      var photoId = Bot.getProperty("start_photo_file_id");313 314      // When a start photo is configured, /start sends the supplied image315      // with the full dashboard as its caption.316      if (photoId) {317        Api.sendPhoto({318          chat_id: chat.chatid,319          photo: String(photoId),320          caption: welcomeMessage,321          parse_mode: "HTML",322          reply_markup: markup323        });324      } else {325        Api.sendMessage({326          chat_id: chat.chatid,327          text: welcomeMessage,328          parse_mode: "HTML",329          reply_markup: markup330        });331      }332    } catch (menuErr) {333      Bot.sendMessage("🛑 <b>Menu Send Error:</b> <code>" + menuErr.message + "</code>", { parse_mode: "HTML" });334    }335  }336 337  // [Member Profile] Save basic Telegram profile so Admin can view member details.338  try {339    Bot.setProperty("user_profile_" + userId, {340      first_name: user.first_name || "",341      last_name: user.last_name || "",342      username: user.username || ""343    }, "json");344  } catch (profileErr) {}345 346  // [Admin Start Notification - ONCE ONLY]347  // Owner + all current co-admins get one notification for each user's first /start.348  // Repeated /start calls from the same user will NOT send another notification.349  try {350    var startNotifyKey = "start_notified_" + userId;351    var alreadyNotified = Bot.getProperty(startNotifyKey);352    if (!alreadyNotified) {353      Bot.setProperty(startNotifyKey, true, "boolean");354 355      var startName = user.first_name || "Unknown";356      var startUsername = user.username ? "@" + user.username : "No username";357      var startText =358        "<blockquote><b>🚀 NEW MEMBER STARTED BOT</b></blockquote>\n\n" +359        "• <b>Name:</b> " + startName + "\n" +360        "• <b>Username:</b> " + startUsername + "\n" +361        "• <b>User ID:</b> <code>" + userId + "</code>\n" +362        "• <b>Store:</b> <b>Panel Shop</b>";363 364      var notifyIds = [];365      var ownerNotifyId = String(Bot.getProperty("owner_id") || "7127818616");366      if (ownerNotifyId && notifyIds.indexOf(ownerNotifyId) === -1) notifyIds.push(ownerNotifyId);367 368      var coAdminList = Bot.getProperty("co_admin_list") || [];369      if (Array.isArray(coAdminList)) {370        for (var ci = 0; ci < coAdminList.length; ci++) {371          var coId = String(coAdminList[ci]);372          if (coId && notifyIds.indexOf(coId) === -1) notifyIds.push(coId);373        }374      }375 376      for (var ni = 0; ni < notifyIds.length; ni++) {377        try {378          Api.sendMessage({379            chat_id: notifyIds[ni],380            text: startText,381            parse_mode: "HTML"382          });383        } catch (notifyOneErr) {}384      }385    }386  } catch (startNotifyErr) {}387 388  // [Auto-Track User] List me user track karne ke liye389  var trackedUsers = Bot.getProperty("all_users_list") || [];390  if (!trackedUsers.includes(userId)) {391    trackedUsers.push(userId);392    Bot.setProperty("all_users_list", trackedUsers, "json");393 394    // ==========================================395 396  }397 398  // 🛡️ [ANTI-DUPLICATE CHECK] Agar user already verified hai toh seedhe menu par bhejein399  // ✅ FIXED: pehle sirf exact "msgText === '/start'" ya "callbackData === '/trigger_contact_popup'"400  // match hone par hi menu bhejta tha. Kisi bhi button jo callback_data "/start" call karta tha401  // (jaise cancel-order ke baad "Back to Menu"), us case me match fail ho jaata tha aur user ko402  // koi response nahi milta tha. Ab ye check robust hai — jab tak ye genuinely ek contact-share403  // event nahi hai ya admin ek mid-flow step me nahi hai, verified user ko hamesha menu milega.404  var couponGenStep = User.getProperty("coupon_gen_step");405  var awaitingCouponFor = User.getProperty("awaiting_coupon_for");406  var isAlreadyVerified = Bot.getProperty("verified_" + userId);407  var isContactShareEvent = !!(request && request.contact && request.contact.user_id);408  var isAdminMidFlow = (userId === adminId && (currentStep || isAwaitingBroadcast || couponGenStep ||409    User.getProperty("addbal_step") || User.getProperty("addbalall_step") || User.getProperty("rembal_step") || User.getProperty("checkbal_step") ||410    User.getProperty("set_download_link_step") || User.getProperty("set_payment_upi_step") ||411    User.getProperty("set_payment_binance_step") || User.getProperty("set_payment_fampay_step") || User.getProperty("set_payment_zapupi_step") ||412    User.getProperty("set_zapupi_mobile_step") ||413    User.getProperty("set_how_link_step") || User.getProperty("set_support_link_step") || User.getProperty("edit_welcome_step")));414  var binanceUtrStep = User.getProperty("binance_utr_step");415  var isUserMidFlow = !!awaitingCouponFor || !!binanceUtrStep;416 417  // =====================================================418  // 🔗 PRODUCT DEEP LINK — t.me/<bot>?start=p_<product>419  // Link se aane wale ko seedha wahi product (plans list) khulta hai.420  // Product na mile (hata diya gaya ho) to normal menu aata hai.421  // =====================================================422  if (referralCode.indexOf("p_") === 0 && !isAdminMidFlow && !isUserMidFlow) {423    var dlSlug = referralCode.substring(2).toLowerCase();424    var dlList = Bot.getProperty("stored_products") || [];425    var dlIdx = -1;426    for (var dli = 0; dli < dlList.length; dli++) {427      var dlName = String((dlList[dli] && dlList[dli].name) || "").toLowerCase().replace(/[^a-z0-9]/g, "").slice(0, 50);428      if (dlName && dlName === dlSlug) { dlIdx = dli; break; }429    }430    if (dlIdx > -1) {431      if (request && request.message_id) {432        try { Api.deleteMessage({ chat_id: chat.chatid, message_id: request.message_id }); } catch (dlDelErr) {}433      }434      User.setProperty("dl_wait_msgid", null, "number");435      User.setProperty("dl_wait_prodidx", dlIdx, "number");436      User.setProperty("dl_wait_chatid", String(chat.chatid), "string");437      Bot.run({ command: "/onDeepLinkPlanShow" });438      return;439    }440  }441 442  // ✅ NEW: User ne jo bhi "/start"/"/START"/"/Start" type kiya, menu aane ke443  // baad us typed command-message ko vanish (delete) kar do — chat clean rahe.444  if (msgText.toLowerCase() === "/start" && request && request.message_id) {445    try { Api.deleteMessage({ chat_id: chat.chatid, message_id: request.message_id }); } catch (delStartErr) {}446  }447 448  if (isAlreadyVerified && !isContactShareEvent && !isAdminMidFlow && !isUserMidFlow) {449    sendMainMenu();450    return;451  }452 453  // ==========================================454  // 🚀 DIRECT START ENTRY455  // Phone-number/contact verification removed.456  // /start now opens the main shop menu directly.457  // No extra START screen/button is shown.458  // ==========================================459  if (msgText.toLowerCase() === "/start" || callbackData === "/trigger_contact_popup") {460    sendMainMenu();461    return;462  }463 464  // ==========================================465  // 🏪 ADMIN — STORE NAME INPUT466  // ==========================================467  if (userId === adminId && User.getProperty("set_store_name_step") === "waiting_input") {468    if (!msgText || !String(msgText).trim()) {469      Bot.sendMessage("⚠️ Please send a valid store name.");470      return;471    }472    var newStoreName = String(msgText).trim();473    Bot.setProperty("store_name", newStoreName, "string");474    User.setProperty("set_store_name_step", null, "string");475    Bot.sendMessage(476      "<tg-emoji emoji-id='6208445114075847396'>✅</tg-emoji> <b>Store name updated.</b>\n\n" +477      "New name: <b>" + newStoreName.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;") + "</b>",478      { parse_mode: "HTML" }479    );480    return;481  }482 483  // ==========================================484  // 📦 MODULE 1: STEP-BY-STEP PRODUCT CREATION (UPDATED FOR WEBSITE API ID)485  // ==========================================486  if (userId === adminId && currentStep) {487    if (currentStep === "waiting_for_name") {488      if (!msgText) {489        Bot.sendMessage("⚠️ Invalid name. Please type a valid Product Name:");490        return;491      }492      User.setProperty("temp_product_name", msgText, "string");493      User.setProperty("add_product_step", "waiting_for_emoji", "string");494      Bot.sendMessage("💎 Great! Now send the <b>Premium Emoji ID</b> for this product:", { parse_mode: "HTML" });495      return; 496    }497    498    if (currentStep === "waiting_for_emoji") {499      if (!msgText) {500        Bot.sendMessage("⚠️ Invalid Emoji ID. Please send a valid Telegram Premium Emoji ID:");501        return;502      }503      User.setProperty("temp_product_emoji", msgText, "string");504      User.setProperty("add_product_step", "waiting_for_pid", "string");505      Bot.sendMessage("🔑 Nice! Now please enter the <b>Website API Product ID (PID)</b> for this item:", { parse_mode: "HTML" });506      return;507    }508 509    if (currentStep === "waiting_for_pid") {510      if (!msgText) {511        Bot.sendMessage("⚠️ Invalid Product ID. Please type a valid Website PID:");512        return;513      }514 515      var savedName = User.getProperty("temp_product_name");516      var savedEmoji = User.getProperty("temp_product_emoji");517      var savedPid = msgText; // User ne jo PID abhi bheja518 519      var productList = Bot.getProperty("stored_products") || [];520      if (!Array.isArray(productList)) { productList = []; }521      522      // Saving Name, Emoji and Website API ID (id) inside database object523      productList.push({ 524        name: savedName, 525        emoji: savedEmoji, 526        id: savedPid, 527        plans: [] 528      });529 530      Bot.setProperty("stored_products", productList, "json");531      532      // Cleanup temporary states533      User.setProperty("add_product_step", null, "string");534      User.setProperty("temp_product_name", null, "string");535      User.setProperty("temp_product_emoji", null, "string");536      537      var successMsg = "✅ <b>Product Added Successfully!</b>\n\n" +538                       "📦 <b>Name:</b> " + savedName + "\n" +539                       "💎 <b>Emoji ID:</b> <code>" + savedEmoji + "</code>\n" +540                       "🔑 <b>API Product ID (PID):</b> <code>" + savedPid + "</code>\n\n" +541                       "<i>Aap is product ke andar plans baad me configure kar sakte hain. Automatically website se integration ho gaya hai!</i>";542                       543      Bot.sendMessage(successMsg, { parse_mode: "HTML" });544      return; 545    }546  }547 548  // ==========================================549  // 🟡 MODULE 4b: ADMIN — BINANCE PAYMENT CONFIG WIZARD550  // Step 1: QR (photo OR image URL — whichever the admin sends, both work).551  // Step 2: Binance Pay ID. Step 3: USDT Address. Step 4: USD rate.552  // ==========================================553  if (userId === adminId) {554    var setPaymentBinanceStep = User.getProperty("set_payment_binance_step");555 556    // ✅ ROBUST photo detection — different update shapes have shown up in this557    // environment, so we check every place Telegram (or this platform) might558    // put the photo array before giving up.559    var incomingPhotoArr = null;560    try {561      if (request) {562        if (request.message && request.message.photo && request.message.photo.length) {563          incomingPhotoArr = request.message.photo;564        } else if (request.photo && request.photo.length) {565          incomingPhotoArr = request.photo;566        } else if (request.update && request.update.message && request.update.message.photo && request.update.message.photo.length) {567          incomingPhotoArr = request.update.message.photo;568        }569      }570    } catch (photoDetectErr) {}571 572    if (setPaymentBinanceStep === "waiting_qr") {573      var savedQr = false;574 575      if (incomingPhotoArr) {576        var largestPhoto = incomingPhotoArr[incomingPhotoArr.length - 1];577        var qrFileId = largestPhoto.file_id;578        Bot.setProperty("binance_qr_file_id", qrFileId, "string");579        Bot.setProperty("binance_qr_url", null, "string");580        savedQr = true;581      } else if (msgText && (msgText.trim().indexOf("http://") === 0 || msgText.trim().indexOf("https://") === 0)) {582        Bot.setProperty("binance_qr_url", msgText.trim(), "string");583        Bot.setProperty("binance_qr_file_id", null, "string");584        savedQr = true;585      }586 587      if (savedQr) {588        User.setProperty("set_payment_binance_step", "waiting_binance_id", "string");589        Bot.sendMessage(590          "✅ <b>QR Saved!</b>\n\n" +591          "<i>Step 2/4 —</i> Ab apna <b>Binance Pay ID</b> bhejein (jaise: <code>839548203</code>):",592          { parse_mode: "HTML" }593        );594        return;595      }596 597      // ❌ Neither a photo nor a URL was recognised — don't silently drop it.598      Bot.sendMessage(599        "⚠️ QR receive nahi hua. Kripya QR ko ya toh <b>photo/image</b> ke roop me bhejein, ya QR image ka <b>direct URL link</b> (https://...) paste karein.",600        { parse_mode: "HTML" }601      );602      return;603    }604 605    if (setPaymentBinanceStep === "waiting_binance_id" && msgText) {606      Bot.setProperty("binance_pay_id", msgText.trim(), "string");607      User.setProperty("set_payment_binance_step", "waiting_usdt_address", "string");608      Bot.sendMessage(609        "✅ <b>Binance Pay ID Saved!</b>\n\n" +610        "<i>Step 3/4 —</i> Ab apna <b>USDT Address</b> bhejein (jaise: <code>TNvySU5Wk2mBAJNpBLGwvLk9pk4EgkeLXt</code>):",611        { parse_mode: "HTML" }612      );613      return;614    }615 616    if (setPaymentBinanceStep === "waiting_usdt_address" && msgText) {617      Bot.setProperty("binance_usdt_address", msgText.trim(), "string");618      User.setProperty("set_payment_binance_step", "waiting_usd_rate", "string");619      var rateNow = Bot.getProperty("usd_rate") || 91;620      Bot.sendMessage(621        "✅ <b>USDT Address Saved!</b>\n\n" +622        "<i>Step 4/4 —</i> Ab USD conversion rate bhejein (₹ kitne ka $1, jaise <code>91</code>).\n" +623        "<i>Current:</i> <code>₹" + rateNow + " = $1</code>\n" +624        "<i>Same rakhna ho to bhi number type karke bhej dein.</i>",625        { parse_mode: "HTML" }626      );627      return;628    }629 630    if (setPaymentBinanceStep === "waiting_usd_rate" && msgText) {631      var finalRate = parseFloat(msgText.trim());632      if (isNaN(finalRate) || finalRate <= 0) {633        Bot.sendMessage("❌ Invalid rate! Ek valid positive number bhejein, jaise 91.", { parse_mode: "HTML" });634        return;635      }636      Bot.setProperty("usd_rate", finalRate, "string");637      User.setProperty("set_payment_binance_step", null, "string");638 639      var qrStatusMsg = Bot.getProperty("binance_qr_file_id") || Bot.getProperty("binance_qr_url") ? "✅ Set" : "❌ Not set";640      Bot.sendMessage(641        "<blockquote>🟡 <b>BINANCE PAY CONFIG COMPLETE!</b></blockquote>\n\n" +642        "🖼 <b>QR:</b> " + qrStatusMsg + "\n" +643        "🆔 <b>Binance Pay ID:</b> <code>" + Bot.getProperty("binance_pay_id") + "</code>\n" +644        "💳 <b>USDT Address:</b> <code>" + Bot.getProperty("binance_usdt_address") + "</code>\n" +645        "💱 <b>USD Rate:</b> <code>₹" + finalRate + " = $1</code>\n\n" +646        "<i>Binance Pay ab live hai!</i>",647        { parse_mode: "HTML" }648      );649      return;650    }651  }652 653  // ==========================================654  // 🟡 MODULE 4c: USER — BINANCE PROOF SUBMISSION (screenshot only)655  // ==========================================656  if (binanceUtrStep === "awaiting_screenshot") {657    var ssPhotoArr = null;658    try {659      if (request) {660        if (request.message && request.message.photo && request.message.photo.length) {661          ssPhotoArr = request.message.photo;662        } else if (request.photo && request.photo.length) {663          ssPhotoArr = request.photo;664        } else if (request.update && request.update.message && request.update.message.photo && request.update.message.photo.length) {665          ssPhotoArr = request.update.message.photo;666        }667      }668    } catch (ssPhotoDetectErr) {}669 670    if (!ssPhotoArr) {671      Bot.sendMessage("⚠️ Kripya payment screenshot ek <b>image/photo</b> ke roop me bhejein.", { parse_mode: "HTML" });672      return;673    }674 675    var ssLargest = ssPhotoArr[ssPhotoArr.length - 1];676    var ssFileId = ssLargest.file_id;677 678    var subInr = User.getProperty("binance_pending_amount_inr");679    var subUsd = User.getProperty("binance_pending_amount_usd");680    var adminSupportId = Bot.getProperty("owner_id") || "7127818616";681 682    var fullNameSub = ((user.first_name || "") + " " + (user.last_name || "")).trim() || "No Name";683    var usernameSub = user.username ? "@" + user.username : "No Username";684 685    var adminCaption =686      "<blockquote><tg-emoji emoji-id='6312263493051489212'>🟡</tg-emoji> <b>NEW BINANCE PAY SUBMISSION</b></blockquote>\n" +687      "👤 <b>User:</b> <a href='tg://user?id=" + userId + "'>" + fullNameSub + "</a> (<code>" + userId + "</code>)\n" +688      "🌐 <b>Username:</b> " + usernameSub + "\n" +689      "💰 <b>Amount:</b> $<code>" + subUsd + "</code> <i>(₹" + subInr + ")</i>\n\n" +690      "<i>Verify the screenshot, then credit balance with the button below or:</i>\n<code>/addbal " + userId + "|" + subInr + "</code>";691 692    try {693      Api.sendPhoto({694        chat_id: adminSupportId,695        photo: ssFileId,696        caption: adminCaption,697        parse_mode: "HTML",698        reply_markup: JSON.stringify({699          inline_keyboard: [[700            { text: "✅ Approve & Credit ₹" + subInr, callback_data: "/addbal_binance_approve " + userId + " " + subInr, style: "success" }701          ]]702        })703      });704    } catch (notifyAdminErr) {}705 706    User.setProperty("binance_utr_step", null, "string");707    User.setProperty("binance_pending_amount_inr", null, "string");708    User.setProperty("binance_pending_amount_usd", null, "string");709 710    Bot.sendMessage(711      "<blockquote><tg-emoji emoji-id='6147936236125298267'>⏳</tg-emoji> <b>WAIT FOR ADMIN CHECK</b></blockquote>\n\n" +712      "<i>Aapka payment screenshot admin ko bhej diya gaya hai. Admin manually verify karke aapka balance add karega — thodi der wait karein!</i>",713      {714        parse_mode: "HTML",715        reply_markup: JSON.stringify({ inline_keyboard: [[{ text: "Back to Menu", callback_data: "/back", style: "danger" }]] })716      }717    );718    return;719  }720 721  // ==========================================722  // 💵 MODULE 5: ADMIN BALANCE TOOLS (Add Bal / Remove Bal / Check Bal723  // button-click continuation — fixes buttons that previously just724  // showed a "Wrong Format" error with no way to actually complete it)725  // ==========================================726  if (userId === adminId) {727    var addbalStep = User.getProperty("addbal_step");728    var addbalAllStep = User.getProperty("addbalall_step");729    var rembalStep = User.getProperty("rembal_step");730    var checkbalStep = User.getProperty("checkbal_step");731 732    if (addbalStep === "waiting_input" && msgText) {733      User.setProperty("addbal_step", null, "string");734 735      // ✅ FIXED: pehle sirf Bot.run(...) se /addbal ko dobara call kiya jaata tha —736      // agar us re-run me "message" text sahi se forward nahi hota tha (jo wildcard737      // "*" -> /start delegation ke through hone par silently fail ho sakta tha),738      // toh balance kabhi credit hi nahi hota tha aur admin ko koi error bhi nahi739      // dikhta tha. Ab balance yahin, isi jagah, seedha add hota hai — kisi doosre740      // command re-run par depend nahi karta. Bot.run wala call sirf backup ke741      // taur par neeche rakha hai.742      var addbalData = msgText.trim();743 744      if (addbalData.indexOf("|") === -1) {745        Bot.sendMessage("❌ *Invalid Format! Use:* `user_id|amount`", { parse_mode: "Markdown" });746        return;747      }748 749      var addbalParts = addbalData.split("|");750      var addbalTargetId = addbalParts[0].trim();751      var addbalAmount = parseFloat(addbalParts[1].trim());752 753      if (!addbalTargetId || isNaN(addbalAmount) || addbalAmount <= 0) {754        Bot.sendMessage("❌ *Invalid Format! Use:* `user_id|amount`", { parse_mode: "Markdown" });755        return;756      }757 758      try {759        // Primary wallet resource (same store the rest of the bot reads for purchases)760        try {761          Libs.ResourcesLib.anotherUserRes("balance", addbalTargetId).add(addbalAmount);762        } catch (resErr) {}763 764        // ✅ Bonus-balance property — this is the SAME property /menu reads and adds765        // on top of the resource balance. Writing it here too guarantees the credited766        // amount always shows up for the user even if the resource write above fails767        // silently for a user who never triggered it before.768        var prevBonus = Number(Bot.getProperty("balance" + addbalTargetId) || 0);769        Bot.setProperty("balance" + addbalTargetId, (prevBonus + addbalAmount).toFixed(2), "string");770 771        Bot.sendMessage("✅ Success! Added " + addbalAmount + " to user " + addbalTargetId, { parse_mode: "HTML" });772 773        try {774          Api.sendMessage({775            chat_id: addbalTargetId,776            text: "<blockquote>" +777              "<tg-emoji emoji-id='6192822213486321961'>🗣</tg-emoji> Admin Added: " + addbalAmount + "\n" +778              "<tg-emoji emoji-id='6266967801580231067'>💎</tg-emoji> Balance Credited!\n" +779              "<tg-emoji emoji-id='6267068789146260253'>💰</tg-emoji> Wallet Updated\n" +780              "<tg-emoji emoji-id='5866053971960929280'>🛒</tg-emoji> /start TO SHOP NOW" +781              "</blockquote>",782            parse_mode: "HTML"783          });784        } catch (notifyErr) {}785      } catch (addbalErr) {786        Bot.sendMessage("⚠️ *Error:* " + addbalErr.message, { parse_mode: "Markdown" });787      }788      return;789    }790    if (addbalAllStep === "waiting_input" && msgText) {791      User.setProperty("addbalall_step", null, "string");792      Bot.run({ command: "/addbal_all", options: { message: "/addbal_all " + msgText.trim() } });793      return;794    }795    if (rembalStep === "waiting_input" && msgText) {796      User.setProperty("rembal_step", null, "string");797      Bot.run({ command: "/rembal", options: { message: "/rembal " + msgText.trim() } });798      return;799    }800    if (checkbalStep === "waiting_input" && msgText) {801      User.setProperty("checkbal_step", null, "string");802      Bot.run({ command: "/checkbal", options: { params: msgText.trim() } });803      return;804    }805 806    var setDownloadLinkStep = User.getProperty("set_download_link_step");807    if (setDownloadLinkStep === "waiting_input" && msgText) {808      User.setProperty("set_download_link_step", null, "string");809      Bot.run({ command: "/set_update_link", options: { params: msgText.trim() } });810      return;811    }812 813    var setPaymentUpiStep = User.getProperty("set_payment_upi_step");814    if (setPaymentUpiStep === "waiting_input" && msgText) {815      User.setProperty("set_payment_upi_step", null, "string");816      Bot.run({ command: "/set_payment_upi", options: { params: msgText.trim() } });817      return;818    }819 820    // ✅ NEW: FamPay gateway config capture (mirrors Paytm UPI setup above)821    // ── FamGateway Setup — 2-step wizard ──822    var setPaymentFampayStep = User.getProperty("set_payment_fampay_step");823    if (setPaymentFampayStep === "step_upi" && msgText) {824      var famUpi = msgText.trim();825      if (famUpi.indexOf("@") === -1) {826        Bot.sendMessage("❌ Valid UPI ID bhejein (Example: <code>name@fam</code>)", { parse_mode: "HTML" });827        return;828      }829      User.setProperty("temp_fam_upi", famUpi, "string");830      User.setProperty("set_payment_fampay_step", "step_key", "string");831      Bot.sendMessage(832        "<blockquote>🟣 <b>FamGateway Setup — Step 2/2</b></blockquote>\n\n" +833        "✅ UPI ID saved: <code>" + famUpi + "</code>\n\n" +834        "🔑 <b>Ab apna FamGateway API Key bhejein:</b>\n" +835        "<i>Example: <code>FAM_xxxxxxxxxxxxxxxx</code></i>\n\n" +836        "<i>famgateway.in dashboard se API key milega</i>",837        { parse_mode: "HTML", reply_markup: JSON.stringify({ inline_keyboard: [[{ text: "❌ Cancel", callback_data: "/admin", style: "danger" }]] }) }838      );839      return;840    }841    if (setPaymentFampayStep === "step_key" && msgText) {842      var famKey = msgText.trim();843      var famUpiSaved = User.getProperty("temp_fam_upi") || "";844      User.setProperty("set_payment_fampay_step", null, "string");845      User.setProperty("temp_fam_upi", null, "string");846      Bot.run({ command: "/set_payment_fampay", options: { params: famUpiSaved + "|" + famKey } });847      return;848    }849 850    // 🟢 Zapupi key capture (2-step wizard: key, then customer mobile number)851    var setPaymentZapupiStep = User.getProperty("set_payment_zapupi_step");852    if (setPaymentZapupiStep === "waiting_input" && msgText) {853      User.setProperty("set_payment_zapupi_step", null, "string");854      try { if (request && request.message_id) Api.deleteMessage({ chat_id: chat.chatid, message_id: request.message_id }); } catch (delKeyErr) {}855      Bot.run({ command: "/set_payment_zapupi", options: { params: msgText.trim() } });856      return;857    }858    var setZapupiMobileStep = User.getProperty("set_zapupi_mobile_step");859    if (setZapupiMobileStep === "waiting_input" && msgText) {860      User.setProperty("set_zapupi_mobile_step", null, "string");861      Bot.run({ command: "/set_zapupi_mobile", options: { params: msgText.trim() } });862      return;863    }864 865    // ✏️ ADMIN — Edit Welcome Text (admin panel button). Reply capture.866    var editWelcomeStep = User.getProperty("edit_welcome_step");867    if (editWelcomeStep === "waiting_input" && msgText) {868 869    // Telegram entities -> safe HTML (bold/italic/underline/strike/code/spoiler/quote/link/premium emoji).870    // Overlap hone par tags band karke dobara khole jaate hain, isliye HTML hamesha valid rehta hai.871    function __wEsc(t) { return String(t).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); }872    function __wEntitiesToHtml(text, ents) {873      var tagFor = function (e) {874        switch (e.type) {875          case "bold": return ["<b>", "</b>"];876          case "italic": return ["<i>", "</i>"];877          case "underline": return ["<u>", "</u>"];878          case "strikethrough": return ["<s>", "</s>"];879          case "code": return ["<code>", "</code>"];880          case "pre": return ["<pre>", "</pre>"];881          case "spoiler": return ["<tg-spoiler>", "</tg-spoiler>"];882          case "blockquote": return ["<blockquote>", "</blockquote>"];883          case "expandable_blockquote": return ["<blockquote expandable>", "</blockquote>"];884          case "text_link": return e.url ? ['<a href="' + String(e.url).replace(/&/g, "&amp;").replace(/"/g, "&quot;") + '">', "</a>"] : null;885          case "custom_emoji": return e.custom_emoji_id ? ["<tg-emoji emoji-id=\"" + String(e.custom_emoji_id).replace(/[^0-9]/g, "") + "\">", "</tg-emoji>"] : null;886          default: return null;887        }888      };889      var list = [];890      for (var i = 0; i < (ents || []).length; i++) {891        var t = tagFor(ents[i]);892        if (t) list.push({ s: ents[i].offset, e: ents[i].offset + ents[i].length, o: t[0], c: t[1], n: i });893      }894      if (!list.length) return __wEsc(text);895      var cuts = {};896      cuts[0] = 1; cuts[text.length] = 1;897      list.forEach(function (x) { cuts[x.s] = 1; cuts[x.e] = 1; });898      var points = Object.keys(cuts).map(Number).filter(function (p) { return p >= 0 && p <= text.length; }).sort(function (a, b) { return a - b; });899      var out = "", prevActive = "";900      for (var pi = 0; pi < points.length - 1; pi++) {901        var a = points[pi], b = points[pi + 1];902        var active = list.filter(function (x) { return x.s <= a && x.e >= b; })903          .sort(function (x, y) { return (y.e - y.s) - (x.e - x.s) || x.n - y.n; });904        var sig = active.map(function (x) { return x.n; }).join(",");905        if (sig !== prevActive) {906          // close previous (reverse), open new907          var prevList = prevActive ? prevActive.split(",").map(function (n) { return list.filter(function (x) { return String(x.n) === n; })[0]; }) : [];908          for (var ci = prevList.length - 1; ci >= 0; ci--) out += prevList[ci].c;909          active.forEach(function (x) { out += x.o; });910          prevActive = sig;911        }912        out += __wEsc(text.substring(a, b));913      }914      if (prevActive) {915        var lastList = prevActive.split(",").map(function (n) { return list.filter(function (x) { return String(x.n) === n; })[0]; });916        for (var li = lastList.length - 1; li >= 0; li--) out += lastList[li].c;917      }918      return out;919    }920 921      var rawWelcome = (typeof message !== "undefined" && message) ? String(message) : msgText;922      if (rawWelcome.length > 850) {923        Bot.sendMessage("❌ Text bahut lamba hai (" + rawWelcome.length + " characters). 850 se kam rakhein.");924        return;925      }926      var wEnts = (request && (request.entities || (request.message && request.message.entities))) || [];927      var wHtml;928      try { wHtml = __wEntitiesToHtml(rawWelcome, wEnts); } catch (wErr) { wHtml = __wEsc(rawWelcome); }929      User.setProperty("edit_welcome_step", null, "string");930      Bot.setProperty("custom_welcome_html", wHtml, "string");931      Bot.sendMessage("✅ <b>Welcome text save ho gaya.</b> Neeche preview hai:", { parse_mode: "HTML" });932      Bot.run({ command: "/menu" });933      return;934    }935 936    var setHowLinkStep = User.getProperty("set_how_link_step");937    if (setHowLinkStep === "waiting_input" && msgText) {938      User.setProperty("set_how_link_step", null, "string");939      Bot.run({ command: "/set_how_link", options: { params: msgText.trim() } });940      return;941    }942 943    var setSupportLinkStep = User.getProperty("set_support_link_step");944    if (setSupportLinkStep === "waiting_input" && msgText) {945      User.setProperty("set_support_link_step", null, "string");946      Bot.run({ command: "/set_support_link", options: { params: msgText.trim() } });947      return;948    }949 950    var extkeyUrlStep = User.getProperty("extkey_url_step");951    if (extkeyUrlStep === "waiting_input" && msgText) {952      User.setProperty("extkey_url_step", null, "string");953      Bot.run({ command: "/extkey_save_url", options: { params: msgText.trim() } });954      return;955    }956    var extkeyApikeyStep = User.getProperty("extkey_apikey_step");957    if (extkeyApikeyStep === "waiting_input" && msgText) {958      User.setProperty("extkey_apikey_step", null, "string");959      Bot.run({ command: "/extkey_save_apikey", options: { params: msgText.trim() } });960      return;961    }962    var extkeyMasterStep = User.getProperty("extkey_master_step");963    if (extkeyMasterStep === "waiting_input" && msgText) {964      User.setProperty("extkey_master_step", null, "string");965      Bot.run({ command: "/extkey_save_master", options: { params: msgText.trim() } });966      return;967    }968  }969 970  // ==========================================971  // 🎟 MODULE 3: ADMIN COUPON GENERATOR (step-by-step wizard)972  // ==========================================973  if (userId === adminId && couponGenStep) {974 975    if (couponGenStep === "code") {976      if (!msgText) { Bot.sendMessage("⚠️ Kripya ek valid coupon code bhejein."); return; }977      var couponCodeUpper = msgText.trim().toUpperCase();978      if (Bot.getProperty("coupon_" + couponCodeUpper)) {979        Bot.sendMessage("❌ Ye coupon code pehle se exist karta hai! Doosra naam try karein.");980        return;981      }982      User.setProperty("coupon_gen_code", couponCodeUpper, "string");983      User.setProperty("coupon_gen_step", "maxclaims", "string");984      Bot.sendMessage("<tg-emoji emoji-id='6091571559233755994'>👥</tg-emoji> <b>Kitne users ye coupon use (claim) kar sakte hain?</b>\n<i>Sirf number bhejein, jaise: 50</i>", { parse_mode: "HTML" });985      return;986    }987 988    if (couponGenStep === "maxclaims") {989      var maxClaimsVal = parseInt(msgText.trim());990      if (isNaN(maxClaimsVal) || maxClaimsVal <= 0) { Bot.sendMessage("❌ Kripya ek valid number bhejein (jaise 50)."); return; }991      User.setProperty("coupon_gen_maxclaims", maxClaimsVal, "number");992      User.setProperty("coupon_gen_step", "type", "string");993      Bot.sendMessage(994        "<tg-emoji emoji-id='6093677128295914531'>🎟</tg-emoji> <b>Coupon ka type kya hoga?</b>\n\n" +995        "• Purchase par % chhut ke liye: <code>discount</code>\n" +996        "• Wallet me seedha balance dene ke liye: <code>balance</code>",997        { parse_mode: "HTML" }998      );999      return;1000    }1001 1002    if (couponGenStep === "type") {1003      var typeInput = (msgText || "").trim().toLowerCase();1004      if (typeInput === "discount") {1005        User.setProperty("coupon_gen_step", "discount", "string");1006        Bot.sendMessage("<tg-emoji emoji-id='6093591495237967001'>💸</tg-emoji> <b>Kitne % discount dena hai?</b>\n<i>Sirf number bhejein (1-100), jaise: 10</i>", { parse_mode: "HTML" });1007      } else if (typeInput === "balance") {1008        User.setProperty("coupon_gen_step", "balanceamt", "string");1009        Bot.sendMessage("<tg-emoji emoji-id='6312263493051489212'>💰</tg-emoji> <b>Har user ko kitna balance (₹) milega?</b>\n<i>Sirf number bhejein, jaise: 10</i>", { parse_mode: "HTML" });1010      } else {1011        Bot.sendMessage("❌ Sirf <code>discount</code> ya <code>balance</code> likhein.", { parse_mode: "HTML" });1012      }1013      return;1014    }1015 1016    if (couponGenStep === "balanceamt") {1017      var balAmt = parseFloat((msgText || "").trim());1018      if (isNaN(balAmt) || balAmt <= 0) { Bot.sendMessage("❌ Kripya valid amount bhejein (jaise 10)."); return; }1019      balAmt = Number(balAmt.toFixed(2));1020      var balCoupon = {1021        code: User.getProperty("coupon_gen_code"),1022        maxClaims: User.getProperty("coupon_gen_maxclaims"),1023        type: "balance",1024        balanceAmount: balAmt,1025        scope: "balance",1026        claimedBy: [],1027        isPaused: false,1028        createdAt: new Date().toLocaleDateString()1029      };1030      Bot.setProperty("coupon_" + balCoupon.code, balCoupon, "json");1031      var balCouponList = Bot.getProperty("coupon_list") || [];1032      if (balCouponList.indexOf(balCoupon.code) === -1) {1033        balCouponList.push(balCoupon.code);1034        Bot.setProperty("coupon_list", balCouponList, "json");1035      }1036      User.setProperty("coupon_gen_step", null, "string");1037      User.setProperty("coupon_gen_code", null, "string");1038      User.setProperty("coupon_gen_maxclaims", null, "number");1039      User.setProperty("coupon_gen_discount", null, "number");1040      Bot.sendMessage(1041        "<blockquote>🎟 <b>BALANCE COUPON CREATED!</b></blockquote>\n\n" +1042        "🏷 <b>Code:</b> <code>" + balCoupon.code + "</code>\n" +1043        "👥 <b>Max Claims:</b> " + balCoupon.maxClaims + "\n" +1044        "💰 <b>Balance:</b> ₹" + balAmt.toFixed(2) + " per user",1045        { parse_mode: "HTML" }1046      );1047      return;1048    }1049 1050    if (couponGenStep === "discount") {1051      var discountVal = parseFloat(msgText.trim());1052      if (isNaN(discountVal) || discountVal <= 0 || discountVal > 100) { Bot.sendMessage("❌ Discount 1 se 100 ke beech honi chahiye."); return; }1053      User.setProperty("coupon_gen_discount", discountVal, "number");1054      User.setProperty("coupon_gen_step", "scope", "string");1055      Bot.sendMessage(1056        "<tg-emoji emoji-id='6093677128295914531'>🎯</tg-emoji> <b>Scope batayein:</b>\n\n" +1057        "• Sabhi products/plans ke liye: <code>global</code> likh kar bhejein\n" +1058        "• Sirf ek specific product+plan ke liye: <code>Product Name | Duration</code>\n" +1059        "  <i>Example:</i> <code>Atomic Habits (Book) | 1d</code>",1060        { parse_mode: "HTML" }1061      );1062      return;1063    }1064 1065    if (couponGenStep === "scope") {1066      var scopeInput = msgText.trim();1067      var couponData = {1068        code: User.getProperty("coupon_gen_code"),1069        maxClaims: User.getProperty("coupon_gen_maxclaims"),1070        discountPercent: User.getProperty("coupon_gen_discount"),1071        claimedBy: [],1072        isPaused: false,1073        createdAt: new Date().toLocaleDateString()1074      };1075 1076      if (scopeInput.toLowerCase() === "global") {1077        couponData.scope = "global";1078      } else if (scopeInput.indexOf("|") > -1) {1079        var scopeParts = scopeInput.split("|");1080        couponData.scope = "specific";1081        couponData.productName = scopeParts[0].trim();1082        couponData.duration = scopeParts[1].trim();1083      } else {1084        Bot.sendMessage("❌ Galat format! 'global' likhein ya 'Product Name | Duration' format me bhejein.");1085        return;1086      }1087 1088      Bot.setProperty("coupon_" + couponData.code, couponData, "json");1089 1090      // ✅ NEW: master list me bhi add karo, taaki /coupons admin command sabko list kar sake1091      var couponList = Bot.getProperty("coupon_list") || [];1092      if (couponList.indexOf(couponData.code) === -1) {1093        couponList.push(couponData.code);1094        Bot.setProperty("coupon_list", couponList, "json");1095      }1096 1097      // Cleanup wizard state1098      User.setProperty("coupon_gen_step", null, "string");1099      User.setProperty("coupon_gen_code", null, "string");1100      User.setProperty("coupon_gen_maxclaims", null, "number");1101      User.setProperty("coupon_gen_discount", null, "number");1102 1103      Bot.sendMessage(1104        "<blockquote>🎟 <b>COUPON CREATED SUCCESSFULLY!</b></blockquote>\n\n" +1105        "🏷 <b>Code:</b> <code>" + couponData.code + "</code>\n" +1106        "👥 <b>Max Claims:</b> " + couponData.maxClaims + "\n" +1107        "💸 <b>Discount:</b> " + couponData.discountPercent + "%\n" +1108        "🎯 <b>Scope:</b> " + (couponData.scope === "global" ? "🌍 Global (All Plans)" : "📦 " + couponData.productName + " (" + couponData.duration + ")"),1109        { parse_mode: "HTML" }1110      );1111      return;1112    }1113  }1114 1115  // ==========================================1116  // 🎟 MODULE 4: USER — APPLY COUPON CODE TEXT ENTRY1117  // ==========================================1118  if (awaitingCouponFor) {1119    var enteredCode = msgText.trim().toUpperCase();1120    var couponRec = Bot.getProperty("coupon_" + enteredCode);1121 1122    User.setProperty("awaiting_coupon_for", null, "string");1123 1124    if (!couponRec) {1125      Bot.sendMessage("❌ <b>Invalid Coupon Code!</b>", { parse_mode: "HTML" });1126      return;1127    }1128    if (couponRec.isPaused) {1129      Bot.sendMessage("⏸ Ye coupon abhi paused hai, thodi der baad try karein.", { parse_mode: "HTML" });1130      return;1131    }1132    if (!Array.isArray(couponRec.claimedBy)) { couponRec.claimedBy = []; }1133    if (couponRec.claimedBy.indexOf(userId) > -1) {1134      Bot.sendMessage("⚠️ Aapne ye coupon already use kar liya hai!", { parse_mode: "HTML" });1135      return;1136    }1137    if (couponRec.claimedBy.length >= couponRec.maxClaims) {1138      Bot.sendMessage("❌ Is coupon ki claim limit khatam ho gayi hai!", { parse_mode: "HTML" });1139      return;1140    }1141 1142    // 💰 BALANCE COUPON: koi bhi jagah se redeem ho, wallet me turant credit + claim.1143    if (couponRec.type === "balance") {1144      var balCredit = Number(couponRec.balanceAmount || 0);1145      if (!(balCredit > 0)) {1146        Bot.sendMessage("❌ Ye coupon sahi se set nahi hai, admin se contact karein.", { parse_mode: "HTML" });1147        return;1148      }1149      couponRec.claimedBy.push(String(userId));1150      Bot.setProperty("coupon_" + enteredCode, couponRec, "json");1151      Libs.ResourcesLib.userRes("balance").add(balCredit);1152      var newBalAfterCoupon = 0;1153      try { newBalAfterCoupon = Number(Libs.ResourcesLib.userRes("balance").value()) || 0; } catch (nbErr) {}1154      newBalAfterCoupon += Number(Bot.getProperty("balance" + userId) || 0);1155      Bot.sendMessage(1156        "<blockquote>🎉 <b>COUPON REDEEMED!</b></blockquote>\n\n" +1157        "💰 <b>Balance Added:</b> ₹" + balCredit.toFixed(2) + "\n" +1158        "💵 <b>New Balance:</b> ₹" + newBalAfterCoupon.toFixed(2),1159        { parse_mode: "HTML" }1160      );1161      var cpnOwner = String(Bot.getProperty("owner_id") || "7127818616");1162      if (String(userId) !== cpnOwner) {1163        try {1164          Api.sendMessage({ chat_id: cpnOwner, parse_mode: "HTML",1165            text: "🎟 <b>Balance coupon redeemed</b>\n👤 <code>" + userId + "</code>\n🏷 <code>" + enteredCode + "</code> → ₹" + balCredit.toFixed(2) });1166        } catch (adErr) {}1167      }1168      Bot.run({ command: "/profile" });1169      return;1170    }1171 1172    // 👤 Profile se aaya coupon: sirf account me save karo; claim purchase par hota hai.1173    if (awaitingCouponFor === "PROFILE") {1174      User.setProperty("profile_coupon", enteredCode, "string");1175      var scopeNote = couponRec.scope === "specific"1176        ? ("\n📦 <i>Sirf " + (couponRec.productName || "selected product") + " par valid.</i>")1177        : "\n🌍 <i>Sab plans par valid.</i>";1178      Bot.sendMessage("🎉 <b>Coupon Saved!</b> -" + couponRec.discountPercent + "% discount next purchase par lagega." + scopeNote, { parse_mode: "HTML" });1179      Bot.run({ command: "/profile" });1180      return;1181    }1182 1183    var couponTargetParts = awaitingCouponFor.split(" ");1184    var cTargetProdIdx = couponTargetParts[0];1185    var cTargetPlanIdx = couponTargetParts[1];1186 1187    if (couponRec.scope === "specific") {1188      var cProductList = Bot.getProperty("stored_products") || [];1189      var cProduct = cProductList[Number(cTargetProdIdx)];1190      var cPlan = cProduct ? cProduct.plans[Number(cTargetPlanIdx)] : null;1191      var cDurationDisplay = cPlan ? (cPlan.durationDisplay || (cPlan.days + " Days")) : "";1192      var matchesProduct = cProduct && cProduct.name.trim().toLowerCase() === couponRec.productName.trim().toLowerCase();1193      var matchesDuration = cDurationDisplay.toLowerCase().indexOf(String(couponRec.duration).toLowerCase().replace(/[^a-z0-9]/g, "")) > -1 ||1194                             String(couponRec.duration).replace(/[^0-9]/g, "") === String(cPlan ? cPlan.days : "");1195      if (!matchesProduct) {1196        Bot.sendMessage("❌ Ye coupon is product ke liye valid nahi hai!", { parse_mode: "HTML" });1197        return;1198      }1199    }1200 1201    // ✅ Valid — apply and mark claimed1202    couponRec.claimedBy.push(userId);1203    Bot.setProperty("coupon_" + enteredCode, couponRec, "json");1204    User.setProperty("applied_coupon_" + cTargetProdIdx + "_" + cTargetPlanIdx, enteredCode, "string");1205 1206    Bot.sendMessage("🎉 <b>Coupon Applied!</b> -" + couponRec.discountPercent + "% discount added.", { parse_mode: "HTML" });1207 1208    Bot.run({1209      command: "buyitem",1210      options: { params: cTargetProdIdx + " " + cTargetPlanIdx }1211    });1212    return;1213  }1214 1215  // ==========================================1216  // 📢 MODULE 2: PREMIUM BROADCAST SYSTEM1217  // ==========================================1218  if (userId === adminId && isAwaitingBroadcast) {1219    User.setProperty("awaiting_broadcast_data", false, "boolean");1220    var userList = Bot.getProperty("all_users_list") || [];1221 1222    if (userList.length === 0) {1223      Bot.sendMessage("❌ Bot mein abhi tak koi bhi user registered nahi hai.");1224      return;1225    }1226 1227    var targetMessageId = null;1228    if (request) {1229      if (request.message_id) { targetMessageId = request.message_id; }1230      else if (request.message && request.message.message_id) { targetMessageId = request.message.message_id; }1231    }1232 1233    if (!targetMessageId) {1234      Bot.sendMessage("❌ Unable to fetch message ID for broadcast.");1235      return;1236    }1237 1238    Bot.sendMessage("⏳ Sending premium broadcast to " + userList.length + " users... Please wait.");1239 1240    // ✅ FIXED: pehle ek bhi blocked/invalid user Api.copyMessage() ko throw karwa deta1241    // tha, jo bahar wale catch() tak chala jaata tha — isse loop beech me hi ruk jaata1242    // tha (baaki users ko broadcast nahi jaata tha) aur admin ko scary "Error in handling"1243    // dikhta tha, jabki zyada tar users ko message mil chuka hota tha. Ab har send apne1244    // try/catch me hai, aur end me accurate success/fail count milega.1245    var sentCount = 0;1246    var failedCount = 0;1247    for (var i = 0; i < userList.length; i++) {1248      try {1249        Api.copyMessage({1250          chat_id: String(userList[i]),1251          from_chat_id: adminId,1252          message_id: Number(targetMessageId)1253        });1254        sentCount++;1255      } catch (perUserErr) {1256        failedCount++;1257      }1258    }1259    Bot.sendMessage(1260      "✅ <b>Broadcast Complete!</b>\n" +1261      "📤 <b>Sent:</b> " + sentCount + " users\n" +1262      (failedCount > 0 ? "⚠️ <b>Failed/Blocked:</b> " + failedCount + " users" : "🎉 <b>No failures!</b>"),1263      { parse_mode: "HTML" }1264    );1265  }1266 1267} catch (err) {1268  Bot.sendMessage("Error in handling: " + err.message);1269}
commands/_start.js · tarunpoonia905/OfcDevShopBot · TeleDevs