devbro468/Dev_x_store_botPublic · Bot Template
AIThis bot operates a digital storefront (DEV X STORE) selling subscription-based products — likely game hacks, accounts, or access keys — categorized by platform (Android Root, Non-Root, iPhone). It features a reseller program with discounted pricing, a dual-currency wallet (INR balance + Telegram Stars/XTR), and a full admin/co-admin panel for managing products, plans, per-plan pricing, stock (keys/accounts), coupons, and API endpoints. Purchases flow through a plan selection screen offering wallet payment, Stars invoices (sendInvoice with XTR currency), and coupon application. Successful Stars payments are handled via successful_payment webhook, crediting wallet or delivering keys directly. Admin tools include user listing with chunked messaging, stock viewing/deletion with inline keyboards, co-admin management, and API registry updates. The bot registers users on first interaction and
commands/_buyitem.js
javascript · 166 lines
1/**#command2name: /buyitem3answer: 4keyboard: 5parse_mode: markdown6aliases: 7allow_only_group: false8need_reply: false9is_web: 010#command**/11 12// =========================================================13// 🚀 PLAN CLICK HANDLER — Premium "Payment Method" confirmation screen14// (Pay from Wallet / Pay via UPI / Apply Coupon / Back to Shop)15// ✅ Supports Hour / Minute / Day duration units16// ✅ Supports coupon discounts (global or product-specific)17// =========================================================18 19try {20 var productList = Bot.getProperty("stored_products") || [];21 var callbackId = (request && request.id) ? request.id : ((request && request.callback_query && request.callback_query.id) || null);22 var chatId = chat.chatid;23 var userId = user.telegramid;24 25 var parts = params ? params.split(" ") : [];26 if (parts.length < 2) {27 var cbData = (request && request.callback_query) ? request.callback_query.data : "";28 parts = cbData.replace("buyitem ", "").split(" ");29 }30 31 var prodIdx = Number(parts[0]);32 var planIdx = Number(parts[1]);33 34 var product = productList[prodIdx];35 if (!product || !product.plans || !product.plans[planIdx]) {36 Bot.sendMessage("❌ Product or Plan configuration missing!");37 return;38 }39 40 var plan = product.plans[planIdx];41 var planUnit = plan.unit || "day";42 var cleanPlanDays = String(plan.days).replace(/[^0-9.]/g, "").trim();43 var unitLabelWord = (planUnit === "hour") ? (Number(cleanPlanDays) === 1 ? "Hour" : "Hours") :44 (planUnit === "minute") ? (Number(cleanPlanDays) === 1 ? "Minute" : "Minutes") :45 (Number(cleanPlanDays) === 1 ? "Day" : "Days");46 var durationDisplay = plan.durationDisplay || (cleanPlanDays + " " + unitLabelWord);47 48 var unifiedBal = (function () {49 var resBal = 0;50 try { resBal = Number(Libs.ResourcesLib.userRes("balance").value()) || 0; } catch (e) {}51 var bonusBal = Number(Bot.getProperty("balance" + userId) || 0);52 return resBal + bonusBal;53 })();54 55 var isReseller = Bot.getProperty("is_reseller_" + userId) === true;56 var cleanProdName = product.name.trim().toUpperCase();57 58 // ✅ Unit-aware price key (Day plans keep the old key format for backward-compat)59 var priceKeySuffix = (planUnit === "day") ? cleanPlanDays : (cleanPlanDays + "_" + planUnit);60 var normalKey = "price_normal_" + cleanProdName + "_" + priceKeySuffix;61 var resellerKey = "price_reseller_" + cleanProdName + "_" + priceKeySuffix;62 63 var adminNormalPrice = Bot.getProperty(normalKey);64 var adminResellerPrice = Bot.getProperty(resellerKey);65 66 var currentNormal = (adminNormalPrice !== undefined && adminNormalPrice !== null) ? adminNormalPrice : plan.normal_price;67 var currentReseller = (adminResellerPrice !== undefined && adminResellerPrice !== null) ? adminResellerPrice : plan.reseller_price;68 69 var originalPrice = isReseller ? Number(currentReseller) : Number(currentNormal);70 var price = originalPrice;71 72 // 💸 Auto-discount (admin-set, no coupon code needed) — plan-specific > product-wide > global73 var planSpecificDiscKey = "auto_discount_" + cleanProdName + "_" + cleanPlanDays + "_" + planUnit.toUpperCase();74 var productWideDiscKey = "auto_discount_" + cleanProdName + "_ALL";75 var autoDiscountPercent = Bot.getProperty(planSpecificDiscKey) || Bot.getProperty(productWideDiscKey) || Bot.getProperty("auto_discount_global") || 0;76 77 // 🎟 Coupon check (if user applied one for this exact prod/plan) — coupon overrides auto-discount78 var appliedCouponCode = User.getProperty("applied_coupon_" + prodIdx + "_" + planIdx);79 var couponDiscountPercent = 0;80 if (appliedCouponCode) {81 var couponRec = Bot.getProperty("coupon_" + appliedCouponCode);82 if (couponRec && couponRec.discountPercent) {83 couponDiscountPercent = couponRec.discountPercent;84 price = Number((originalPrice * (1 - couponDiscountPercent / 100)).toFixed(2));85 }86 } else if (autoDiscountPercent > 0) {87 couponDiscountPercent = autoDiscountPercent; // reuse the same display variable88 price = Number((originalPrice * (1 - autoDiscountPercent / 100)).toFixed(2));89 }90 91 // 💎 PREMIUM EMOJI SET (verified valid custom-emoji IDs from your reference bot)92 var e_diamond = "<tg-emoji emoji-id='6266967801580231067'>💎</tg-emoji>";93 var e_pack = "<tg-emoji emoji-id='6147767796097884213'>📦</tg-emoji>";94 var e_hour = "<tg-emoji emoji-id='6147936236125298267'>⏳</tg-emoji>";95 var e_tag = "<tg-emoji emoji-id='6080214566191505147'>🏷</tg-emoji>";96 var e_wallet = "<tg-emoji emoji-id='5348392971207194994'>💳</tg-emoji>";97 var e_check = "<tg-emoji emoji-id='6100657257605763582'>✔️</tg-emoji>";98 var e_offer = "<tg-emoji emoji-id='6102856637343600044'>🎉</tg-emoji>";99 var e_lock = "<tg-emoji emoji-id='6215386799133433653'>🔒</tg-emoji>";100 var e_coupon = "<tg-emoji emoji-id='6093677128295914531'>🎫</tg-emoji>";101 var e_back = "<tg-emoji emoji-id='5893163582194978381'>⬅️</tg-emoji>";102 103 var priceLine = couponDiscountPercent > 0104 ? e_tag + " <b>Price:</b> <s>₹" + originalPrice.toFixed(2) + "</s> ➜ <b>₹" + price.toFixed(2) + "</b> " + e_offer + " <b>-" + couponDiscountPercent + "%</b>"105 : e_tag + " <b>Price:</b> ₹<code>" + price.toFixed(2) + "</code>";106 107 // =====================================================108 // 💎 PREMIUM CHECKOUT SCREEN — always shown on plan click109 // =====================================================110 var confirmText =111 "<blockquote>" + e_diamond + " <b>CONFIRM YOUR ORDER</b> " + e_diamond + "</blockquote>\n" +112 "━━━━━━━━━━━━━━━━━━━━━\n\n" +113 e_pack + " <b>Product:</b> " + product.name + "\n" +114 e_hour + " <b>Duration:</b> " + durationDisplay + "\n" +115 priceLine + "\n" +116 e_wallet + " <b>Wallet Balance:</b> ₹<code>" + unifiedBal.toFixed(2) + "</code>\n\n" +117 "━━━━━━━━━━━━━━━━━━━━━\n" +118 e_lock + " <i>Secure checkout — choose a payment method below</i> " + e_check;119 120 var confirmButtons = [];121 122 if (unifiedBal >= price) {123 confirmButtons.push([124 { text: "Pay ₹" + price.toFixed(2) + " from Wallet", callback_data: "/confirm_buyitem " + prodIdx + " " + planIdx, style: "success", icon_custom_emoji_id: "6100657257605763582" }125 ]);126 } else {127 var needToPayPreview = (price - unifiedBal).toFixed(2);128 confirmButtons.push([129 { text: "Pay ₹" + needToPayPreview + " via UPI", callback_data: "/pay_upi " + prodIdx + " " + planIdx, style: "success", icon_custom_emoji_id: "5348392971207194994" }130 ]);131 }132 133 confirmButtons.push([134 { text: "Apply Coupon Code", callback_data: "/apply_coupon " + prodIdx + " " + planIdx, style: "primary", icon_custom_emoji_id: "6093677128295914531" }135 ]);136 confirmButtons.push([137 { text: "Back to Shop", callback_data: "/buy_hack", style: "danger", icon_custom_emoji_id: "5893163582194978381" }138 ]);139 140 if (request && request.message) {141 Api.editMessageText({142 chat_id: String(chatId),143 message_id: Number(request.message.message_id),144 text: confirmText,145 parse_mode: "HTML",146 reply_markup: JSON.stringify({ inline_keyboard: confirmButtons })147 });148 } else {149 Api.sendMessage({150 chat_id: String(chatId),151 text: confirmText,152 parse_mode: "HTML",153 reply_markup: JSON.stringify({ inline_keyboard: confirmButtons })154 });155 }156 157 if (callbackId) {158 Api.answerCallbackQuery({ callback_query_id: String(callbackId) });159 }160 161} catch (e) {162 var errChatId = (typeof chat !== "undefined" && chat && chat.chatid) ? chat.chatid : null;163 if (errChatId) {164 try { Api.sendMessage({ chat_id: errChatId, text: "❌ <b>Error:</b> <code>" + e.message + "</code>", parse_mode: "HTML" }); } catch (fatal) {}165 }166}