indrajitghosh20006/Igstore_01botPublic Β· Bot Template
AIThe bot provides an admin interface for a digital store, allowing the owner or coβadmins to add balances, products, plans, and categories. It supports payment workflows via UPI and Binance Pay, automatically generating QR codes and handling manual approval of deposits. The code patches inline keyboards to use premium emoji icons and includes helper functions for user and bot properties. Overall, it serves as a commerce management tool for a Telegram-based storefront.
Commercestoreadminbalanceproductplancategory
170 commands0 envUpdated 8h agoCreated Oct 30, 2026
commands/_viewprod.js
javascript Β· 267 lines
1/**#command2name: /viewprod3answer: 4keyboard: 5parse_mode: markdown6aliases: 7allow_only_group: false8need_reply: false9is_web: 010#command**/11 12// PREMIUM BUTTON ICONS13(function(){14 try {15 if (!JSON.__premiumPatched) {16 var __origStringify = JSON.stringify;17 JSON.stringify = function(value, replacer, space) {18 try {19 if (value && value.inline_keyboard && Array.isArray(value.inline_keyboard)) {20 var premiumIds = [21 "6143444134125379822",22 "6091379307907652768",23 "6147534454819661264",24 "6147817325660741985",25 "6235683689292897318",26 "6102856637343600044"27 ];28 var rows = value.inline_keyboard.map(function(row, ri) {29 if (!Array.isArray(row)) return row;30 return row.map(function(btn, bi) {31 if (!btn || typeof btn !== "object") return btn;32 var copy = {};33 for (var k in btn) copy[k] = btn[k];34 if (!copy.icon_custom_emoji_id) copy.icon_custom_emoji_id = premiumIds[(ri + bi) % premiumIds.length];35 return copy;36 });37 });38 var cloned = {};39 for (var key in value) cloned[key] = value[key];40 cloned.inline_keyboard = rows;41 return __origStringify.call(JSON, cloned, replacer, space);42 }43 } catch (e) {}44 return __origStringify.call(JSON, value, replacer, space);45 };46 JSON.__premiumPatched = true;47 }48 } catch (e) {}49})();50 51 52 53// =========================================================54// π¦ Shows a product's plans (Step 2 of the buy flow)55// β
CRITICAL BUG FIX: pehle "<tg-emoji emoji-id='X'></tg-emoji>" ek EMPTY56// tag tha (koi fallback character nahi) β Telegram ka HTML parser aise57// malformed tg-emoji tag par POORA MESSAGE hi reject kar deta hai. Isi58// wajah se product par click karne par plan-list screen kabhi aati hi nahi59// thi β poora buy flow yahi pe tootta tha!60// β
Photo-message-edit bug bhi fix, aur missing else-branch (fresh send)61// bhi add kiya.62// =========================================================63 64try {65 66 // π PANEL MAINTENANCE GUARD67 // Re-check at every purchase/payment stage so an admin can switch a panel68 // OFF even if a user already opened the checkout screen.69 function isPanelUnderMaintenance(product) {70 if (!product) return false;71 var mKey = "panel_maintenance_" +72 String(product.id || product.name || "").toUpperCase().replace(/[^A-Z0-9_-]/g, "_");73 return Bot.getProperty(mKey) === true;74 }75 76 var productList = Bot.getProperty("stored_products") || [];77 var callbackId = request ? request.id : null;78 var chatId = chat.chatid;79 var messageId = request && request.message ? request.message.message_id : (request ? request.message_id : null);80 var isPhotoMsg = !!(request && request.message && request.message.photo);81 82 var userId = user.telegramid;83 var isReseller = Bot.getProperty("is_reseller_" + userId) === true;84 85 var productIndex = params ? params.trim() : "";86 if (productIndex === "") {87 var cbData = request && request.callback_query ? request.callback_query.data : "";88 productIndex = cbData.replace("/viewprod ", "").replace("viewprod ", "");89 }90 91 var selectedProduct = productList[Number(productIndex)];92 93 if (selectedProduct) {94 var viewMaintKey = "panel_maintenance_" +95 String(selectedProduct.id || selectedProduct.name || productIndex).toUpperCase().replace(/[^A-Z0-9_-]/g, "_");96 if (Bot.getProperty(viewMaintKey) === true) {97 var viewMaintText = "π <b>PANEL UNDER MAINTENANCE</b>\n\n" +98 "π¦ <b>Panel:</b> <code>" + String(selectedProduct.name || "Product") + "</code>\n\n" +99 "β³ Is panel par purchase temporarily disabled hai. Please try again later.";100 if (callbackId) {101 try { Api.answerCallbackQuery({ callback_query_id: String(callbackId), text: "π Panel is under maintenance", show_alert: true }); } catch (e) {}102 }103 if (messageId) {104 try {105 Api.editMessageText({106 chat_id: chatId,107 message_id: Number(messageId),108 text: viewMaintText,109 parse_mode: "HTML",110 reply_markup: JSON.stringify({ inline_keyboard: [[111 { text: "β¬
οΈ Back to Shop", callback_data: "/buy_hack", style: "danger", icon_custom_emoji_id: "5893163582194978381" }112 ]] })113 });114 } catch (e) {115 Api.sendMessage({ chat_id: chatId, text: viewMaintText, parse_mode: "HTML" });116 }117 } else {118 Api.sendMessage({ chat_id: chatId, text: viewMaintText, parse_mode: "HTML" });119 }120 return;121 }122 }123 124 if (!selectedProduct) {125 if (callbackId) {126 try { Api.answerCallbackQuery({ callback_query_id: String(callbackId), text: "β οΈ Product not found!", show_alert: true }); } catch (e) {}127 }128 return;129 }130 131 var planButtons = [];132 var planLines = [];133 var plans = selectedProduct.plans || [];134 135 if (plans.length === 0) {136 plans = [137 { days: "1", unit: "day", durationDisplay: "1 Day", normal_price: "79", reseller_price: "65" },138 { days: "7", unit: "day", durationDisplay: "7 Days", normal_price: "350", reseller_price: "300" }139 ];140 }141 142 // User-specific price is resolved here for the exact Telegram member.143 // Global normal/reseller prices remain untouched.144 for (var j = 0; j < plans.length; j++) {145 var plan = plans[j];146 var planUnit = plan.unit || "day";147 148 var cleanProdName = selectedProduct.name.trim().toUpperCase();149 var cleanPlanDays = String(plan.days).replace(/[^0-9.]/g, "").trim();150 151 var priceKeySuffix = (planUnit === "day") ? cleanPlanDays : (cleanPlanDays + "_" + planUnit);152 var normalKey = "price_normal_" + cleanProdName + "_" + priceKeySuffix;153 var resellerKey = "price_reseller_" + cleanProdName + "_" + priceKeySuffix;154 155 var adminNormalPrice = Bot.getProperty(normalKey);156 var adminResellerPrice = Bot.getProperty(resellerKey);157 158 var currentNormal = (adminNormalPrice !== undefined && adminNormalPrice !== null) ? adminNormalPrice : plan.normal_price;159 var currentReseller = (adminResellerPrice !== undefined && adminResellerPrice !== null) ? adminResellerPrice : plan.reseller_price;160 161 var baseDisplayPrice = isReseller ? Number(currentReseller) : Number(currentNormal);162 var memberPriceKey = "member_custom_price_" + userId + "_" + cleanProdName.replace(/[^A-Z0-9_-]/g, "_") + "_" + ((planUnit === "day") ? cleanPlanDays : (cleanPlanDays + "_hour"));163 var memberCustomPrice = Bot.getProperty(memberPriceKey);164 var hasMemberCustomPrice = memberCustomPrice !== undefined && memberCustomPrice !== null && isFinite(Number(memberCustomPrice));165 var displayPrice = hasMemberCustomPrice ? Number(memberCustomPrice) : baseDisplayPrice;166 167 var unitLabelWord = (planUnit === "hour") ? (Number(cleanPlanDays) === 1 ? "HOUR" : "HOURS") :168 (planUnit === "minute") ? (Number(cleanPlanDays) === 1 ? "MINUTE" : "MINUTES") :169 (Number(cleanPlanDays) === 1 ? "DAY" : "DAYS");170 var dayLabel = plan.durationDisplay || (cleanPlanDays + " " + unitLabelWord);171 172 // Live manual stock count is isolated by Product + Duration + Unit.173 var stockProductSlug = cleanProdName.replace(/[^A-Z0-9_-]/g, "_");174 var stockStorageKey = "manual_keys_" + stockProductSlug + "_" + cleanPlanDays + "_" + planUnit;175 var liveStock = Bot.getProperty(stockStorageKey) || [];176 if (!Array.isArray(liveStock)) liveStock = [];177 178 // Backward compatibility for old Day-only manual stock.179 if (liveStock.length === 0 && planUnit === "day") {180 var legacyStock = Bot.getProperty("manual_keys_" + cleanProdName + "_" + cleanPlanDays) || [];181 if (Array.isArray(legacyStock)) liveStock = legacyStock;182 }183 184 // Stock is tracked internally for delivery, but deliberately hidden from the customer UI.185 // Price β duration, using the requested custom emoji ID.186 var priceEmoji = "<tg-emoji emoji-id='6147565374289220368'>π²</tg-emoji>";187 var durationEmoji = "<tg-emoji emoji-id='6147565374289220368'>β±οΈ</tg-emoji>";188 planLines.push(189 priceEmoji + " <b>βΉ" + Number(displayPrice).toFixed(2) + "</b> β " +190 durationEmoji + " <b>" + dayLabel.toUpperCase() + "</b>" +191 (hasMemberCustomPrice ? " π€" : "")192 );193 194 // Buttons stay tied to the exact panel/plan/member-specific price.195 // Do not expose stock count on the customer-facing button.196 planButtons.push([197 {198 text: dayLabel.toUpperCase() + " β βΉ" + Number(displayPrice).toFixed(2),199 callback_data: "/buyitem " + productIndex + " " + j,200 style: "success",201 icon_custom_emoji_id: "6147565374289220368"202 }203 ]);204 }205 206 // β
NEW: Back button ab is product ki category wali list par le jaata hai207 // (Android Root / Android Non Root), generic /buy_hack (category-select) par nahi.208 var backCategory = selectedProduct.category ? String(selectedProduct.category).toLowerCase() : "both";209 var backCallback = (backCategory === "root") ? "/buy_hack_cat root" : (backCategory === "iphone") ? "/buy_hack_cat iphone" : "/buy_hack_cat nonroot";210 211 // Demo videos, when configured by admin, appear at the bottom of the plan list.212 var demoVideosForProduct = Array.isArray(selectedProduct.demo_videos) ? selectedProduct.demo_videos : [];213 if (demoVideosForProduct.length > 0) {214 planButtons.push([215 {216 text: "π₯ Demo Video (" + demoVideosForProduct.length + ")",217 callback_data: "/demo_view " + String(productIndex),218 style: "primary"219 }220 ]);221 }222 223 planButtons.push([224 {225 text: "Back to Shop",226 callback_data: backCallback,227 style: "danger",228 icon_custom_emoji_id: "5893163582194978381"229 }230 ]);231 232 // β
FIX: empty tg-emoji tag hata diya β ab sirf plain product emoji text hai233 var planText =234 "<blockquote>π <b>" + selectedProduct.name.toUpperCase() + "</b> π</blockquote>\n\n" +235 "<blockquote>π <b>Your Account Tier: " + (isReseller ? "RESELLER" : "USER") + "</b></blockquote>\n\n" +236 "π <b>Choose your access plan:</b>\n\n" +237 planLines.join("\n") + "\n\n" +238 "<blockquote>π <i>Tap any plan below to continue</i></blockquote>";239 240 241 var replyMarkupStr = JSON.stringify({ inline_keyboard: planButtons });242 243 if (messageId) {244 if (isPhotoMsg) {245 try { Api.deleteMessage({ chat_id: chatId, message_id: messageId }); } catch (e) {}246 Api.sendMessage({ chat_id: chatId, text: planText, parse_mode: "HTML", reply_markup: replyMarkupStr });247 } else {248 Api.editMessageText({249 chat_id: chatId,250 message_id: Number(messageId),251 text: planText,252 parse_mode: "HTML",253 reply_markup: replyMarkupStr254 });255 }256 } else {257 // β
FIX: pehle is case me kuch bhejta hi nahi tha258 Api.sendMessage({ chat_id: chatId, text: planText, parse_mode: "HTML", reply_markup: replyMarkupStr });259 }260 261 if (callbackId) {262 try { Api.answerCallbackQuery({ callback_query_id: String(callbackId) }); } catch (e) {}263 }264 265} catch (err) {266 Bot.sendMessage("β οΈ View Product Error: " + err.message, { parse_mode: "HTML" });267}