tarunpoonia905/OfcDevShopBotPublic · Bot Template
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
commands/_wz.js
javascript · 1328 lines
1/**#command2name: /wz3answer: 4keyboard: 5parse_mode: markdown6aliases: 7allow_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 17// =========================================================================18// 🧭 ADMIN GUIDED WIZARD — "ek ek karke puchna" (no typed formats)19//20// Every admin button opens a flow: /wz go <flow>21// • choices are shown as BUTTONS (category / panel / plan / user type ...)22// • values are asked ONE AT A TIME (panel name -> days -> PID -> price ...)23// • a summary + Confirm button is shown before anything is saved24//25// Text answers arrive through the wildcard command (_.js), which forwards them26// here with options.wz_text = true while a wizard is active.27// Wizard state lives in the User property "wz_state" (auto-expires).28// Everything is saved in the SAME properties the old typed commands used.29// =========================================================================30 31try {32 var ownerId = String(Bot.getProperty("owner_id") || "7127818616");33 var me = String(chat.chatid);34 var isCo = !!Bot.getProperty("co_admin_" + me);35 var isOwner = (me === ownerId);36 if (!isOwner && !isCo) { Bot.sendMessage("❌ Restricted command!"); return; }37 38 var opt = (typeof options !== "undefined" && options) ? options : {};39 var isText = !!opt.wz_text;40 var rawText = "";41 if (isText) {42 rawText = String(opt.text || ((typeof message !== "undefined" && message) ? message : "")).trim();43 }44 var cmd = (!isText && typeof params !== "undefined" && params) ? String(params).trim() : "";45 var cmdParts = cmd.split(/\s+/);46 var verb = (cmdParts[0] || "").toLowerCase();47 var arg = cmdParts.slice(1).join(" ").trim();48 49 // ---------------------------------------------------------------- helpers50 var qid = (!isText && request) ? (request.id || (request.callback_query && request.callback_query.id)) : null;51 var mid = null;52 if (!isText && request) {53 mid = (request.message && request.message.message_id) ||54 (request.callback_query && request.callback_query.message && request.callback_query.message.message_id) || null;55 }56 if (qid) { try { Api.answerCallbackQuery({ callback_query_id: String(qid) }); } catch (e) {} }57 58 function esc(s) { return String(s === undefined || s === null ? "" : s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">"); }59 function short(s, n) { s = String(s || ""); return s.length > n ? s.slice(0, n - 1) + "…" : s; }60 61 function show(text, rows) {62 var kb = JSON.stringify({ inline_keyboard: rows || [] });63 if (mid && !isText) {64 try {65 Api.editMessageText({ chat_id: me, message_id: Number(mid), text: text, parse_mode: "HTML", reply_markup: kb });66 return;67 } catch (e) {}68 }69 Api.sendMessage({ chat_id: me, text: text, parse_mode: "HTML", reply_markup: kb });70 }71 72 var NAV_CANCEL = { text: "❌ Cancel", callback_data: "/wz cancel", style: "danger" };73 var NAV_BACK = { text: "⬅️ Back", callback_data: "/wz back", style: "danger" };74 var BACK_ADMIN = [{ text: "🔙 Back to Admin", callback_data: "/admin", style: "danger" }];75 76 function prods() {77 var p = Bot.getProperty("stored_products");78 if (typeof p === "string") { try { p = JSON.parse(p); } catch (e) { p = []; } }79 return Array.isArray(p) ? p : [];80 }81 // ---- Multi website (api_registry) helpers82 function sitesReg() {83 var r = Bot.getProperty("api_registry");84 if (typeof r === "string") { try { r = JSON.parse(r); } catch (e) { r = {}; } }85 return (r && typeof r === "object") ? r : {};86 }87 function siteIds() { return Object.keys(sitesReg()); }88 function siteName(id) { var x = sitesReg()[id]; return x ? String(x.name || id) : String(id); }89 function hostOf(u) { return String(u || "").replace(/^https?:\/\//i, "").split("/")[0]; }90 function maskKey(k) {91 k = String(k || "");92 if (!k) return "Not set";93 if (k.length <= 8) return k.slice(0, 2) + "****";94 return k.slice(0, 4) + "••••" + k.slice(-4);95 }96 function idCats() {97 var c = Bot.getProperty("ff_categories");98 return (c && typeof c === "object") ? c : {};99 }100 function planLabel(pl) {101 var base = pl.durationDisplay || pl.name_on_website || (String(pl.days) + " " + (pl.unit || "day"));102 return String(base);103 }104 function planValueUnit(pl) {105 return { value: String(pl.days === undefined ? "" : pl.days).replace(/[^0-9.]/g, ""), unit: pl.unit || "day" };106 }107 108 // duration label -> {value, unit} (same rules as the old /addplan)109 function parseDuration(durationText) {110 var lower = durationText.toLowerCase();111 var durMatch = lower.match(/^([0-9]+(?:\.[0-9]+)?)\s*(d|day|days|h|hr|hrs|hour|hours|m|min|mins|minute|minutes)(?:\s+(.+))?$/);112 var numericOnly = durationText.match(/^([0-9]+(?:\.[0-9]+)?)/);113 var value = durMatch ? durMatch[1] : (numericOnly ? numericOnly[1] : "0");114 var unitRaw = durMatch ? durMatch[2] : "d";115 var unit = "day";116 if (/^h/.test(unitRaw)) unit = "hour";117 else if (/^m/.test(unitRaw)) unit = "minute";118 return { value: String(value), unit: unit };119 }120 121 // ------------------------------------------------------------- validators122 function vName(s) {123 s = s.replace(/\s+/g, " ").trim();124 if (!s) return { err: "Naam khaali nahi ho sakta." };125 if (s.length > 60) return { err: "Naam 60 characters se chhota rakhein." };126 if (s.indexOf("|") !== -1) return { err: "Naam mein | ka use na karein." };127 return { val: s };128 }129 function vEmoji(s) {130 s = s.replace(/\s+/g, "");131 if (!/^\d{5,30}$/.test(s)) return { err: "Emoji ID sirf numbers ka hota hai (jaise 5226656353744862682). Ya Skip dabayein." };132 return { val: s };133 }134 function vDur(s) {135 s = s.replace(/\s+/g, " ").trim();136 if (!s) return { err: "Duration khaali nahi ho sakta." };137 if (s.length > 40 || s.indexOf("|") !== -1) return { err: "Duration chhota rakhein (max 40 characters, | nahi)." };138 // 7 / 7d / 7 day -> "7 Days" ; 1h -> "1 Hour" ; 30m -> "30 Minutes"139 // (the buy flow maps "N Days" to the correct API name per product; custom labels stay as typed)140 var m = s.toLowerCase().match(/^(\d+(?:\.\d+)?)\s*(d|day|days|h|hr|hrs|hour|hours|m|min|mins|minute|minutes)?$/);141 if (m) {142 var n = m[1], u = m[2] || "d", one = Number(n) === 1;143 if (Number(n) <= 0) return { err: "Duration 0 se zyada hona chahiye." };144 if (/^d/.test(u)) return { val: n + (one ? " Day" : " Days") };145 if (/^h/.test(u)) return { val: n + (one ? " Hour" : " Hours") };146 return { val: n + (one ? " Minute" : " Minutes") };147 }148 return { val: s };149 }150 function vPid(s) {151 s = s.trim();152 if (!/^[A-Za-z0-9_\-]{1,40}$/.test(s)) return { err: "PID mein sirf letters/numbers/_/- hone chahiye." };153 return { val: s };154 }155 function vPrice(s) {156 var n = parseFloat(String(s).replace(/[₹,\s]/g, ""));157 if (isNaN(n) || n <= 0 || n > 10000000) return { err: "Valid price bhejein (number, 0 se zyada)." };158 return { val: n };159 }160 function vPrice0(s) {161 var n = parseFloat(String(s).replace(/[₹,\s]/g, ""));162 if (isNaN(n) || n < 0 || n > 10000000) return { err: "Valid price bhejein (number)." };163 return { val: n };164 }165 function vUser(s) {166 s = s.replace(/\s+/g, "");167 if (!/^\d{5,15}$/.test(s)) return { err: "User ID sirf numbers (5-15 digits) ka hona chahiye." };168 return { val: s };169 }170 function vPct(s) {171 var n = parseFloat(String(s).replace(/%/g, ""));172 if (isNaN(n) || n <= 0 || n > 100) return { err: "Percent 1 se 100 ke beech bhejein." };173 return { val: n };174 }175 function vUrl(s) {176 s = s.trim().replace(/\/+$/, "");177 if (!/^https?:\/\/.+/i.test(s)) return { err: "Valid URL bhejein, http:// ya https:// se shuru honi chahiye." };178 return { val: s };179 }180 function vApiKey(s) {181 s = s.trim();182 if (s.length < 6) return { err: "Valid API key bhejein." };183 return { val: s };184 }185 function vPrompt(s) {186 s = s.trim();187 if (s.length < 10 || s.length > 2000) return { err: "Prompt 10-2000 characters ke beech hona chahiye." };188 return { val: s };189 }190 function vLines(s) {191 var arr = s.split("\n").map(function (x) { return x.trim(); }).filter(Boolean);192 if (!arr.length) return { err: "Kam se kam ek line bhejein." };193 return { val: arr };194 }195 function vAccounts(s) {196 var arr = s.split("\n").map(function (x) { return x.trim(); }).filter(function (x) { return x && x.indexOf("|") !== -1; });197 if (!arr.length) return { err: "Har line is format mein ho: email|password" };198 return { val: arr };199 }200 function cleanUser(v) {201 return String(v || "").trim().replace(/^https?:\/\/(www\.)?t\.me\//i, "").replace(/^t\.me\//i, "").replace(/^@/, "").split(/[?\/\s]/)[0];202 }203 function vBotUser(s) {204 var u = cleanUser(s);205 if (!/^[A-Za-z][A-Za-z0-9_]{1,28}bot$/i.test(u)) return { err: "Bot username 5-32 characters ka ho, letters/numbers/_ aur 'bot' par khatam (jaise MyShopBot)." };206 return { val: u };207 }208 function vAdminUser(s) {209 var u = cleanUser(s);210 if (!/^[A-Za-z][A-Za-z0-9_]{4,31}$/.test(u)) return { err: "Username 5-32 characters ka ho, sirf letters/numbers/_ (jaise YourName)." };211 return { val: u };212 }213 214 // ------------------------------------------------------------ step makers215 var CAT_LABELS = { root: "ANDROID ROOT", nonroot: "ANDROID NON ROOT", iphone: "iPHONE", both: "BOTH" };216 var DEFAULT_EMOJI = "5226656353744862682";217 var DEFAULT_ID_EMOJI = "5323261730283863478";218 219 function T(k, q, v, x) { return { k: k, t: "text", q: q, v: v, x: x || {} }; }220 var S_CAT = { k: "cat", t: "cat", q: "📂 <b>Category chuniye:</b>" };221 var S_PROD = { k: "pi", t: "prod", q: "📦 <b>Panel / Product chuniye:</b>" };222 var S_PLAN = { k: "li", t: "plan", q: "⏱ <b>Plan chuniye:</b>" };223 var S_IDCAT = { k: "slug", t: "idcat", q: "📁 <b>ID Category chuniye:</b>" };224 var S_NAME = T("pn", "📦 <b>Panel ka naam bhejein</b>\n<i>Jaise: MST PANEL, DRIP CLIENT</i>", vName);225 var S_EMOJI = T("emoji", "💎 <b>Premium Emoji ID bhejein</b> (optional)\n<i>Nahi hai to Skip dabayein.</i>", vEmoji, { skip: { l: "⏭ Skip (default emoji)", v: "" } });226 var S_DUR = T("dur", "⏳ <b>Kitne din / kitna time?</b>\n<i>Button dabayein ya likhein: <code>7d</code>, <code>1h</code>, <code>30m</code> ya exact API naam. Sirf number likhoge to Days maana jayega.</i>\n\n<b>Examples:</b> <code>3 Hours</code>, <code>1 Day</code>, <code>7 Days</code>.\n<i>Aapke shop ki displayed validity hamesha ⏳ hi rahegi — ye sirf API ke liye hai.</i>\n\nAgar API wahi duration naam use karta hai, to wahi exact value bhejein. Website se copy karke laate ho to usko bhi last mein isi tarah lagana padta hai.", vDur,227 { quick: [["1 Day", "1d"], ["3 Days", "3d"], ["7 Days", "7d"], ["15 Days", "15d"], ["30 Days", "30d"], ["1 Hour", "1h"]] });228 var S_PID = T("pid", "🆔 <b>Is plan ka PID bhejein</b>\n<i>API wale product ki ID. Agar sirf manual keys se chalana hai to niche wala button dabayein.</i>", vPid, { skip: { l: "🔑 Manual keys (no PID)", v: "0" } });229 var S_PRICE = T("price", "💰 <b>Price kitna hoga?</b> (₹, number)", vPrice);230 var S_RPRICE = T("rprice", "👑 <b>Reseller price kitna hoga?</b> (₹, number)", vPrice0, { skipSame: true });231 var S_PRODCAT = { k: "pi", t: "prodcat", q: "📦 <b>Panel chuniye</b> (is category ke andar jo panels hain):" };232 var S_UNIT = { k: "unit", t: "unit", q: function (st) {233 var pr = prods()[st.d.pi]; var lines = [];234 var pls = pr && pr.plans ? pr.plans : [];235 for (var i = 0; i < pls.length; i++) lines.push("• " + esc(planLabel(pls[i])) + " — ₹" + pls[i].normal_price);236 return "⏱ <b>Kitne Hours ya Days ka key add karna hai?</b>\n" +237 (lines.length ? "\n<b>Abhi ye add hain:</b>\n" + lines.join("\n") + "\n" : "") + "\n<i>Pehle Hours ya Days chuniye, phir number likhna hai.</i>";238 } };239 var S_NUM = T("num", "🔢 <b>Kitne?</b>\n<i>Sirf number likhein. Jaise 12 ya 3</i>", function (s) {240 var m = String(s).trim().toLowerCase().match(/^(\d+(?:\.\d+)?)\s*(h|hr|hrs|hour|hours|d|day|days)?$/);241 var n = m ? parseFloat(m[1]) : NaN;242 if (isNaN(n) || n <= 0 || n > 9999) return { err: "Valid number bhejein (0 se zyada), jaise 12." };243 return { val: String(n) };244 });245 var S_PRICE_PUB = T("price", "💰 <b>Price kitna?</b>\n<i>Ye public/normal users ko dikhega (₹)</i>", vPrice);246 var S_RPRICE_Q = T("rprice", "👑 <b>Reseller price kitna?</b>\n<i>Ye resellers ko dikhega (₹)</i>", vPrice0);247 var S_PID_REQ = T("pid", "🆔 <b>PID bhejein</b>\n<i>Website wali product ID, jisse key apne aap generate hoti hai.</i>", vPid);248 var S_USER = T("uid", "👤 <b>User ID bhejein</b>\n<i>Sirf number, jaise <code>123456789</code></i>", vUser);249 var S_AMT = T("amt", "💵 <b>Amount kitna?</b> (₹, number)", vPrice);250 251 // --------------------------------------------------------------- savers252 function saveProductAndPlan(d) {253 var list = prods();254 var pName = d.pn;255 var idx = -1;256 for (var i = 0; i < list.length; i++) {257 if (list[i] && list[i].name && list[i].name.trim().toLowerCase() === pName.toLowerCase()) { idx = i; break; }258 }259 var isNewProduct = idx === -1;260 if (isNewProduct) {261 list.push({ name: pName, emoji: d.emoji || DEFAULT_EMOJI, category: d.cat || "both", plans: [] });262 idx = list.length - 1;263 } else if (d.cat) {264 // Add Product on an existing panel = update emoji/category, keep plans.265 list[idx].category = d.cat;266 if (d.emoji) list[idx].emoji = d.emoji;267 delete list[idx].id;268 }269 if (!Array.isArray(list[idx].plans)) list[idx].plans = [];270 271 var durationText = d.dur;272 var pd = parseDuration(durationText);273 var pDays = pd.value, pUnit = pd.unit;274 var cleanProdName = pName.toUpperCase();275 var suffix = (pUnit === "day") ? pDays : (pDays + "_" + pUnit);276 Bot.setProperty("price_normal_" + cleanProdName + "_" + suffix, d.price, "number");277 Bot.setProperty("price_reseller_" + cleanProdName + "_" + suffix, d.rprice, "number");278 279 var plan = {280 days: pDays, unit: pUnit, durationDisplay: durationText,281 normal_price: d.price, reseller_price: d.rprice,282 name_on_website: durationText, api_duration: durationText,283 pid: d.pid, product_id: d.pid, variant_id: d.pid284 };285 var updated = false;286 for (var p = 0; p < list[idx].plans.length; p++) {287 var pl = list[idx].plans[p];288 if (String(pl.days) === pDays && (pl.unit || "day") === pUnit) { list[idx].plans[p] = plan; updated = true; break; }289 }290 if (!updated) list[idx].plans.push(plan);291 Bot.setProperty("stored_products", list, "json");292 return { idx: idx, isNewProduct: isNewProduct, planUpdated: updated };293 }294 295 function setPlanPrices(pi, li, which, price) {296 var list = prods();297 if (!list[pi] || !list[pi].plans || !list[pi].plans[li]) return false;298 var pl = list[pi].plans[li];299 var vu = planValueUnit(pl);300 var suffix = (vu.unit === "day") ? vu.value : (vu.value + "_" + vu.unit);301 var key = (which === "n" ? "price_normal_" : "price_reseller_") + String(list[pi].name).trim().toUpperCase() + "_" + suffix;302 Bot.setProperty(key, price, "number");303 if (which === "n") pl.normal_price = price; else pl.reseller_price = price;304 Bot.setProperty("stored_products", list, "json");305 return true;306 }307 308 // -------------------------------------------------------------- flow table309 function durLabel(d) {310 if (d.dur) return d.dur;311 if (d.num && d.unit) {312 var one = Number(d.num) === 1;313 return d.num + (d.unit === "h" ? (one ? " Hour" : " Hours") : (one ? " Day" : " Days"));314 }315 return "";316 }317 318 function recap(d) {319 var L = [];320 if (d.cat) L.push("📂 Category: <b>" + esc(CAT_LABELS[d.cat] || d.cat) + "</b>");321 if (d.pn) L.push("📦 Panel: <b>" + esc(d.pn) + "</b>");322 if (d.pl) L.push("⏱ Plan: <b>" + esc(d.pl) + "</b>");323 if (d.catName) L.push("📁 ID Category: <b>" + esc(d.catName) + "</b>");324 if (d.emoji) L.push("💎 Emoji: <code>" + esc(d.emoji) + "</code>");325 if (durLabel(d)) L.push("⏳ Duration: <b>" + esc(durLabel(d)) + "</b>");326 if (d.swn) L.push("🌐 Website: <b>" + esc(d.swn) + "</b>");327 if (d.pid) L.push("🆔 PID: <code>" + esc(d.pid) + "</code>");328 if (d.price !== undefined) L.push("💰 Price: <b>₹" + d.price + "</b>");329 if (d.rprice !== undefined) L.push("👑 Reseller: <b>₹" + d.rprice + "</b>");330 if (d.uid) L.push("👤 User ID: <code>" + esc(d.uid) + "</code>");331 if (d.amt !== undefined) L.push("💵 Amount: <b>₹" + d.amt + "</b>");332 return L.join("\n");333 }334 335 function planSummary(d) {336 return recap(d);337 }338 339 var F = {};340 341 F.add_product = {342 title: "➕ ADD PRODUCT",343 steps: [S_CAT, S_NAME, S_EMOJI, S_DUR, S_PID, S_PRICE, S_RPRICE],344 sum: planSummary,345 run: function (d) {346 var r = saveProductAndPlan(d);347 return {348 text: "<blockquote>✅ <b>" + (r.isNewProduct ? "Product Add Ho Gaya!" : "Product Update Ho Gaya!") + "</b></blockquote>\n\n" + recap(d) +349 "\n\n<i>" + (r.planUpdated ? "Ye plan pehle se tha, update kar diya." : "Plan bhi add ho gaya. Ab ye store mein dikhega.") + "</i>",350 rows: [351 [{ text: "➕ Isi Panel mein aur Plan", callback_data: "/wz more " + r.idx, style: "success" }],352 [{ text: "🔑 Keys Add Karein", callback_data: "/wz go add_key", style: "primary" }],353 [{ text: "➕ Naya Product", callback_data: "/wz go add_product", style: "success" }]354 ]355 };356 }357 };358 359 F.add_plan = {360 title: "📋 ADD PLAN",361 steps: [S_PROD, S_DUR, S_PID, S_PRICE, S_RPRICE],362 sum: planSummary,363 run: function (d) {364 var r = saveProductAndPlan(d);365 return {366 text: "<blockquote>✅ <b>" + (r.planUpdated ? "Plan Update Ho Gaya!" : "Plan Add Ho Gaya!") + "</b></blockquote>\n\n" + recap(d),367 rows: [368 [{ text: "➕ Isi Panel mein aur Plan", callback_data: "/wz more " + r.idx, style: "success" }],369 [{ text: "🔑 Keys Add Karein", callback_data: "/wz go add_key", style: "primary" }]370 ]371 };372 }373 };374 375 F.quick_add = {376 title: "⚡ QUICK ADD API KEY",377 steps: [S_CAT, S_PRODCAT, S_UNIT, S_NUM, S_PRICE_PUB, S_RPRICE_Q, S_PID_REQ],378 sum: function (d) {379 var txt = recap(d);380 var pr = prods()[d.pi], pd = parseDuration(durLabel(d));381 var pls = pr && pr.plans ? pr.plans : [];382 for (var i = 0; i < pls.length; i++) {383 if (String(pls[i].days) === pd.value && (pls[i].unit || "day") === pd.unit) {384 txt += "\n\n⚠️ <i>Ye time pehle se hai (₹" + pls[i].normal_price + "). Confirm karne par update ho jayega.</i>";385 break;386 }387 }388 return txt;389 },390 run: function (d) {391 d.dur = durLabel(d);392 var r = saveProductAndPlan({ pn: d.pn, dur: d.dur, pid: d.pid, price: d.price, rprice: d.rprice });393 return {394 text: "<blockquote>✅ <b>" + (r.planUpdated ? "Update Ho Gaya!" : "Add Ho Gaya!") + "</b></blockquote>\n\n" + recap(d),395 rows: [396 [{ text: "⚡ Isi Panel mein aur Add", callback_data: "/wz qmore " + r.idx, style: "success" }],397 [{ text: "⚡ Dusra Panel / Category", callback_data: "/wz go quick_add", style: "primary" }]398 ]399 };400 }401 };402 403 F.rem_plan = {404 title: "🗑 REMOVE PLAN",405 own: true,406 steps: [S_PROD, S_PLAN],407 sum: function (d) { return recap(d) + "\n\n⚠️ <i>Ye plan delete ho jayega. Agar ye aakhri plan hai to poora panel bhi hat jayega.</i>"; },408 run: function (d) {409 var list = prods();410 var p = list[d.pi];411 if (!p || !p.plans || !p.plans[d.li]) return { text: "❌ Plan nahi mila (shayad pehle hi hat chuka hai)." };412 p.plans.splice(d.li, 1);413 var msg;414 if (p.plans.length === 0) { list.splice(d.pi, 1); msg = "🗑 <b>" + esc(d.pn) + "</b> ka aakhri plan tha, isliye poora panel bhi remove ho gaya."; }415 else { msg = "✅ <b>" + esc(d.pn) + "</b> se <b>" + esc(d.pl) + "</b> plan remove ho gaya."; }416 Bot.setProperty("stored_products", list, "json");417 return { text: msg };418 }419 };420 421 F.add_key = {422 title: "🔑 ADD KEYS",423 steps: [S_PROD, S_PLAN, T("keys", "🔑 <b>Keys bhejein</b>\n<i>Ek line mein ek key. Kai keys ek saath paste kar sakte hain.</i>", vLines)],424 noconfirm: true,425 run: function (d) {426 var list = prods();427 var product = list[d.pi];428 var plan = product && product.plans ? product.plans[d.li] : null;429 if (!product || !plan) return { text: "❌ Plan nahi mila." };430 var vu = planValueUnit(plan);431 var value = vu.value, unit = vu.unit;432 var cleanName = product.name.trim().toUpperCase();433 var stockKey = "manual_keys_" + cleanName + "_" + value + "_" + unit;434 var stock = Bot.getProperty(stockKey) || [];435 if (typeof stock === "string") {436 try { stock = JSON.parse(stock); } catch (e) { stock = stock.split("\n").map(function (x) { return x.trim(); }).filter(Boolean); }437 }438 if (!Array.isArray(stock)) stock = [];439 // v63: unlimited keys — O(n) dedupe (object map), koi count limit nahi440 var seenK = {};441 for (var sq = 0; sq < stock.length; sq++) seenK[String(stock[sq])] = true;442 var added = 0;443 for (var q = 0; q < d.keys.length; q++) {444 var kk = String(d.keys[q]);445 if (!seenK[kk]) { seenK[kk] = true; stock.push(d.keys[q]); added++; }446 }447 Bot.setProperty(stockKey, stock, "json");448 if (unit === "day") {449 Bot.setProperty("manual_keys_" + cleanName + "_" + value, stock, "json");450 Bot.setProperty("stock_" + product.name.trim() + "_" + value + "_Day", stock, "json");451 Bot.setProperty("stock_" + d.pi + "_" + d.li, stock, "json");452 }453 return {454 text: "<blockquote><b>✅ KEYS ADD HO GAYI</b></blockquote>\n\n📦 Panel: <b>" + esc(product.name) + "</b>\n⏱ Plan: <b>" + esc(d.pl) + "</b>\n🔑 Nayi keys: <b>" + added +455 "</b>" + (added < d.keys.length ? " <i>(" + (d.keys.length - added) + " duplicate skip)</i>" : "") + "\n📦 Total stock: <b>" + stock.length + "</b>",456 rows: [[{ text: "🔑 Aur Keys Add Karein", callback_data: "/wz go add_key", style: "success" }]]457 };458 }459 };460 461 F.rem_key = {462 title: "🗑 REMOVE KEY",463 own: true,464 steps: [S_PROD, S_PLAN],465 noconfirm: true,466 run: function (d) {467 var list = prods();468 var product = list[d.pi];469 var plan = product && product.plans ? product.plans[d.li] : null;470 if (!product || !plan) return { text: "❌ Plan nahi mila." };471 var vu = planValueUnit(plan);472 if (vu.unit !== "day") return { text: "ℹ️ Key remove abhi sirf <b>Day</b> plans ke liye available hai." };473 var cleanPlanDays = vu.value + "_Day";474 var keyStock = Bot.getProperty("stock_" + product.name.trim() + "_" + cleanPlanDays) || [];475 if (!Array.isArray(keyStock) || keyStock.length === 0) return { text: "❌ <b>" + esc(product.name) + " (" + esc(cleanPlanDays) + ")</b> ka stock khaali hai!" };476 var rows = [];477 for (var i = 0; i < keyStock.length && i < 90; i++) {478 var fk = String(keyStock[i]);479 var sk = fk.length > 15 ? fk.substring(0, 12) + "..." : fk;480 rows.push([{ text: "🗑️ Key " + (i + 1) + " [" + sk + "]", callback_data: "/deletekey_now " + i + "|" + product.name.trim() + "|" + cleanPlanDays }]);481 }482 return {483 text: "<blockquote><b>🗑️ REMOVE KEY CHUNIYE</b>\n\n• Panel: <code>" + esc(product.name) + "</code>\n• Plan: <code>" + esc(cleanPlanDays) + "</code>\n• Total Keys: <code>" + keyStock.length + "</code></blockquote>",484 rows: rows485 };486 }487 };488 489 // ----- FF ID categories490 F.id_add_cat = {491 title: "📁 ADD ID CATEGORY",492 own: true,493 steps: [T("catName", "📁 <b>Category ka naam bhejein</b>\n<i>Jaise: Facebook Id</i>", vName),494 T("emoji", "💎 <b>Emoji ID bhejein</b> (optional)", vEmoji, { skip: { l: "⏭ Skip (default emoji)", v: "" } })],495 sum: function (d) { return recap(d); },496 run: function (d) {497 var slug = d.catName.toLowerCase().replace(/[^a-z0-9]/g, "");498 if (!slug) return { text: "❌ Naam mein kam se kam ek letter/number hona chahiye." };499 var cats = idCats();500 if (cats[slug]) return { text: "⚠️ <b>" + esc(cats[slug].name) + "</b> category pehle se hai. Naya naam chuniye." };501 var em = d.emoji || DEFAULT_ID_EMOJI;502 cats[slug] = { name: d.catName, emoji_id: em, normal_price: 0, reseller_price: 0 };503 Bot.setProperty("ff_categories", cats, "json");504 Bot.setProperty("ff_stock_" + slug, [], "json");505 return {506 text: "✅ <b>ID Category Add Ho Gayi!</b>\n\n• Icon: <tg-emoji emoji-id='" + esc(em) + "'>✨</tg-emoji>\n• Naam: <code>" + esc(d.catName) + "</code>\n\n<i>Ab price set karein aur stock add karein.</i>",507 rows: [[{ text: "💰 Set Normal Price", callback_data: "/wz go id_price_n", style: "primary" }, { text: "➕ Add Stock", callback_data: "/wz go id_add_stock", style: "success" }]]508 };509 }510 };511 512 F.id_rem_cat = {513 title: "🗑 REMOVE ID CATEGORY",514 own: true,515 steps: [S_IDCAT],516 sum: function (d) { return recap(d) + "\n\n⚠️ <i>Category aur uska poora stock delete ho jayega.</i>"; },517 run: function (d) {518 var cats = idCats();519 if (!cats[d.slug]) return { text: "❌ Category nahi mili." };520 var nm = cats[d.slug].name;521 delete cats[d.slug];522 Bot.setProperty("ff_categories", cats, "json");523 Bot.setProperty("ff_stock_" + d.slug, null);524 return { text: "🗑 <b>Category delete ho gayi:</b> <code>" + esc(nm) + "</code>" };525 }526 };527 528 F.id_add_stock = {529 title: "📥 ADD ID STOCK",530 own: true,531 steps: [S_IDCAT, T("accts", "📥 <b>Accounts bhejein</b>\n<i>Har line: <code>email|password</code>. Kai accounts ek saath paste kar sakte hain.</i>", vAccounts)],532 noconfirm: true,533 run: function (d) {534 var cats = idCats();535 if (!cats[d.slug]) return { text: "❌ Category nahi mili." };536 var cur = Bot.getProperty("ff_stock_" + d.slug) || [];537 if (!Array.isArray(cur)) cur = [];538 for (var i = 0; i < d.accts.length; i++) cur.push(d.accts[i]);539 Bot.setProperty("ff_stock_" + d.slug, cur, "json");540 return {541 text: "⚡ <b>Stock Add Ho Gaya!</b>\n\n• <code>" + d.accts.length + " accounts</code> ➔ <b>" + esc(cats[d.slug].name) + "</b>\n• Total stock: <b>" + cur.length + "</b>",542 rows: [[{ text: "📥 Aur Stock Add Karein", callback_data: "/wz go id_add_stock", style: "success" }]]543 };544 }545 };546 547 function idPriceFlow(which) {548 return {549 title: which === "n" ? "💰 ID NORMAL PRICE" : "👑 ID RESELLER PRICE",550 own: true,551 steps: [S_IDCAT, T("price", which === "n" ? "💰 <b>Normal price kitna?</b> (₹)" : "👑 <b>Reseller price kitna?</b> (₹)", vPrice)],552 sum: function (d) { return recap(d); },553 run: function (d) {554 var cats = idCats();555 if (!cats[d.slug]) return { text: "❌ Category nahi mili." };556 if (which === "n") cats[d.slug].normal_price = d.price; else cats[d.slug].reseller_price = d.price;557 Bot.setProperty("ff_categories", cats, "json");558 return { text: "✅ <b>" + (which === "n" ? "Normal" : "Reseller") + " Price Update!</b>\n\n• Category: <code>" + esc(cats[d.slug].name) + "</code>\n• Naya price: <code>₹" + d.price + "</code>" };559 }560 };561 }562 F.id_price_n = idPriceFlow("n");563 F.id_price_r = idPriceFlow("r");564 565 // ----- all-product prices566 function allPriceFlow(which) {567 return {568 title: which === "n" ? "💰 NORMAL PRICE (PANEL PLAN)" : "👑 RESELLER PRICE (PANEL PLAN)",569 own: true,570 steps: [S_PROD, S_PLAN, T("price", which === "n" ? "💰 <b>Naya normal price kitna?</b> (₹)" : "👑 <b>Naya reseller price kitna?</b> (₹)", vPrice)],571 sum: function (d) { return recap(d); },572 run: function (d) {573 if (!setPlanPrices(d.pi, d.li, which, d.price)) return { text: "❌ Plan nahi mila." };574 return { text: "✅ <b>" + (which === "n" ? "Normal" : "Reseller") + " Price Update Ho Gaya!</b>\n\n" + recap(d) };575 }576 };577 }578 F.all_price_n = allPriceFlow("n");579 F.all_price_r = allPriceFlow("r");580 581 // ----- balances582 F.bal_add = {583 title: "➕ ADD BALANCE",584 steps: [S_USER, S_AMT],585 sum: function (d) { return recap(d); },586 run: function (d) {587 var credited = false;588 try { Libs.ResourcesLib.anotherUserRes("balance", d.uid).add(d.amt); credited = true; } catch (e1) {}589 if (!credited) {590 // Fallback store (same one /menu adds on top). Only used if the wallet resource failed,591 // so the amount is never credited twice.592 var prev = Number(Bot.getProperty("balance" + d.uid) || 0);593 Bot.setProperty("balance" + d.uid, (prev + d.amt).toFixed(2), "string");594 }595 try {596 Api.sendMessage({597 chat_id: d.uid, parse_mode: "HTML",598 text: "<blockquote><tg-emoji emoji-id='6192822213486321961'>🗣</tg-emoji> Admin Added: " + d.amt + "\n" +599 "<tg-emoji emoji-id='6266967801580231067'>💎</tg-emoji> Balance Credited!\n" +600 "<tg-emoji emoji-id='6267068789146260253'>💰</tg-emoji> Wallet Updated\n" +601 "<tg-emoji emoji-id='5866053971960929280'>🛒</tg-emoji> /start TO SHOP NOW</blockquote>"602 });603 } catch (e2) {}604 return { text: "✅ <b>Balance Add Ho Gaya!</b>\n\n👤 User: <code>" + esc(d.uid) + "</code>\n💵 Added: <b>₹" + d.amt + "</b>",605 rows: [[{ text: "➕ Aur Balance Add", callback_data: "/wz go bal_add", style: "success" }]] };606 }607 };608 609 F.bal_rem = {610 title: "➖ REMOVE BALANCE",611 steps: [S_USER, S_AMT],612 sum: function (d) { return recap(d); },613 run: function (d) {614 var wallet = Libs.ResourcesLib.anotherUserRes("balance", d.uid);615 var cur = Number(wallet.value()) || 0;616 var legacy = Number(Bot.getProperty("balance" + d.uid) || 0);617 var total = cur + legacy;618 if (d.amt > total) {619 return { text: "❌ <b>Insufficient Balance</b>\n\nMember balance: <code>₹" + total.toFixed(2) + "</code>\nRemove requested: <code>₹" + d.amt.toFixed(2) + "</code>" };620 }621 var fromRes = Math.min(cur, d.amt);622 if (fromRes > 0) wallet.remove(fromRes);623 var rem = d.amt - fromRes;624 if (rem > 0) Bot.setProperty("balance" + d.uid, Math.max(0, legacy - rem), "float");625 var after = (total - d.amt).toFixed(2);626 try {627 Api.sendMessage({ chat_id: d.uid, parse_mode: "HTML",628 text: "<blockquote><b>💳 BALANCE UPDATED</b>\n\n• Removed by Admin: <code>₹" + d.amt.toFixed(2) + "</code>\n• Remaining Balance: <code>₹" + after + "</code>\n\nUse /balance to check your wallet.</blockquote>" });629 } catch (e) {}630 return { text: "✅ <b>Balance Remove Ho Gaya</b>\n\nMember: <code>" + esc(d.uid) + "</code>\nRemoved: <code>₹" + d.amt.toFixed(2) + "</code>\nRemaining: <code>₹" + after + "</code>" };631 }632 };633 634 // ----- reseller / role635 F.reseller_add = {636 title: "👑 ADD RESELLER",637 steps: [S_USER],638 sum: function (d) { return recap(d) + "\n\n<i>User turant Reseller ban jayega (payment nahi lagegi).</i>"; },639 run: function (d) {640 if (Bot.getProperty("is_reseller_" + d.uid) === true) return { text: "🔰 Ye user (<code>" + esc(d.uid) + "</code>) <b>pehle se Reseller hai!</b>" };641 Bot.setProperty("is_reseller_" + d.uid, true, "boolean");642 try {643 Api.sendMessage({ chat_id: d.uid, parse_mode: "HTML",644 text: "<blockquote><b><tg-emoji emoji-id='6064138396228392033'>✨</tg-emoji> CONGRATULATIONS <tg-emoji emoji-id='6064138396228392033'>✨</tg-emoji></b>\n\n<tg-emoji emoji-id='5346024644635804737'>🔰</tg-emoji> You Are Now A Reseller.\nCheck Your Discounted Store /start To Check Now<tg-emoji emoji-id='6298298582982199311'>💰</tg-emoji></blockquote>" });645 } catch (e) {}646 return { text: "✅ User <code>" + esc(d.uid) + "</code> ab <b>Reseller</b> hai." };647 }648 };649 650 F.reseller_rem = {651 title: "☠ REMOVE RESELLER",652 steps: [S_USER],653 own: true,654 sum: function (d) { return recap(d); },655 run: function (d) {656 Bot.setProperty("is_reseller_" + d.uid, false, "boolean");657 try {658 Api.sendMessage({ chat_id: d.uid, parse_mode: "HTML",659 text: "<blockquote><b>⚠️ ROLE REMOVED</b>\n\nAapka <b>Reseller Role</b> admin dwara remove kar diya gaya hai. Ab aapko normal prices show hongi.</blockquote>" });660 } catch (e) {}661 return { text: "✅ User <code>" + esc(d.uid) + "</code> ka reseller role hata diya." };662 }663 };664 665 F.role = {666 title: "🪪 VIEW ROLE",667 steps: [S_USER],668 noconfirm: true,669 run: function (d) {670 var role = "Normal User";671 if (String(d.uid) === ownerId) role = "Owner / Admin 👑";672 else if (Bot.getProperty("co_admin_" + d.uid)) role = "Co-Admin 🛡";673 else if (Bot.getProperty("is_reseller_" + d.uid)) role = "Reseller 🔰";674 var nm = "N/A", un = "N/A";675 if (String(d.uid) === String(user.telegramid)) { nm = user.first_name || "N/A"; un = user.username ? "@" + user.username : "N/A"; }676 return { text: "<blockquote><b>📞 USER ROLE</b>\n\n• Name: " + esc(nm) + "\n• Username: " + esc(un) + "\n• User ID: <code>" + esc(d.uid) + "</code>\n• Role: " + role + "</blockquote>",677 rows: [[{ text: "🔎 Aur Check Karein", callback_data: "/wz go role", style: "primary" }]] };678 }679 };680 681 // ----- fees682 F.fee_setprice = {683 title: "⚙️ RESELLER UPGRADE FEE",684 steps: [T("price", "💰 <b>Reseller upgrade fee kitni?</b> (₹, poora number)\n<i>Current: " + esc(Bot.getProperty("reseller_upgrade_price") || Bot.getProperty("reseller_price") || "Not set") + "</i>", function (s) {685 var n = parseInt(s, 10);686 if (isNaN(n) || n <= 0) return { err: "Valid number bhejein (0 se zyada)." };687 return { val: n };688 })],689 own: true,690 sum: function (d) { return recap(d); },691 run: function (d) {692 // ⚠️ FIX: pehle ye sirf "reseller_price" save karta tha, jabki asli693 // "💼 Reseller Upgrade" button (/reseller_upgrade) "reseller_upgrade_price"694 // padhta hai — isliye admin yaha se fee set karta tha lekin button695 // "price admin ne abhi set nahi kiya" dikhata rehta tha. Ab dono keys696 // saath me set hoti hain taaki /reseller (legacy) aur /reseller_upgrade697 // (button flow) dono sync me rahein.698 Bot.setProperty("reseller_price", d.price, "integer");699 Bot.setProperty("reseller_upgrade_price", d.price, "number");700 return { text: "👑 <b>Reseller upgrade fee update:</b> ₹" + d.price };701 }702 };703 F.fee_upgrade = {704 title: "💎 RESELLER PRICE",705 steps: [T("price", "💰 <b>Reseller upgrade price kitna?</b> (₹)\n<i>Current: " + esc(Bot.getProperty("reseller_upgrade_price") || "Not set") + "</i>", vPrice)],706 sum: function (d) { return recap(d); },707 run: function (d) {708 Bot.setProperty("reseller_upgrade_price", d.price, "number");709 Bot.setProperty("reseller_price", d.price, "integer"); // legacy /reseller command isi key se padhta hai — sync rakhte hain710 return { text: "✅ <b>Reseller upgrade price set:</b> ₹" + d.price.toFixed(2) };711 }712 };713 714 // ----- AI support (multi-API, OpenAI-compatible)715 F.ai_api_add = {716 title: "🤖 ADD AI API",717 steps: [718 T("name", "🤖 <b>AI API ka naam</b> bhejein (sirf pehchaan ke liye)\n<i>Jaise: OpenAI Main, Gemini Backup</i>", vName),719 T("url", "🔗 <b>Base URL</b> bhejein (OpenAI-compatible /chat/completions ke bina)\n<i>Jaise: https://api.openai.com/v1</i>", vUrl,720 { quick: [["OpenAI", "https://api.openai.com/v1"], ["Groq", "https://api.groq.com/openai/v1"], ["OpenRouter", "https://openrouter.ai/api/v1"]] }),721 T("model", "🧠 <b>Model ka naam</b> bhejein\n<i>Jaise: gpt-4o-mini, llama-3.3-70b-versatile</i>", vName),722 T("key", "🔑 <b>API Key</b> bhejein", vApiKey)723 ],724 sum: function (d) {725 var maskedKey = d.key.length > 8 ? (d.key.slice(0, 4) + "••••" + d.key.slice(-4)) : "Configured";726 return "🤖 Name: <b>" + esc(d.name) + "</b>\n🔗 URL: <code>" + esc(d.url) + "</code>\n🧠 Model: <code>" + esc(d.model) + "</code>\n🔑 Key: <code>" + esc(maskedKey) + "</code>";727 },728 run: function (d) {729 var list = Bot.getProperty("ai_api_configs") || [];730 var newId = "ai" + Date.now();731 list.push({ id: newId, name: d.name, base_url: d.url, model: d.model, api_key: d.key });732 Bot.setProperty("ai_api_configs", list, "json");733 Bot.setProperty("ai_active_api_id", newId, "string");734 return {735 text: "✅ <b>AI API Added & Activated!</b>\n\n🤖 " + esc(d.name) + "\n🧠 " + esc(d.model),736 rows: [[{ text: "⬅️ Back to AI Manager", callback_data: "/admin_ai", style: "danger" }]]737 };738 }739 };740 F.ai_prompt = {741 title: "✏️ AI SYSTEM PROMPT",742 steps: [T("prompt", "✏️ <b>AI ko kya instruction follow karni chahiye?</b>\n<i>Current: " + esc(Bot.getProperty("ai_system_prompt") || "You are a helpful support assistant.") + "</i>", vPrompt)],743 sum: function (d) { return "✏️ Prompt:\n<i>" + esc(d.prompt) + "</i>"; },744 run: function (d) {745 Bot.setProperty("ai_system_prompt", d.prompt, "string");746 return { text: "✅ AI system prompt update ho gaya.", rows: [[{ text: "⬅️ Back to AI Manager", callback_data: "/admin_ai", style: "danger" }]] };747 }748 };749 750 // =====================================================================751 // 🌐 MULTI WEBSITE (API) + 🆔 PID EDIT752 // Har website = api_registry ka ek entry (URL + API key + Master key).753 // Product ko website assign karne par us product ki keys usi website se754 // kharidi jaati hain (product.api_id). Assign nahi to Default (Active) website.755 // =====================================================================756 var S_SITE = { k: "sid", t: "site", q: "🌐 <b>Website chuniye:</b>" };757 var S_SITEOPT = { k: "sid", t: "siteopt", q: "🌐 <b>Is product ki key kaunsi website se leni hai?</b>\n<i>Is panel ke saare plans usi website ke API se kharide jayenge.</i>" };758 function vMasterKey(s) {759 s = s.trim();760 if (s.length < 4) return { err: "Valid master key bhejein." };761 return { val: s };762 }763 // API type shortcuts: gk_post / gk_get (generate_key style, e.g. hkmodz) or reseller_v1 (standard)764 function vMode(s) {765 s = String(s).trim().toLowerCase();766 if (s === "gk_post" || s === "gk_get" || s === "reseller_v1") return { val: s };767 return { err: "Neeche ke buttons me se API type chuniye." };768 }769 function modeToFields(v) {770 if (v === "gk_get") return { mode: "generate_key", method: "GET" };771 if (v === "gk_post") return { mode: "generate_key", method: "POST" };772 return { mode: "reseller_v1", method: "POST" };773 }774 function modeLabel(x) {775 x = x || {};776 if (String(x.mode) === "generate_key") return "Generate Key (" + String(x.method || "POST").toUpperCase() + ")";777 return "Standard (reseller_v1)";778 }779 function vExtra(s) {780 s = String(s).trim().replace(/^[?&]+/, "");781 if (!/^[A-Za-z0-9_.\-]+=[^&\s]*(&[A-Za-z0-9_.\-]+=[^&\s]*)*$/.test(s)) return { err: "Format: <code>naam=value&naam2=value2</code> (space nahi). Nahi chahiye to Skip dabayein." };782 return { val: s };783 }784 var MODE_QUICK = [["Generate Key — POST", "gk_post"], ["Generate Key — GET", "gk_get"], ["Standard (reseller_v1)", "reseller_v1"]];785 function newSiteId(name) {786 var reg = sitesReg();787 var base = String(name || "site").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 20) || "site";788 if (base === "default") base = "site";789 var id = base, n = 2;790 while (reg[id]) { id = base + "_" + n; n++; }791 return id;792 }793 function productsUsing(id) {794 var out = [], pl = prods();795 for (var i = 0; i < pl.length; i++) { if (pl[i] && pl[i].name && String(pl[i].api_id || "") === String(id)) out.push(pl[i].name); }796 return out;797 }798 799 F.sites = { title: "👤 ACCOUNTS (PANEL API)", menu: [800 ["➕ Naya Account Add", "/wz go site_add"],801 ["🔗 Product ko Website Do", "/wz go site_prod"],802 ["📋 Accounts List + Test", "/wz go site_list"],803 ["✏️ Account Edit (URL / Key / Master / Type)", "/wz go site_edit"],804 ["⭐ Default (Active) Account", "/wz go site_active"],805 ["⏯ Account ON / OFF", "/wz go site_toggle"],806 ["🗑 Account Remove", "/wz go site_rem"],807 ["🆔 Plan ka PID Badlo", "/wz go pid_edit"]808 ] };809 810 F.site_add = {811 title: "➕ NAYI WEBSITE",812 steps: [813 T("sname", "🌐 <b>Website ka naam</b> bhejein (sirf pehchaan ke liye)\n<i>Jaise: KeyPanel, Site 2</i>", vName),814 T("surl", "🔗 <b>Website ka API URL</b> bhejein\n<i>Jaise: https://keypanel.shop/reseller_gateway.php</i>", vUrl),815 T("skey", "🔑 <b>API Key</b> bhejein", vApiKey),816 T("smaster", "🗝 <b>Master Key</b> bhejein (agar website me alag hai)\n<i>Nahi hai to neeche button dabayein, API key hi master key rahegi.</i>", vMasterKey, { skip: { l: "↩️ API key hi master key", v: "" } }),817 T("smode", "⚙️ <b>API type chuniye</b>\n<i>hkmodz jaisi <code>generate_key.php</code> wali site ke liye <b>Generate Key</b> (pehle POST, na chale to GET). Purani reseller_gateway wali site ke liye <b>Standard</b>.</i>", vMode, { quick: MODE_QUICK }),818 T("sextra", "➕ <b>Extra parameters</b> (optional)\n<i>Agar website kuch aur fixed field maangti hai to aise bhejein: <code>type=1&server=2</code>. Nahi chahiye to Skip dabayein.</i>", vExtra, { skip: { l: "⏭ Skip", v: "" } })819 ],820 sum: function (d) {821 return "🌐 Naam: <b>" + esc(d.sname) + "</b>\n🔗 URL: <code>" + esc(d.surl) + "</code>\n🔑 API Key: <code>" + esc(maskKey(d.skey)) + "</code>\n🗝 Master Key: <code>" + esc(d.smaster ? maskKey(d.smaster) : "Same as API key") + "</code>\n⚙️ Type: <b>" + esc(modeLabel(modeToFields(d.smode))) + "</b>" + (d.sextra ? "\n➕ Extra: <code>" + esc(d.sextra) + "</code>" : "");822 },823 run: function (d) {824 var reg = sitesReg();825 var id = newSiteId(d.sname);826 reg[id] = {827 id: id, name: d.sname, url: d.surl, api_key: d.skey,828 master_key: d.smaster || d.skey, master_custom: !!d.smaster,829 mode: modeToFields(d.smode).mode, method: modeToFields(d.smode).method, extra: d.sextra || "",830 android_required: false, policy: "", side: "", user_number: "",831 enabled: true, updated_at: new Date().toISOString()832 };833 Bot.setProperty("api_registry", reg, "json");834 var act = String(Bot.getProperty("active_reseller_api") || "");835 if (!act || !reg[act]) Bot.setProperty("active_reseller_api", id, "string");836 return {837 text: "<blockquote>✅ <b>Account Add Ho Gaya!</b></blockquote>\n\n🌐 <b>" + esc(d.sname) + "</b> (<code>" + esc(id) + "</code>)\n\n<i>Pehle 🧪 Test Connection dabao. Phir kisi panel ko ye account do aur plan me PID daalo.</i>",838 rows: [839 [{ text: "🧪 Test Connection", callback_data: "/extkey_test " + id, style: "success" }],840 [{ text: "🔗 Panel ko ye Account Do", callback_data: "/wz go site_prod", style: "primary" }],841 [{ text: "➕ Ek aur Account", callback_data: "/wz go site_add", style: "primary" }]842 ]843 };844 }845 };846 847 F.site_prod = {848 title: "🔗 PRODUCT KO WEBSITE",849 steps: [S_PROD, S_SITEOPT],850 sum: function (d) { return recap(d); },851 run: function (d) {852 var list = prods();853 if (!list[d.pi]) return { text: "❌ Panel nahi mila." };854 if (d.sid) list[d.pi].api_id = d.sid; else delete list[d.pi].api_id;855 Bot.setProperty("stored_products", list, "json");856 return {857 text: "<blockquote>✅ <b>Website Set Ho Gayi!</b></blockquote>\n\n📦 <b>" + esc(d.pn) + "</b> → 🌐 <b>" + esc(d.swn) + "</b>\n\n<i>Ab is panel ke saare plans isi website ke API se kharide jayenge. Plan ka PID bhi isi website ka hona chahiye.</i>",858 rows: [859 [{ text: "🆔 PID Badlo", callback_data: "/wz go pid_edit", style: "primary" }],860 [{ text: "🔗 Dusre Product ko Website", callback_data: "/wz go site_prod", style: "success" }]861 ]862 };863 }864 };865 866 F.site_list = { title: "📋 WEBSITES LIST", steps: [], noconfirm: true,867 run: function () {868 var reg = sitesReg(); var ids = Object.keys(reg);869 var act = String(Bot.getProperty("active_reseller_api") || "");870 if (!ids.length) return { text: "<blockquote>🌐 <b>WEBSITES</b></blockquote>\n\n<i>Abhi koi website add nahi hai.</i>", rows: [[{ text: "➕ Nayi Website Add", callback_data: "/wz go site_add", style: "success" }]] };871 var all = prods(), unassigned = [];872 for (var i = 0; i < all.length; i++) { if (all[i] && all[i].name && !(all[i].api_id && reg[all[i].api_id])) unassigned.push(all[i].name); }873 var L = [], rows = [];874 for (var k = 0; k < ids.length; k++) {875 var x = reg[ids[k]] || {};876 var used = productsUsing(ids[k]);877 if (ids[k] === act) used = used.concat(unassigned.map(function (n) { return n + " (default)"; }));878 L.push("🌐 <b>" + esc(x.name || ids[k]) + "</b> (<code>" + esc(ids[k]) + "</code>)" + (ids[k] === act ? " ⭐" : "") + (x.enabled === false ? " 🔴 OFF" : " 🟢 ON") +879 "\n 🔗 " + esc(hostOf(x.url)) + " • ⚙️ " + esc(modeLabel(x)) + "\n 🔑 <code>" + esc(maskKey(x.api_key)) + "</code> • 🗝 <code>" + esc(x.master_custom ? maskKey(x.master_key) : "Same as API key") + "</code>" +880 "\n 📦 " + (used.length ? esc(used.join(", ")) : "<i>koi product nahi</i>"));881 if (rows.length < 8) rows.push([{ text: "🧪 Test: " + short(x.name || ids[k], 24), callback_data: "/extkey_test " + ids[k], style: "primary" }]);882 }883 return { text: "<blockquote>🌐 <b>WEBSITES</b></blockquote> <i>⭐ = Default (Active)</i>\n\n" + L.join("\n\n"), rows: rows };884 } };885 886 F.site_edit = { title: "✏️ WEBSITE EDIT", menu: [887 ["📝 Naam badlo", "/wz go site_e_name"],888 ["🔗 URL badlo", "/wz go site_e_url"],889 ["🔑 API Key badlo", "/wz go site_e_key"],890 ["🗝 Master Key badlo", "/wz go site_e_master"],891 ["⚙️ API Type badlo (Generate Key / Standard)", "/wz go site_e_mode"],892 ["➕ Extra Parameters badlo", "/wz go site_e_extra"]893 ] };894 function siteEditFlow(title, field, q, v, x) {895 return {896 title: title,897 steps: [S_SITE, T("sval", q, v, x)],898 sum: function (d) {899 var shown = (field === "api_key" || field === "master_key") ? (d.sval ? maskKey(d.sval) : "Same as API key") : (field === "mode" ? modeLabel(modeToFields(d.sval)) : (field === "extra" ? (d.sval || "(khaali)") : d.sval));900 return "🌐 Website: <b>" + esc(d.swn) + "</b>\n✏️ Naya: <code>" + esc(shown) + "</code>";901 },902 run: function (d) {903 var reg = sitesReg(); var x0 = reg[d.sid];904 if (!x0) return { text: "❌ Website nahi mili." };905 if (field === "name") x0.name = d.sval;906 else if (field === "url") x0.url = d.sval;907 else if (field === "api_key") { x0.api_key = d.sval; if (!x0.master_custom) x0.master_key = d.sval; }908 else if (field === "master_key") { x0.master_custom = !!d.sval; x0.master_key = d.sval || x0.api_key || ""; }909 else if (field === "mode") { var mf = modeToFields(d.sval); x0.mode = mf.mode; x0.method = mf.method; }910 else if (field === "extra") { x0.extra = d.sval || ""; }911 x0.updated_at = new Date().toISOString();912 reg[d.sid] = x0;913 Bot.setProperty("api_registry", reg, "json");914 return {915 text: "✅ <b>Website update ho gayi:</b> " + esc(x0.name || d.sid),916 rows: [[{ text: "🧪 Test Connection", callback_data: "/extkey_test " + d.sid, style: "primary" }], [{ text: "⬅️ Website Menu", callback_data: "/wz go sites", style: "primary" }]]917 };918 }919 };920 }921 F.site_e_name = siteEditFlow("📝 WEBSITE NAAM", "name", "📝 <b>Naya naam</b> bhejein", vName);922 F.site_e_url = siteEditFlow("🔗 WEBSITE URL", "url", "🔗 <b>Naya API URL</b> bhejein", vUrl);923 F.site_e_key = siteEditFlow("🔑 WEBSITE API KEY", "api_key", "🔑 <b>Nayi API Key</b> bhejein", vApiKey);924 F.site_e_mode = siteEditFlow("⚙️ ACCOUNT API TYPE", "mode", "⚙️ <b>Naya API type chuniye</b>", vMode, { quick: MODE_QUICK });925 F.site_e_extra = siteEditFlow("➕ ACCOUNT EXTRA PARAMS", "extra", "➕ <b>Extra parameters bhejein</b>\n<i>Format: <code>naam=value&naam2=value2</code>. Hatana ho to Skip dabayein.</i>", vExtra, { skip: { l: "🗑 Khaali karo", v: "" } });926 F.site_e_master = siteEditFlow("🗝 WEBSITE MASTER KEY", "master_key", "🗝 <b>Nayi Master Key</b> bhejein\n<i>Alag master key nahi hai to neeche button dabayein.</i>", vMasterKey, { skip: { l: "↩️ API key hi master key", v: "" } });927 928 F.site_active = { title: "⭐ DEFAULT WEBSITE", steps: [S_SITE],929 sum: function (d) { return recap(d) + "\n\n<i>Jin products ko alag website assign nahi hai, wo isi se keys kharidenge.</i>"; },930 run: function (d) {931 if (!sitesReg()[d.sid]) return { text: "❌ Website nahi mili." };932 Bot.setProperty("active_reseller_api", d.sid, "string");933 return { text: "✅ <b>Default (Active) website:</b> " + esc(d.swn) };934 } };935 936 F.site_toggle = { title: "⏯ WEBSITE ON / OFF", steps: [S_SITE], noconfirm: true,937 run: function (d) {938 var reg = sitesReg(); var x0 = reg[d.sid];939 if (!x0) return { text: "❌ Website nahi mili." };940 x0.enabled = (x0.enabled === false);941 reg[d.sid] = x0; Bot.setProperty("api_registry", reg, "json");942 return { text: "🌐 <b>" + esc(x0.name || d.sid) + "</b> ab " + (x0.enabled ? "🟢 ON" : "🔴 OFF") + " hai.\n<i>OFF website ke products kharid nahi honge.</i>" };943 } };944 945 F.site_rem = { title: "🗑 WEBSITE REMOVE", steps: [S_SITE],946 sum: function (d) { var u = productsUsing(d.sid); return recap(d) + (u.length ? "\n\n⚠️ <i>Ye website in products par lagi hai: " + esc(u.join(", ")) + ". Remove karne par ye Default website par chale jayenge.</i>" : ""); },947 run: function (d) {948 var reg = sitesReg();949 if (!reg[d.sid]) return { text: "❌ Website nahi mili." };950 if (String(Bot.getProperty("active_reseller_api") || "") === d.sid) return { text: "❌ Ye <b>Default (Active)</b> website hai. Pehle ⭐ Default Website se dusri website set karein, phir remove karein." };951 var list = prods(), cleared = 0;952 for (var i = 0; i < list.length; i++) { if (list[i] && String(list[i].api_id || "") === d.sid) { delete list[i].api_id; cleared++; } }953 if (cleared) Bot.setProperty("stored_products", list, "json");954 delete reg[d.sid];955 Bot.setProperty("api_registry", reg, "json");956 return { text: "🗑 <b>" + esc(d.swn) + "</b> remove ho gayi." + (cleared ? "\n<i>" + cleared + " product Default website par chale gaye.</i>" : "") };957 } };958 959 F.pid_edit = {960 title: "🆔 PID BADLO",961 steps: [S_PROD, S_PLAN, T("pid", function (st) {962 var p = prods()[st.d.pi]; var pl = p && p.plans && p.plans[st.d.li];963 var cur = pl ? (pl.pid || pl.product_id || pl.variant_id || "—") : "—";964 return "🆔 <b>Naya PID bhejein</b>\n<i>Abhi ka PID: <code>" + esc(cur) + "</code></i>";965 }, vPid, { skip: { l: "🔑 Manual keys (no PID)", v: "0" } })],966 sum: function (d) {967 var p = prods()[d.pi]; var pl = p && p.plans && p.plans[d.li];968 var old = pl ? (pl.pid || pl.product_id || pl.variant_id || "—") : "—";969 return recap(d) + "\n🔁 Purana PID: <code>" + esc(old) + "</code>";970 },971 run: function (d) {972 var list = prods(); var p = list[d.pi]; var pl = p && p.plans && p.plans[d.li];973 if (!pl) return { text: "❌ Plan nahi mila (shayad pehle hi hat chuka hai)." };974 pl.pid = d.pid; pl.product_id = d.pid; pl.variant_id = d.pid;975 Bot.setProperty("stored_products", list, "json");976 return {977 text: "<blockquote>✅ <b>PID Update Ho Gaya!</b></blockquote>\n\n📦 <b>" + esc(d.pn) + "</b> • ⏱ <b>" + esc(d.pl) + "</b>\n🆔 Naya PID: <code>" + esc(d.pid) + "</code>",978 rows: [[{ text: "🆔 Aur PID Badlo", callback_data: "/wz go pid_edit", style: "primary" }]]979 };980 }981 };982 983 // ----- discounts984 F.discount = { title: "💸 SET DISCOUNT", menu: [985 ["🌍 Sab par (Global)", "/wz go disc_global"],986 ["📦 Poore Panel par", "/wz go disc_prod"],987 ["⏱ Ek Plan par", "/wz go disc_plan"],988 ["🗑 Discount Hatao", "/wz go disc_remove"]989 ] };990 F.disc_remove = { title: "🗑 DISCOUNT HATAO", menu: [991 ["🌍 Global hatao", "/wz go disc_rem_global"],992 ["📦 Panel ka hatao", "/wz go disc_rem_prod"],993 ["⏱ Plan ka hatao", "/wz go disc_rem_plan"]994 ] };995 F.disc_global = { title: "🌍 GLOBAL DISCOUNT", steps: [T("pct", "💸 <b>Kitne % discount?</b> (1-100)", vPct)],996 sum: function (d) { return "💸 Discount: <b>" + d.pct + "%</b> (sabhi products/plans par)"; },997 run: function (d) { Bot.setProperty("auto_discount_global", d.pct, "number"); return { text: "✅ <b>Global Discount set:</b> -" + d.pct + "%" }; } };998 F.disc_prod = { title: "📦 PANEL DISCOUNT", steps: [S_PROD, T("pct", "💸 <b>Kitne % discount?</b> (1-100)", vPct)],999 sum: function (d) { return recap(d) + "\n💸 Discount: <b>" + d.pct + "%</b> (panel ke sabhi plans)"; },1000 run: function (d) { Bot.setProperty("auto_discount_" + d.pn.toUpperCase() + "_ALL", d.pct, "number"); return { text: "✅ <b>Discount Set!</b>\n\n📦 " + esc(d.pn) + "\n💸 -" + d.pct + "% (sabhi plans)" }; } };1001 function planDiscKey(d) {1002 var list = prods(); var pl = list[d.pi] && list[d.pi].plans ? list[d.pi].plans[d.li] : null;1003 if (!pl) return null;1004 var vu = planValueUnit(pl);1005 return "auto_discount_" + String(list[d.pi].name).trim().toUpperCase() + "_" + vu.value + "_" + vu.unit.toUpperCase();1006 }1007 F.disc_plan = { title: "⏱ PLAN DISCOUNT", steps: [S_PROD, S_PLAN, T("pct", "💸 <b>Kitne % discount?</b> (1-100)", vPct)],1008 sum: function (d) { return recap(d) + "\n💸 Discount: <b>" + d.pct + "%</b>"; },1009 run: function (d) { var k = planDiscKey(d); if (!k) return { text: "❌ Plan nahi mila." }; Bot.setProperty(k, d.pct, "number"); return { text: "✅ <b>Discount Set!</b>\n\n" + recap(d) + "\n💸 -" + d.pct + "%" }; } };1010 F.disc_rem_global = { title: "🗑 GLOBAL DISCOUNT HATAO", steps: [], sum: function () { return "Global discount hata diya jayega."; },1011 run: function () { Bot.setProperty("auto_discount_global", null, "number"); return { text: "✅ Global discount hata diya gaya." }; } };1012 F.disc_rem_prod = { title: "🗑 PANEL DISCOUNT HATAO", steps: [S_PROD], sum: function (d) { return recap(d); },1013 run: function (d) { Bot.setProperty("auto_discount_" + d.pn.toUpperCase() + "_ALL", null, "number"); return { text: "✅ Discount hata diya: <code>" + esc(d.pn) + "</code>" }; } };1014 F.disc_rem_plan = { title: "🗑 PLAN DISCOUNT HATAO", steps: [S_PROD, S_PLAN], sum: function (d) { return recap(d); },1015 run: function (d) { var k = planDiscKey(d); if (!k) return { text: "❌ Plan nahi mila." }; Bot.setProperty(k, null, "number"); return { text: "✅ Discount hata diya gaya:\n\n" + recap(d) }; } };1016 1017 // ----- member custom price1018 function memberKey(d) {1019 var list = prods(); var pl = list[d.pi] && list[d.pi].plans ? list[d.pi].plans[d.li] : null;1020 if (!pl) return { err: "Plan nahi mila." };1021 var vu = planValueUnit(pl);1022 if (vu.unit === "minute") return { err: "Member price sirf Hour/Day plans par lag sakta hai." };1023 var clean = String(list[d.pi].name).toUpperCase().replace(/\s+/g, " ").trim();1024 var keyProduct = clean.replace(/[^A-Z0-9_-]/g, "_");1025 var suffix = vu.unit === "day" ? vu.value : vu.value + "_hour";1026 return { key: "member_custom_price_" + d.uid + "_" + keyProduct + "_" + suffix };1027 }1028 F.mp_set = { title: "👤 MEMBER CUSTOM PRICE", steps: [S_USER, S_PROD, S_PLAN, T("price", "💰 <b>Is member ke liye price kitna?</b> (₹)", vPrice0)],1029 sum: function (d) { return recap(d) + "\n\n<i>Global price nahi badlega, sirf is member par lagega.</i>"; },1030 run: function (d) { var k = memberKey(d); if (k.err) return { text: "❌ " + k.err }; Bot.setProperty(k.key, d.price, "number"); return { text: "✅ <b>Member price set!</b>\n\n" + recap(d) }; } };1031 F.mp_rem = { title: "🗑 MEMBER PRICE HATAO", steps: [S_USER, S_PROD, S_PLAN], sum: function (d) { return recap(d); },1032 run: function (d) { var k = memberKey(d); if (k.err) return { text: "❌ " + k.err }; Bot.setProperty(k.key, null, "number"); return { text: "✅ Member custom price hata diya.\n\n" + recap(d) }; } };1033 1034 // ----- co-admins / ownership / identity (owner only)1035 F.coadmin = { title: "👑 CO-ADMINS", own: true, menu: [1036 ["➕ Co-Admin Add", "/wz go co_add"], ["➖ Co-Admin Remove", "/wz go co_rem"], ["📋 List Dekhein", "/wz go co_list"]1037 ] };1038 F.co_add = { title: "➕ CO-ADMIN ADD", steps: [S_USER], own: true, sum: function (d) { return recap(d); },1039 run: function (d) {1040 if (String(d.uid) === ownerId) return { text: "❌ Owner khud ko co-admin nahi bana sakta!" };1041 var list = Bot.getProperty("co_admin_list") || [];1042 Bot.setProperty("co_admin_" + d.uid, true, "boolean");1043 if (list.indexOf(d.uid) === -1) { list.push(d.uid); Bot.setProperty("co_admin_list", list, "json"); }1044 try { Api.sendMessage({ chat_id: d.uid, parse_mode: "HTML", text: "<blockquote>👑 <b>YOU ARE NOW A CO-ADMIN!</b></blockquote>\n\n<i>Admin panel ke liye /admin use karein.</i>" }); } catch (e) {}1045 return { text: "✅ <b>Co-Admin Added!</b> User <code>" + esc(d.uid) + "</code> ab admin panel use kar sakta hai." };1046 } };1047 F.co_rem = { title: "➖ CO-ADMIN REMOVE", steps: [S_USER], own: true, sum: function (d) { return recap(d); },1048 run: function (d) {1049 var list = Bot.getProperty("co_admin_list") || [];1050 Bot.setProperty("co_admin_" + d.uid, null, "boolean");1051 var i = list.indexOf(d.uid);1052 if (i > -1) { list.splice(i, 1); Bot.setProperty("co_admin_list", list, "json"); }1053 return { text: "✅ <b>Co-Admin Removed!</b> User <code>" + esc(d.uid) + "</code> ka access hat gaya." };1054 } };1055 F.co_list = { title: "📋 CO-ADMIN LIST", steps: [], noconfirm: true, own: true,1056 run: function () {1057 var list = Bot.getProperty("co_admin_list") || [];1058 return { text: "<blockquote>👑 <b>CO-ADMIN LIST</b></blockquote>\n\n" + (list.length ? list.map(function (x) { return "• <code>" + esc(x) + "</code>"; }).join("\n") : "<i>Koi co-admin nahi hai.</i>") };1059 } };1060 1061 F.transfer = { title: "🔁 SET USER ID / TRANSFER OWNERSHIP", own: true,1062 steps: [T("uid", "🆔 <b>Naye Owner ka User ID bhejein</b>\n<i>Sirf number. ⚠️ Confirm ke baad aap Owner nahi rahenge — ID dobara check kar lein.</i>", vUser)],1063 noconfirm: true,1064 run: function (d) {1065 if (String(d.uid) === ownerId) return { text: "ℹ️ Ye ID pehle se Owner ki hai." };1066 User.setProperty("pending_ownership_transfer_to", d.uid, "string");1067 return {1068 text: "<blockquote>⚠️ <b>CONFIRM OWNERSHIP TRANSFER</b></blockquote>\n\nAap ownership <code>" + esc(d.uid) + "</code> ko transfer karne wale hain.\n<b>Ye action turant apply hoga aur aap Owner nahi rahenge!</b>\n\n<i>Kya aap sure hain?</i>",1069 rows: [[{ text: "Confirm Transfer", callback_data: "/confirm_ownership_transfer", style: "danger", icon_custom_emoji_id: "6215386799133433653" },1070 { text: "Cancel", callback_data: "/cancel_ownership_transfer", style: "primary" }]]1071 };1072 } };1073 1074 F.idb = { title: "🤖 SET BOT USERNAME", own: true,1075 steps: [T("bu", "🤖 <b>Bot ka username bhejein</b> (jaise <code>@MyShopBot</code>)\n<i>Current: @" + esc(String(Bot.getProperty("bot_username") || "JASSMODZSHOP_BOT").replace(/^@/, "")) + "</i>", vBotUser)],1076 noconfirm: true,1077 run: function (d) {1078 Bot.setProperty("bot_username", d.bu, "string");1079 return { text: "✅ <b>Bot username update:</b> <code>@" + esc(d.bu) + "</code>\n\n🔗 Referral link:\n<code>https://t.me/JASSMODZSHOP_BOT?start=_tgr_uXY38UUxODY9</code>",1080 rows: [[{ text: "🪪 Identity Settings", callback_data: "/bot_identity", style: "primary" }]] };1081 } };1082 F.ida = { title: "📞 SET ADMIN USERNAME", own: true,1083 steps: [T("au", "📞 <b>Admin ka @username bhejein</b> (jaise <code>@YourName</code>)", vAdminUser)],1084 noconfirm: true,1085 run: function (d) {1086 Bot.setProperty("admin_username", d.au, "string");1087 Bot.setProperty("support_link", "https://t.me/" + d.au, "string");1088 return { text: "✅ <b>Admin username update:</b> <code>@" + esc(d.au) + "</code>\n\n📞 Support ka <b>Contact Admin</b> ab <code>https://t.me/" + esc(d.au) + "</code> par khulega.",1089 rows: [[{ text: "🪪 Identity Settings", callback_data: "/bot_identity", style: "primary" }]] };1090 } };1091 1092 // ------------------------------------------------------------ the engine1093 function loadState() {1094 var st = User.getProperty("wz_state");1095 if (typeof st === "string") { try { st = JSON.parse(st); } catch (e) { st = null; } }1096 if (st && st.t && (Date.now() - st.t) > 20 * 60 * 1000) { st = null; }1097 if (!(st && st.f && F[st.f])) { clearState(); return null; } // expired/unknown -> never leave a stale state1098 return st;1099 }1100 function saveState(st) { st.t = Date.now(); User.setProperty("wz_state", st, "json"); }1101 function clearState() { User.setProperty("wz_state", null, "json"); }1102 1103 function ownerGuard(fl) {1104 if (fl.own && !isOwner) { show("❌ Ye option sirf <b>Owner</b> ke liye hai.", [BACK_ADMIN]); return false; }1105 return true;1106 }1107 1108 function finish(st) {1109 var fl = F[st.f];1110 var res = fl.run(st.d);1111 clearState();1112 var rows = (res.rows || []).slice();1113 rows.push(BACK_ADMIN);1114 // results are always sent fresh so the history stays readable1115 Api.sendMessage({ chat_id: me, text: res.text, parse_mode: "HTML", reply_markup: JSON.stringify({ inline_keyboard: rows }) });1116 }1117 1118 function chooseRows(sp, st) {1119 var rows = [];1120 if (sp.t === "cat") {1121 var ks = ["root", "nonroot", "iphone", "both"];1122 for (var i = 0; i < ks.length; i++) rows.push([{ text: CAT_LABELS[ks[i]], callback_data: "/wz c " + ks[i], style: "danger" }]);1123 } else if (sp.t === "prodcat") {1124 var all = prods();1125 for (var pc = 0; pc < all.length && rows.length < 60; pc++) {1126 if (all[pc] && all[pc].name && inCat(all[pc], st.d.cat)) {1127 rows.push([{ text: short(all[pc].name, 30) + " (" + ((all[pc].plans || []).length) + ")", callback_data: "/wz c " + pc, style: "primary" }]);1128 }1129 }1130 } else if (sp.t === "unit") {1131 rows.push([{ text: "⏰ Hours", callback_data: "/wz c h", style: "primary" }, { text: "📅 Days", callback_data: "/wz c d", style: "primary" }]);1132 } else if (sp.t === "prod") {1133 var pl = prods();1134 for (var j = 0; j < pl.length && j < 60; j++) {1135 if (pl[j] && pl[j].name) rows.push([{ text: (j + 1) + ". " + short(pl[j].name, 34), callback_data: "/wz c " + j, style: "primary" }]);1136 }1137 } else if (sp.t === "plan") {1138 var pr = prods()[st.d.pi];1139 var plans = pr && pr.plans ? pr.plans : [];1140 for (var k = 0; k < plans.length && k < 60; k++) {1141 rows.push([{ text: short(planLabel(plans[k]), 26) + " • ₹" + plans[k].normal_price, callback_data: "/wz c " + k, style: "primary" }]);1142 }1143 } else if (sp.t === "site" || sp.t === "siteopt") {1144 var sr = sitesReg(); var sids = Object.keys(sr);1145 if (sp.t === "siteopt") rows.push([{ text: "↩️ Default (Active) website", callback_data: "/wz c none", style: "success" }]);1146 for (var si = 0; si < sids.length && si < 40; si++) {1147 var sx = sr[sids[si]] || {};1148 rows.push([{ text: "🌐 " + short(sx.name || sids[si], 20) + " • " + short(hostOf(sx.url), 22) + (sx.enabled === false ? " (OFF)" : ""), callback_data: "/wz c " + si, style: "primary" }]);1149 }1150 } else if (sp.t === "idcat") {1151 var cs = idCats(); var slugs = Object.keys(cs);1152 for (var m = 0; m < slugs.length && m < 60; m++) rows.push([{ text: "📁 " + short(cs[slugs[m]].name || slugs[m], 30), callback_data: "/wz c " + m, style: "primary" }]);1153 }1154 return rows;1155 }1156 1157 // panel belongs to a category (root/nonroot/iphone); "both"/unset panels show under every category1158 function inCat(p, cat) {1159 var c = String(p.category || "both");1160 return cat === "both" ? c === "both" : (c === cat || c === "both");1161 }1162 1163 function render(st) {1164 var fl = F[st.f];1165 if (fl.menu) {1166 var mrows = fl.menu.map(function (m) { return [{ text: m[0], callback_data: m[1], style: "primary" }]; });1167 mrows.push(BACK_ADMIN);1168 show("<blockquote><b>" + fl.title + "</b></blockquote>\n\nKya karna hai?", mrows);1169 return;1170 }1171 var steps = fl.steps;1172 if (st.s >= steps.length) {1173 if (fl.noconfirm || !fl.sum) { finish(st); return; }1174 show("<blockquote><b>" + fl.title + "</b> • Confirm</blockquote>\n\n" + fl.sum(st.d) + "\n\n<b>Sab sahi hai?</b>",1175 [[{ text: "✅ Confirm & Save", callback_data: "/wz ok", style: "success" }], [NAV_BACK, NAV_CANCEL]]);1176 return;1177 }1178 var sp = steps[st.s];1179 var head = "<blockquote><b>" + fl.title + "</b> • Step " + (st.s + 1) + "/" + steps.length + "</blockquote>\n\n";1180 var rc = recap(st.d);1181 var body = (rc ? rc + "\n\n" : "") + (typeof sp.q === "function" ? sp.q(st) : sp.q);1182 var rows = [];1183 if (sp.t === "text") {1184 if (sp.x.quick) {1185 var row = [];1186 for (var q = 0; q < sp.x.quick.length; q++) {1187 row.push({ text: sp.x.quick[q][0], callback_data: "/wz c " + sp.x.quick[q][1], style: "primary" });1188 if (row.length === 3) { rows.push(row); row = []; }1189 }1190 if (row.length) rows.push(row);1191 }1192 if (sp.x.skip) rows.push([{ text: sp.x.skip.l, callback_data: "/wz skip", style: "success" }]);1193 if (sp.x.skipSame) rows.push([{ text: "🟰 Same as user price", callback_data: "/wz skip", style: "success" }]);1194 } else {1195 rows = chooseRows(sp, st);1196 if (!rows.length) {1197 clearState();1198 show("❌ " + (sp.t === "prodcat" ? "Is category mein abhi koi panel nahi hai. Pehle Add Product se panel banayein." : sp.t === "idcat" ? "Koi ID category nahi hai. Pehle ID category add karein." : sp.t === "plan" ? "Is panel mein koi plan nahi hai." : (sp.t === "site" || sp.t === "siteopt") ? "Abhi koi website add nahi hai. Pehle Multi Website me Nayi Website Add karein." : "Abhi koi product nahi hai. Pehle Add Product karein.") , [BACK_ADMIN]);1199 return;1200 }1201 }1202 rows.push(st.s > 0 ? [NAV_BACK, NAV_CANCEL] : [NAV_CANCEL]);1203 show(head + body, rows);1204 }1205 1206 // apply a value to the current step (buttons + text)1207 function applyChoice(st, token) {1208 var sp = F[st.f].steps[st.s];1209 if (!sp) return false;1210 if (sp.t === "cat") { if (!CAT_LABELS[token]) return false; st.d.cat = token; }1211 else if (sp.t === "prod") {1212 var i = parseInt(token, 10); var pl = prods();1213 if (isNaN(i) || !pl[i]) return false;1214 st.d.pi = i; st.d.pn = pl[i].name;1215 } else if (sp.t === "prodcat") {1216 var q = parseInt(token, 10); var pq = prods();1217 if (isNaN(q) || !pq[q] || !inCat(pq[q], st.d.cat)) return false;1218 st.d.pi = q; st.d.pn = pq[q].name;1219 } else if (sp.t === "unit") {1220 if (token !== "h" && token !== "d") return false;1221 st.d.unit = token;1222 } else if (sp.t === "plan") {1223 var l = parseInt(token, 10); var pr = prods()[st.d.pi];1224 if (isNaN(l) || !pr || !pr.plans || !pr.plans[l]) return false;1225 st.d.li = l; st.d.pl = planLabel(pr.plans[l]);1226 } else if (sp.t === "site" || sp.t === "siteopt") {1227 if (sp.t === "siteopt" && token === "none") { st.d.sid = ""; st.d.swn = "Default (Active) website"; }1228 else {1229 var xi = parseInt(token, 10); var xids = siteIds();1230 if (isNaN(xi) || !xids[xi]) return false;1231 st.d.sid = xids[xi]; st.d.swn = siteName(xids[xi]);1232 }1233 } else if (sp.t === "idcat") {1234 var m = parseInt(token, 10); var cs = idCats(); var sl = Object.keys(cs);1235 if (isNaN(m) || !sl[m]) return false;1236 st.d.slug = sl[m]; st.d.catName = cs[sl[m]].name || sl[m];1237 } else if (sp.t === "text") {1238 var res = sp.v(String(token)); // quick buttons pass a ready value1239 if (res.err) return false;1240 st.d[sp.k] = res.val;1241 } else return false;1242 st.s++;1243 return true;1244 }1245 1246 // --------------------------------------------------------------- dispatch1247 if (isText) {1248 var st0 = loadState();1249 if (!st0) { Bot.sendMessage("ℹ️ Koi active wizard nahi hai. /admin se option chuniye."); return; }1250 try { if (request && request.message_id) Api.deleteMessage({ chat_id: me, message_id: request.message_id }); } catch (de) {}1251 var fl0 = F[st0.f];1252 var sp0 = fl0.steps ? fl0.steps[st0.s] : null;1253 if (!sp0 || sp0.t !== "text") { Bot.sendMessage("👆 Upar diye gaye <b>buttons</b> se chuniye.", { parse_mode: "HTML" }); return; }1254 var rr = sp0.v(rawText);1255 if (rr.err) {1256 Api.sendMessage({ chat_id: me, parse_mode: "HTML", text: "❌ " + esc(rr.err) + "\n\nDobara bhejein:",1257 reply_markup: JSON.stringify({ inline_keyboard: [[NAV_CANCEL]] }) });1258 return;1259 }1260 st0.d[sp0.k] = rr.val; st0.s++;1261 saveState(st0);1262 render(st0);1263 return;1264 }1265 1266 if (verb === "go") {1267 var name = arg.split(/\s+/)[0];1268 var fl = F[name];1269 if (!fl) { show("⚠️ Unknown option.", [BACK_ADMIN]); return; }1270 if (!ownerGuard(fl)) return;1271 var st = { f: name, s: 0, d: {} };1272 if (fl.menu) { clearState(); render(st); return; }1273 saveState(st);1274 render(st);1275 return;1276 }1277 1278 if (verb === "more") {1279 // add another plan to a panel that was just created1280 var pi = parseInt(arg, 10); var pls = prods();1281 if (isNaN(pi) || !pls[pi]) { show("❌ Panel nahi mila.", [BACK_ADMIN]); return; }1282 var stm = { f: "add_plan", s: 1, d: { pi: pi, pn: pls[pi].name } };1283 saveState(stm); render(stm); return;1284 }1285 1286 if (verb === "qmore") {1287 var qi = parseInt(arg, 10); var qp = prods();1288 if (isNaN(qi) || !qp[qi]) { show("❌ Panel nahi mila.", [BACK_ADMIN]); return; }1289 var cat0 = (qp[qi].category && CAT_LABELS[qp[qi].category]) ? qp[qi].category : "both";1290 var stq = { f: "quick_add", s: 2, d: { cat: cat0, pi: qi, pn: qp[qi].name } };1291 saveState(stq); render(stq); return;1292 }1293 1294 if (verb === "cancel") {1295 clearState();1296 show("❌ <b>Cancel ho gaya.</b>", [BACK_ADMIN]);1297 return;1298 }1299 1300 var cur = loadState();1301 if (!cur) { show("⌛ Session expire ho gaya. /admin se dobara shuru karein.", [BACK_ADMIN]); return; }1302 if (!ownerGuard(F[cur.f])) return;1303 1304 if (verb === "back") {1305 if (cur.s > 0) cur.s--;1306 saveState(cur); render(cur); return;1307 }1308 if (verb === "skip") {1309 var spk = F[cur.f].steps[cur.s];1310 if (spk && spk.t === "text" && spk.x.skip) { cur.d[spk.k] = spk.x.skip.v; cur.s++; }1311 else if (spk && spk.x && spk.x.skipSame) { cur.d[spk.k] = cur.d.price; cur.s++; }1312 saveState(cur); render(cur); return;1313 }1314 if (verb === "c") {1315 if (!applyChoice(cur, arg)) { render(cur); return; }1316 saveState(cur); render(cur); return;1317 }1318 if (verb === "ok") {1319 var flo = F[cur.f];1320 if (cur.s < flo.steps.length) { render(cur); return; }1321 finish(cur); return;1322 }1323 1324 show("⚠️ Unknown action.", [BACK_ADMIN]);1325 1326} catch (err) {1327 Bot.sendMessage("⚠️ Wizard Error: " + err.message);1328}