amanjha18v/AMAN_SHOPS_BOTPublic · Bot Template
AIAMAN SHOP STORE appears to be a Telegram automation bot. Commands include /*, /addbal, /addbal_all, /addbal_binance, /addbal_binance_approve, /addbal_binance_paid, /addbal_upi, /addcat_id. Observed in code: messaging, http, libs, keyboards, payments.
Utilityutility
132 commands0 envUpdated 6h agoCreated Sep 4, 2026
commands/_confirm_buyitem.js
javascript · 424 lines
1/**#command2name: /confirm_buyitem3answer: 4keyboard: 5parse_mode: markdown6aliases: 7allow_only_group: false8need_reply: false9is_web: 010#command**/11 12function resolveApiDuration(plan, cleanPlanDays, planUnit, productNameOverride) {13 // IMPORTANT: Keep the admin/API duration name exactly as entered.14 // The product-specific day ranges below are used only when the stored plan15 // contains a plain numeric Day duration; this lets 1-30 Day plans target16 // the exact website/API names requested by the admin without changing any17 // other product data or purchase logic.18 var raw = String((plan && (plan.api_duration || plan.name_on_website || plan.durationDisplay || plan.name || plan.title)) || "").replace(/\s+/g, " ").trim();19 20 // Already-custom API labels (including casing/suffixes) must pass through unchanged.21 if (raw && !/^[0-9]+(?:\.[0-9]+)?\s*(day|days)$/i.test(raw)) {22 return raw;23 }24 25 var dayMatch = raw.match(/^([0-9]+(?:\.[0-9]+)?)\s*(day|days)$/i);26 var n = dayMatch ? dayMatch[1] : String(cleanPlanDays || "1");27 var productName = String(productNameOverride || (plan && (plan.product_name || plan.productName || plan.product || plan.category)) || "").trim().toLowerCase();28 29 // If product name is not stored on the plan, the caller's raw API label is30 // still preserved above. Generic numeric Day plans remain "N Days".31 if (/pc\s*aim\s*silent/.test(productName)) return n + " Day Pc Aim Silent";32 if (/pc\s*modmenu\s*x86/.test(productName)) return n + " Day Pc Modmenu x86";33 if (/pc\s*bypass\s*\+\s*silent/.test(productName) || /bypass\s*\+\s*silent/.test(productName)) return n + " Days Pc Bypass + Silent";34 if (/nonroot/.test(productName) && !/root\s*\+\s*nonroot/.test(productName)) return n + " DaYS NONROOT";35 if (/pc\s*aimkill/.test(productName) || /aimkill/.test(productName)) return n + " DaYS PC AIMKILL";36 if (/root\s*\+\s*nonroot/.test(productName)) return n + " DaYs Root + Nonroot";37 if (/fluo?rite\s*ff/.test(productName)) return n + " DAYs FluoRite FF";38 if (/\broot\b/.test(productName)) return n + " DaYs ROOT";39 if (/all\s*colou?rs\s*mix/.test(productName)) return n + " DaYs All Colours Mix";40 if (/\bbasic\b/.test(productName)) return n + " DaYs Basic";41 if (/\bpro\b/.test(productName)) return n + " DaYs PRO";42 if (/\bsafe\b/.test(productName)) return n + " DaYs SAFE";43 if (/\bbrutal\b/.test(productName)) return n + " DaYs BRUTAL";44 if (/\bbrutal\b/.test(productName)) return n + " DaYs";45 46 // Hours/minutes are preserved exactly; no existing API duration is removed.47 var gh = raw.match(/^([0-9]+(?:\.[0-9]+)?)\s*(hour|hours)$/i);48 if (gh) return gh[1] + " Hours";49 var gm = raw.match(/^([0-9]+(?:\.[0-9]+)?)\s*(minute|minutes)$/i);50 if (gm) return gm[1] + (Number(gm[1]) === 1 ? " Minute" : " Minutes");51 52 return raw || n + " Days";53}54 55 56// =========================================================57// ✅ ACTUAL PURCHASE EXECUTION — runs after user taps "Confirm" on the58// premium confirmation screen, OR automatically right after a shortfall59// QR payment is verified (see _onCheck.js), so key delivery is fully automatic.60// =========================================================61 62try {63 var productList = Bot.getProperty("stored_products") || [];64 var chatId = chat.chatid;65 var userId = user.telegramid;66 67 var parts = params ? String(params).trim().split(" ") : [];68 var prodIdx = Number(parts[0]);69 var planIdx = Number(parts[1]);70 71 var product = productList[prodIdx];72 if (!product || !product.plans || !product.plans[planIdx]) {73 Api.sendMessage({ chat_id: chatId, text: "❌ Product or Plan configuration missing!" });74 return;75 }76 77 var plan = product.plans[planIdx];78 var planUnit = plan.unit || "day";79 var isReseller = Bot.getProperty("is_reseller_" + userId) === true;80 81 var cleanProdName = product.name.trim().toUpperCase();82 var cleanPlanDays = String(plan.days).replace(/[^0-9.]/g, "").trim();83 var unitLabelWord = (planUnit === "hour") ? (Number(cleanPlanDays) === 1 ? "Hour" : "Hours") :84 (planUnit === "minute") ? (Number(cleanPlanDays) === 1 ? "Minute" : "Minutes") :85 (Number(cleanPlanDays) === 1 ? "Day" : "Days");86 var durationDisplay = plan.durationDisplay || (cleanPlanDays + " " + unitLabelWord);87 88 var priceKeySuffix = (planUnit === "day") ? cleanPlanDays : (cleanPlanDays + "_" + planUnit);89 var normalKey = "price_normal_" + cleanProdName + "_" + priceKeySuffix;90 var resellerKey = "price_reseller_" + cleanProdName + "_" + priceKeySuffix;91 92 var adminNormalPrice = Bot.getProperty(normalKey);93 var adminResellerPrice = Bot.getProperty(resellerKey);94 95 var currentNormal = (adminNormalPrice !== undefined && adminNormalPrice !== null) ? adminNormalPrice : plan.normal_price;96 var currentReseller = (adminResellerPrice !== undefined && adminResellerPrice !== null) ? adminResellerPrice : plan.reseller_price;97 98 var originalPrice = isReseller ? Number(currentReseller) : Number(currentNormal);99 var price = originalPrice;100 101 var planSpecificDiscKey = "auto_discount_" + cleanProdName + "_" + cleanPlanDays + "_" + planUnit.toUpperCase();102 var productWideDiscKey = "auto_discount_" + cleanProdName + "_ALL";103 var autoDiscountPercent = Bot.getProperty(planSpecificDiscKey) || Bot.getProperty(productWideDiscKey) || Bot.getProperty("auto_discount_global") || 0;104 105 // 🎟 Apply coupon discount (if any was applied for this exact prod/plan) — coupon overrides auto-discount106 var appliedCouponCode = User.getProperty("applied_coupon_" + prodIdx + "_" + planIdx);107 var couponDiscountPercent = 0;108 if (appliedCouponCode) {109 var couponRec0 = Bot.getProperty("coupon_" + appliedCouponCode);110 if (couponRec0 && couponRec0.discountPercent) {111 couponDiscountPercent = couponRec0.discountPercent;112 price = Number((originalPrice * (1 - couponDiscountPercent / 100)).toFixed(2));113 }114 User.setProperty("applied_coupon_" + prodIdx + "_" + planIdx, null, "string");115 } else if (autoDiscountPercent > 0) {116 couponDiscountPercent = autoDiscountPercent;117 price = Number((originalPrice * (1 - autoDiscountPercent / 100)).toFixed(2));118 }119 120 // 🛡️ Safety re-check: balance abhi bhi sufficient hai ya nahi (race-condition guard)121 var unifiedBal = (function () {122 var resBal = 0;123 try { resBal = Number(Libs.ResourcesLib.userRes("balance").value()) || 0; } catch (e) {}124 var bonusBal = Number(Bot.getProperty("balance" + userId) || 0);125 return resBal + bonusBal;126 })();127 128 if (unifiedBal < price) {129 Api.sendMessage({130 chat_id: chatId,131 text: "⚠️ <b>Balance abhi kam hai.</b> Kripya phir se try karein.",132 parse_mode: "HTML"133 });134 return;135 }136 137 // =====================================================138 // 🔑 STEP 0 — MANUAL STOCK FIRST CHECK (✅ NEW)139 // Agar admin ne manually koi key already daal rakhi hai, to wahi seedha140 // deliver karo aur PAID EXTERNAL API ko bilkul call hi mat karo — taaki141 // "1 available key ke liye 2 keys spend" (1 manual + 1 wasted API buy)142 // wala bug kabhi na ho. API sirf tabhi call hoga jab manual stock khaali ho.143 // =====================================================144 var pDaysNumOnly = cleanPlanDays;145 var manualKeysStorageKey = "manual_keys_" + cleanProdName + "_" + pDaysNumOnly;146 var backupStockKey = "stock_" + product.name.trim() + "_" + pDaysNumOnly + "_Day";147 var isBackupUsed = false;148 149 var manualStock = Bot.getProperty(manualKeysStorageKey);150 if (!manualStock || (Array.isArray(manualStock) && manualStock.length === 0)) {151 manualStock = Bot.getProperty(backupStockKey);152 isBackupUsed = true;153 }154 if (typeof manualStock === "string" && manualStock.trim() !== "") {155 try {156 manualStock = JSON.parse(manualStock);157 } catch (err) {158 manualStock = manualStock.split("\n").map(function (k) { return k.trim(); }).filter(Boolean);159 }160 }161 162 if (Array.isArray(manualStock) && manualStock.length > 0) {163 var generatedKey = manualStock.shift();164 165 if (isBackupUsed) {166 Bot.setProperty(backupStockKey, manualStock, "json");167 var mainStock = Bot.getProperty(manualKeysStorageKey) || [];168 if (typeof mainStock === "string") { mainStock = mainStock.split("\n").map(function (k) { return k.trim(); }).filter(Boolean); }169 if (Array.isArray(mainStock)) {170 var idx1 = mainStock.indexOf(generatedKey);171 if (idx1 > -1) { mainStock.splice(idx1, 1); }172 Bot.setProperty(manualKeysStorageKey, mainStock, "json");173 }174 } else {175 Bot.setProperty(manualKeysStorageKey, manualStock, "json");176 var backupStock2 = Bot.getProperty(backupStockKey) || [];177 if (typeof backupStock2 === "string") { backupStock2 = backupStock2.split("\n").map(function (k) { return k.trim(); }).filter(Boolean); }178 if (Array.isArray(backupStock2)) {179 var idx2 = backupStock2.indexOf(generatedKey);180 if (idx2 > -1) { backupStock2.splice(idx2, 1); }181 Bot.setProperty(backupStockKey, backupStock2, "json");182 }183 }184 185 // 💰 Deduct balance + record purchase (same accounting as API path)186 Libs.ResourcesLib.userRes("balance").add(-price);187 var pastSpent2 = Bot.getProperty("total_spent_by_" + userId) || 0;188 Bot.setProperty("total_spent_by_" + userId, Number(pastSpent2) + price, "number");189 190 // 🎁 REFER & EARN — referrer bonus jab referred friend PEHLI baar purchase kare191 try {192 var referredByBuy2 = User.getProperty("referred_by");193 if (referredByBuy2 && !User.getProperty("ref_buy_bonus_given")) {194 var refBonusBuy2 = Number(Bot.getProperty("refer_earn_buy_amount"));195 if (isNaN(refBonusBuy2)) refBonusBuy2 = 2;196 if (refBonusBuy2 > 0) {197 Libs.ResourcesLib.anotherUserRes("balance", referredByBuy2).add(refBonusBuy2);198 var pastEarnBuy2 = Number(Bot.getProperty("refer_earnings_" + referredByBuy2) || 0);199 Bot.setProperty("refer_earnings_" + referredByBuy2, pastEarnBuy2 + refBonusBuy2, "number");200 try {201 Api.sendMessage({202 chat_id: referredByBuy2,203 text: "<blockquote>💸 <b>Referral Bonus!</b>\n\nAapke referred friend ne pehli purchase ki — aapko ₹" + refBonusBuy2.toFixed(2) + " mile hain!</blockquote>",204 parse_mode: "HTML"205 });206 } catch (e) {}207 }208 User.setProperty("ref_buy_bonus_given", true, "boolean");209 }210 } catch (e) {}211 212 var keysHistory2 = User.getProperty("my_purchased_keys") || [];213 keysHistory2.push({214 product: String(product.name).trim(),215 product_id: product.id || null,216 days: pDaysNumOnly,217 price: price,218 key: generatedKey,219 date: new Date().toLocaleDateString()220 });221 User.setProperty("my_purchased_keys", keysHistory2, "json");222 223 var remainingBal2 = Libs.ResourcesLib.userRes("balance").value().toFixed(2);224 225 // ✅ NEW: Key ke saath automatic "Join Updates" button attach hota hai (agar admin ne link set kiya ho)226 var updateLinkForKey = Bot.getProperty("update_channel_link");227 var keyDeliveryButtons = [[{ text: "📋 Copy Key", copy_text: { text: generatedKey } }]];228 if (updateLinkForKey) {229 keyDeliveryButtons.push([{ text: "📥 Join Updates", url: updateLinkForKey, style: "primary", icon_custom_emoji_id: "6091571559233755994" }]);230 }231 keyDeliveryButtons.push([{ text: "Back to Menu", callback_data: "/back", style: "primary", icon_custom_emoji_id: "5877536313623711363" }]);232 var keyDeliveryMarkup = JSON.stringify({ inline_keyboard: keyDeliveryButtons });233 234 var deliverText2 = "<blockquote>" +235 "<tg-emoji emoji-id='5350447674971660988'>✅</tg-emoji> <b>PURCHASE SUCCESSFUL!</b>\n\n" +236 "<tg-emoji emoji-id='6147767796097884213'>📦</tg-emoji> <b>Product:</b> <code>" + String(product.name).trim() + "</code>\n" +237 "<tg-emoji emoji-id='6284816251143331422'>🗝</tg-emoji> <b>Validity:</b> <code>" + durationDisplay + "</code>\n" +238 "<tg-emoji emoji-id='5352825278672412291'>👆</tg-emoji> <b>Your Key:</b> <code>" + generatedKey + "</code>\n\n" +239 "━━━━━ <tg-emoji emoji-id='6147934084346682063'>#⃣</tg-emoji> <b>BALANCE DETAILS</b> ━━━━━\n" +240 "<tg-emoji emoji-id='6195037488898121775'>✨</tg-emoji> <b>Total Invest:</b> ₹" + price.toFixed(2) + "\n" +241 "<tg-emoji emoji-id='5409048419211682843'>💵</tg-emoji> <b>New Wallet Balance:</b> ₹" + remainingBal2 + "\n\n" +242 "<i>Enjoy your purchase. <tg-emoji emoji-id='6057881002540274780'>🥳</tg-emoji></i>" +243 "</blockquote>";244 245 if (request && request.message) {246 try {247 Api.editMessageText({248 chat_id: String(chatId),249 message_id: Number(request.message.message_id),250 text: deliverText2,251 parse_mode: "HTML",252 reply_markup: keyDeliveryMarkup253 });254 } catch (e) {255 Api.sendMessage({ chat_id: chatId, text: deliverText2, parse_mode: "HTML", reply_markup: keyDeliveryMarkup });256 }257 } else {258 Api.sendMessage({ chat_id: chatId, text: deliverText2, parse_mode: "HTML", reply_markup: keyDeliveryMarkup });259 }260 261 var adminId3 = "5191323229";262 Api.sendMessage({263 chat_id: adminId3,264 text: "🔔 <b>NEW PURCHASE DELIVERED (MANUAL STOCK)</b> ✔️\n\n" +265 "👤 <b>Buyer:</b> " + (user.first_name || "User") + " (<code>" + userId + "</code>)\n" +266 "📦 <b>Product:</b> " + String(product.name).trim() + "\n" +267 "⏳ <b>Plan:</b> " + durationDisplay + "\n" +268 "💸 <b>Price Deducted:</b> ₹" + price.toFixed(2) + "\n" +269 "💳 <b>User Remaining Bal:</b> ₹" + remainingBal2 + "\n" +270 "🔑 <b>Key:</b> <code>" + generatedKey + "</code>\n\n" +271 "<i>✅ Manual stock se deliver hui — external paid API call SKIP ki gayi.</i>",272 parse_mode: "HTML"273 });274 275 var qId0 = request ? (request.id || (request.callback_query && request.callback_query.id)) : null;276 if (qId0) {277 try { Api.answerCallbackQuery({ callback_query_id: String(qId0), text: "✅ Key Delivered!", show_alert: false }); } catch (e) {}278 }279 280 return; // 🚫 STOP — external API bilkul call nahi hui281 }282 283 var webProductId = String(product.id || "PID_ID").trim();284 var prodNameLower = String(product.name).toLowerCase();285 286 var durationParam = resolveApiDuration(plan, cleanPlanDays, planUnit, product && product.name);287 288 // =====================================================289 // 🔌 MULTI-API SYSTEM290 // Admin can add/update/select multiple reseller APIs.291 // The active API is used for external purchases.292 // =====================================================293 var apiRegistry = Bot.getProperty("api_registry") || {};294 var activeApiId = Bot.getProperty("active_reseller_api");295 var selectedApi = activeApiId ? apiRegistry[activeApiId] : null;296 297 // Backward-compatible bootstrap from the existing API configuration.298 if (!selectedApi) {299 selectedApi = {300 id: "default",301 name: "Default Reseller API",302 url: "https://adminpanels.shop/api/reseller_v1.php",303 api_key: "2eb54d8d16cefcc6e3b6daf73a259d3c",304 master_key: "a7f3e8b2c9d1f4a6b8c2d5e9f1a3b6c8",305 mode: "reseller_v1",306 android_required: false,307 enabled: true308 };309 apiRegistry.default = selectedApi;310 Bot.setProperty("api_registry", apiRegistry, "json");311 Bot.setProperty("active_reseller_api", "default", "string");312 }313 314 if (selectedApi.enabled === false) {315 Api.sendMessage({chat_id: chatId, text: "❌ Selected API is disabled. Admin ko /apiset se another API select karna hoga."});316 return;317 }318 319 var webProductId = String(product.id || "PID_ID").trim();320 var prodNameLower = String(product.name).toLowerCase();321 322 var durationParam = resolveApiDuration(plan, cleanPlanDays, planUnit, product && product.name);323 324 // Product-level API override is supported: product.api_id.325 var productApiId = product.api_id ? String(product.api_id).trim() : "";326 if (productApiId && apiRegistry[productApiId] && apiRegistry[productApiId].enabled !== false) {327 selectedApi = apiRegistry[productApiId];328 activeApiId = productApiId;329 }330 331 var postFields = {332 api_key: selectedApi.api_key || "",333 action: "buy",334 product_id: webProductId,335 duration: durationParam336 };337 338 // Device-bound APIs can require android_id. The value may be saved by339 // your existing product/user flow as android_id_<USER_ID>.340 var savedAndroidId = User.getProperty("android_id") || User.getProperty("android_id_" + userId) ||341 Bot.getProperty("android_id_" + userId) || "";342 if (selectedApi.android_required) {343 if (!savedAndroidId) {344 Api.sendMessage({345 chat_id: chatId,346 text: "⚠️ <b>Android ID required</b>\nIs API/product ke liye Android ID zaroori hai. Pehle user ka Android ID save karein.",347 parse_mode: "HTML"348 });349 return;350 }351 postFields.android_id = String(savedAndroidId);352 } else if (savedAndroidId) {353 // Optional APIs may also accept it.354 postFields.android_id = String(savedAndroidId);355 }356 357 var apiHeaders = {358 "Content-Type": "application/x-www-form-urlencoded"359 };360 if (selectedApi.master_key) apiHeaders["x-master-key"] = selectedApi.master_key;361 362 var postFieldsString = Object.keys(postFields).map(function(k) {363 return encodeURIComponent(k) + "=" + encodeURIComponent(postFields[k]);364 }).join("&");365 366 User.setProperty("last_pending_price", Number(price), "number");367 User.setProperty("last_pending_prod_id", webProductId, "string");368 User.setProperty("last_pending_prod_name", String(product.name).trim(), "string");369 User.setProperty("last_pending_plan_days", cleanPlanDays, "string");370 User.setProperty("last_pending_plan_unit", planUnit, "string");371 User.setProperty("last_pending_api_id", String(selectedApi.id || activeApiId || ""), "string");372 373 var queryId = request ? (request.id || (request.callback_query && request.callback_query.id)) : null;374 375 var processingText = "<tg-emoji emoji-id='6147936236125298267'>⏳</tg-emoji> <b>Processing your order... please wait!</b>";376 if (request && request.message) {377 try {378 Api.editMessageText({379 chat_id: String(chatId),380 message_id: Number(request.message.message_id),381 text: processingText,382 parse_mode: "HTML"383 });384 Bot.setProperty("gen_msg_id_" + userId, request.message.message_id, "string");385 User.setProperty("gen_msg_id_" + userId, request.message.message_id, "string");386 } catch (e) {387 var pm1 = Api.sendMessage({ chat_id: chatId, text: processingText, parse_mode: "HTML" });388 try {389 var pmid1 = (pm1 && pm1.result && pm1.result.message_id) ? pm1.result.message_id : (pm1 && pm1.message_id ? pm1.message_id : null);390 if (pmid1) { Bot.setProperty("gen_msg_id_" + userId, pmid1, "string"); User.setProperty("gen_msg_id_" + userId, pmid1, "string"); }391 } catch (e2) {}392 }393 } else {394 var pm2 = Api.sendMessage({ chat_id: chatId, text: processingText, parse_mode: "HTML" });395 try {396 var pmid2 = (pm2 && pm2.result && pm2.result.message_id) ? pm2.result.message_id : (pm2 && pm2.message_id ? pm2.message_id : null);397 if (pmid2) { Bot.setProperty("gen_msg_id_" + userId, pmid2, "string"); User.setProperty("gen_msg_id_" + userId, pmid2, "string"); }398 } catch (e2) {}399 }400 401 HTTP.post({402 url: selectedApi.url,403 body: postFieldsString,404 headers: apiHeaders,405 success: "/onWebKeyReceive",406 error: "/onWebKeyError"407 });408 409 if (queryId) {410 try {411 Api.answerCallbackQuery({412 callback_query_id: String(queryId),413 text: "⏳ Processing your order... Please wait!",414 show_alert: false415 });416 } catch (e) {}417 }418 419} catch (e) {420 var errChatId = (typeof chat !== "undefined" && chat && chat.chatid) ? chat.chatid : null;421 if (errChatId) {422 try { Api.sendMessage({ chat_id: errChatId, text: "❌ <b>Error:</b> <code>" + e.message + "</code>", parse_mode: "HTML" }); } catch (fatal) {}423 }424}