111dhruvil111/EntrysakibotPublic · Bot Template

AIThis TBL bot implements a private crypto community access flow called RED EYE. It stores user Telegram profiles, enforces entry requirements such as minimum crypto net worth and deal volume, and offers inline buttons for applying, checking application status, and contacting support. Admin commands are protected by an owner/admin registry, log actions to an audit trail, and route callback-driven menus. A global webhook worker retries failed notifications, and the wildcard handler collects multi-step form input such as asset names.

Socialcryptoprivate-communityaccess-applicationadmin-panelaudit-lognotifications
ProfileTelegram
7 commands0 envUpdated 20d agoCreated Aug 17, 2026
Back to folder

commands/_handle_callback_query.js

javascript · 883 lines

Raw
1/**#command2name: /handle_callback_query3answer: 4keyboard: 5parse_mode: markdown6aliases: 7allow_only_group: false8need_reply: false9is_web: 010#command**/11 12/**#command13name: /handle_callback_query14answer:15keyboard:16parse_mode: markdown17aliases:18allow_only_group: false19need_reply: 020case_insensitive: true21is_web: 022#command**/23 24// ======================================================25// RED EYE CONSOLIDATED SHARED HELPERS26// ======================================================27function reNum(v, d){ let n=Number(v); return Number.isFinite(n)?n:(d||0); }28function reHtml(v){ return String(v==null?"":v).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"); }29function reNow(){ return Date.now(); }30async function reAudit(action,target,details,by){31  let logs=await db.bot.get("audit_logs",[]); if(!Array.isArray(logs))logs=[];32  logs.push({id:"AUD-"+Date.now()+"-"+Math.floor(Math.random()*100000),action:String(action||"event"),target_user_id:Number(target||0)||undefined,details:details||{},by:Number(by||0),at:Date.now()});33  await db.bot.set("audit_logs",logs.slice(-1000));34}35async function reNotify(payload,kind,target){36  try{let r=await Api.sendMessage(payload);if(r&&r.ok===false)throw new Error(String(r.description||"send_failed"));return true;}catch(e){let q=await db.bot.get("notification_retry_queue",[]);if(!Array.isArray(q))q=[];q.push({id:"NQ-"+Date.now()+"-"+Math.floor(Math.random()*100000),payload:payload,kind:String(kind||"notification"),target_user_id:Number(target||payload.chat_id||0),attempts:0,next_retry_at:Date.now()+5*60000,created_at:Date.now()});await db.bot.set("notification_retry_queue",q.slice(-500));return false;}37}38async function reSettings(){ let s=await db.bot.get("system_settings",{}); if(!s||typeof s!=="object")s={}; return s; }39function reDefaultNetworks(asset){40  asset=String(asset||"").toUpperCase();41  if(asset==="USDT")return ["TRON","ETHEREUM","SOLANA","TON"];42  if(asset==="ETH")return ["ETHEREUM"];43  if(asset==="BTC")return ["BITCOIN"];44  if(asset==="SOL")return ["SOLANA"];45  if(asset==="TON")return ["TON"];46  return ["MANUAL"];47}48async function reNetworksFor(asset){49  let s=await reSettings(); let map=s.asset_networks;50  if(map&&typeof map==="object"&&Array.isArray(map[String(asset||"").toUpperCase()])&&map[String(asset||"").toUpperCase()].length)return map[String(asset||"").toUpperCase()];51  return reDefaultNetworks(asset);52}53async function rePriceUSD(asset){54  asset=String(asset||"").toUpperCase();55  let paprika={BTC:"btc-bitcoin",ETH:"eth-ethereum",SOL:"sol-solana",TON:"ton-toncoin",USDT:"usdt-tether"};56  let gecko={BTC:"bitcoin",ETH:"ethereum",SOL:"solana",TON:"the-open-network",USDT:"tether"};57  if(!paprika[asset])return {ok:false,status:"manual_review",reason:"Unsupported automatic price asset"};58  try{let base=String((typeof process!=="undefined"&&process.env&&process.env.COINPAPRIKA_BASE_URL)||"https://api.coinpaprika.com/v1").replace(/\/+$/,""),r=await HTTP.get({url:base+"/tickers/"+encodeURIComponent(paprika[asset]),timeout:6500,responseType:"json"});let x=r&&r.ok&&r.data&&r.data.quotes&&r.data.quotes.USD?Number(r.data.quotes.USD.price):0;if(x>0)return {ok:true,price_usd:x,source:"coinpaprika"};}catch(e){}59  try{let id=gecko[asset],base=String((typeof process!=="undefined"&&process.env&&process.env.COINGECKO_BASE_URL)||"https://api.coingecko.com/api/v3").replace(/\/+$/,""),r=await HTTP.get({url:base+"/simple/price?ids="+encodeURIComponent(id)+"&vs_currencies=usd",timeout:6500,responseType:"json"});let x=r&&r.ok&&r.data&&r.data[id]?Number(r.data[id].usd):0;if(x>0)return {ok:true,price_usd:x,source:"coingecko"};}catch(e){}60  return {ok:false,status:"temporary_unavailable",reason:"Price providers unavailable"};61}62function reEvmAddress(a){return /^0x[a-fA-F0-9]{40}$/.test(String(a||"").trim());}63async function reBalance(wallet){64  let asset=String(wallet.asset||"").toUpperCase(),network=String(wallet.network||"").toUpperCase(),address=String(wallet.address||"").trim();65  if(!asset||!address)return {ok:false,status:"manual_review",reason:"Incomplete wallet"};66  if(asset==="BTC"||network.indexOf("BITCOIN")>=0){67    try{let base=String((typeof process!=="undefined"&&process.env&&process.env.MEMPOOL_API_URL)||"https://mempool.space/api").replace(/\/+$/,""),r=await HTTP.get({url:base+"/address/"+encodeURIComponent(address),timeout:7500,responseType:"json"});if(r&&r.ok&&r.data&&r.data.chain_stats){let st=r.data.chain_stats,b=(Number(st.funded_txo_sum||0)-Number(st.spent_txo_sum||0))/1e8;return {ok:true,balance:Math.max(0,b),source:"mempool.space"};}}catch(e){}68    return {ok:false,status:"temporary_unavailable",reason:"Bitcoin provider unavailable"};69  }70  if(asset==="ETH"&&(network.indexOf("ETH")>=0||network.indexOf("ERC")>=0)){71    if(!reEvmAddress(address))return {ok:false,status:"manual_review",reason:"Invalid EVM address"};72    let url=String((typeof process!=="undefined"&&process.env&&process.env.EVM_RPC_URL)||"https://cloudflare-eth.com");73    try{let r=await HTTP.post({url:url,timeout:7500,responseType:"json",body:{jsonrpc:"2.0",id:1,method:"eth_getBalance",params:[address,"latest"]}});let h=r&&r.ok&&r.data?String(r.data.result||""):"";if(/^0x[0-9a-fA-F]+$/.test(h)){let raw=Number(BigInt(h));return {ok:true,balance:raw/1e18,source:"evm_rpc"};}}catch(e){}74    return {ok:false,status:"temporary_unavailable",reason:"EVM provider unavailable"};75  }76  if(asset==="USDT"&&(network.indexOf("ETH")>=0||network.indexOf("ERC")>=0)){77    if(!reEvmAddress(address))return {ok:false,status:"manual_review",reason:"Invalid EVM address"};78    let url=String((typeof process!=="undefined"&&process.env&&process.env.EVM_RPC_URL)||"https://cloudflare-eth.com"),contract="0xdAC17F958D2ee523a2206206994597C13D831ec7",clean=address.slice(2).toLowerCase().padStart(64,"0");79    try{let r=await HTTP.post({url:url,timeout:7500,responseType:"json",body:{jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:contract,data:"0x70a08231"+clean},"latest"]}});let h=r&&r.ok&&r.data?String(r.data.result||""):"";if(/^0x[0-9a-fA-F]+$/.test(h)){let raw=Number(BigInt(h));return {ok:true,balance:raw/1e6,source:"erc20_rpc"};}}catch(e){}80    return {ok:false,status:"temporary_unavailable",reason:"USDT ERC20 provider unavailable"};81  }82  if(asset==="SOL"||network.indexOf("SOLANA")>=0){83    let url=String((typeof process!=="undefined"&&process.env&&process.env.SOLANA_RPC_URL)||"https://api.mainnet-beta.solana.com");84    try{let r=await HTTP.post({url:url,timeout:7500,responseType:"json",body:{jsonrpc:"2.0",id:1,method:"getBalance",params:[address]}});let v=r&&r.ok&&r.data&&r.data.result?Number(r.data.result.value):NaN;if(Number.isFinite(v))return {ok:true,balance:v/1e9,source:"solana_rpc"};}catch(e){}85    return {ok:false,status:"temporary_unavailable",reason:"Solana provider unavailable"};86  }87  if(asset==="TON"||network.indexOf("TON")>=0){88    let base=String((typeof process!=="undefined"&&process.env&&process.env.TONCENTER_API_URL)||"https://toncenter.com/api/v2").replace(/\/+$/,"");let key=String((typeof process!=="undefined"&&process.env&&process.env.TONCENTER_API_KEY)||"");let url=base+"/getAddressBalance?address="+encodeURIComponent(address)+(key?"&api_key="+encodeURIComponent(key):"");89    try{let r=await HTTP.get({url:url,timeout:7500,responseType:"json"});if(r&&r.ok&&r.data&&r.data.ok===true){let v=Number(r.data.result);if(Number.isFinite(v))return {ok:true,balance:v/1e9,source:"toncenter"};}}catch(e){}90    return {ok:false,status:"temporary_unavailable",reason:"TON provider unavailable"};91  }92  return {ok:false,status:"manual_review",reason:"Unsupported asset/network; manual review required"};93}94async function reVerifyWallet(wallet){95  let b=await reBalance(wallet); if(!b.ok)return {ok:false,status:b.status||"temporary_unavailable",reason:b.reason||"Provider unavailable",checked_at:Date.now()};96  let p=await rePriceUSD(wallet.asset); if(!p.ok)return {ok:false,status:p.status||"temporary_unavailable",reason:p.reason||"Pricing unavailable",balance:b.balance,balance_source:b.source,checked_at:Date.now()};97  return {ok:true,status:"verified",balance:b.balance,price_usd:p.price_usd,usd_value:b.balance*p.price_usd,balance_source:b.source,price_source:p.source,checked_at:Date.now()};98}99async function reVerifyWalletList(wallets){100  if(!Array.isArray(wallets))wallets=[];let out=[],total=0,auto=0,manual=0,temp=0;101  for(let w of wallets){let r=await reVerifyWallet(w||{}),n=Object.assign({},w||{},{auto_verification:r,verification_checked_at:Date.now()});if(r.ok){total+=Number(r.usd_value||0);auto++;}else if(r.status==="manual_review")manual++;else temp++;out.push(n);}102  return {wallets:out,total_usd:total,automatic_count:auto,manual_count:manual,temporary_count:temp,checked_at:Date.now()};103}104async function reAdminRecord(uid){105  let s=await reSettings(),owner=Number(s.owner_id||771142220);if(Number(uid)===owner)return {user_id:owner,role:"owner",revoked:false};106  let a=await db.bot.get("admin_registry",[]);if(!Array.isArray(a))a=[];return a.find(x=>x&&Number(x.user_id)===Number(uid)&&x.revoked!==true)||null;107}108function reRolePerms(role){109  let all=["dashboard","applications","review","approve","reject","more_info","override","members","wallets","reverify","alerts","blacklist","rules","settings","assets","p2p","announcements","analytics","admins","audit","backup","maintenance","system"];110  if(role==="owner"||role==="super_admin")return all;111  if(role==="verification_staff")return ["dashboard","applications","review","approve","reject","more_info","members","wallets","reverify","alerts","analytics"];112  if(role==="moderator")return ["dashboard","members","alerts","blacklist","rules","announcements","audit"];113  if(role==="support")return ["dashboard","applications","members"];114  return [];115}116async function reSessionOK(uid,role){117  let h=String(await db.user.get("staff_pin_hash","",{user_id:Number(uid)})||"");118  if(!h)return false;119  let until=Number(await db.user.get("staff_session_until",0,{user_id:Number(uid)})||0);return until>Date.now();120}121 122// ======================================================123// RED EYE PREMIUM UI LAYER124// ======================================================125function rePremiumKeyboard(kb){126  if(!Array.isArray(kb)) return kb;127  function styled(btn){128    if(!btn || typeof btn!=="object") return btn;129    let b=Object.assign({},btn);130    let t=String(b.text||"").toLowerCase();131    if(!b.style){132      if(/reject|delete|remove|blacklist|revoke|logout|cancel|under 18|disable|archive/.test(t)) b.style="danger";133      else if(/apply|continue|verify|approve|submit|confirm|save|done|join|enable|send|create|login|check/.test(t)) b.style="success";134      else if(/home|status|support|view|manage|settings|applications|members|wallet|rules|assets|analytics|audit|backup|network|admin|authentication|more info|re-verification|alerts/.test(t)) b.style="primary";135    }136    return b;137  }138  return kb.map(row=>Array.isArray(row)?row.map(styled):row);139}140 141async function userRouter(action) {142let uid = Number(user.telegramid || user.id);143let now = Date.now();144 145let s = await db.bot.get("system_settings", {});146if (!s || typeof s !== "object") s = {};147const OWNER_ID = Number(s.owner_id || 771142220);148const OFFICIAL_CHANNEL = String(s.official_channel || "@red_eye_official");149const OFFICIAL_CHANNEL_URL = String(s.official_channel_url || "https://t.me/red_eye_official");150const MIN_CRYPTO = Number(s.min_crypto_networth || 1000);151const MIN_DEALS = Number(s.min_deal_volume || 3000);152 153function ack(text, alert) {154  if (request && request.id) {155    Api.answerCallbackQuery({ callback_query_id: request.id, text: text || undefined, show_alert: !!alert });156  }157}158 159function edit(text, kb) {160  if (request && request.message) {161    return Api.editMessageText({162      chat_id: chat.id,163      message_id: request.message.message_id,164      text: text,165      parse_mode: "HTML",166      reply_markup: kb ? { inline_keyboard: rePremiumKeyboard(kb) } : undefined167    });168  }169  return Api.sendMessage({ chat_id: chat.id, text: text, parse_mode: "HTML", reply_markup: kb ? { inline_keyboard: rePremiumKeyboard(kb) } : undefined });170}171 172async function setStage(stage) {173  let t=Date.now();174  await db.user.set("application_stage", stage);175  await db.user.set("application_last_activity_at", t);176  let q=await db.bot.get("application_queue",[]);if(Array.isArray(q)){for(let x of q){if(x&&Number(x.user_id)===uid&&x.status==="started")x.last_activity_at=t;}await db.bot.set("application_queue",q);}177}178 179async function loadList(key) {180  let v = await db.user.get(key, []);181  return Array.isArray(v) ? v : [];182}183 184async function renderActivities() {185  let items = await loadList("activities");186  let defs = [["p2p","P2P"],["otc","Limited OTC"],["nft","NFT Gifts"],["networking","Crypto Networking"],["advertising","Advertising"]];187  let rows = defs.map(d => [{ text: (items.includes(d[0]) ? "✓ " : "○ ") + d[1], callback_data: "user_core activity:" + d[0] }]);188  rows.push([{ text: "Continue  →", callback_data: "user_core activity_done" }]);189  rows.push([{ text: "← Back", callback_data: "user_core age" }]);190  edit("💠 <b>STEP 4 • YOUR CRYPTO PROFILE</b>\n\nChoose every market you actively participate in.\n<i>You can select multiple options.</i>", rows);191}192 193async function renderAssets() {194  let items = await loadList("assets");195  let featured = s.featured_assets;196  if (!Array.isArray(featured) || !featured.length) featured = ["USDT","SOL","ETH","BTC","TON"];197  let rows = featured.map(a => [{ text: (items.includes(a) ? "✓ " : "○ ") + a, callback_data: "user_core asset:" + a }]);198  rows.push([{ text: "+ Other Cryptocurrency", callback_data: "user_core asset_other" }]);199  rows.push([{ text: "Continue  →", callback_data: "user_core asset_done" }]);200  rows.push([{ text: "← Back", callback_data: "user_core activities" }]);201  edit("💎 <b>STEP 5 • ASSETS TO VERIFY</b>\n\nSelect the assets you want counted toward your verified portfolio.\n<i>Multiple assets and wallets are supported.</i>", rows);202}203 204if (!action || action === "home") {205  Bot.runCommand("/start");206  return;207}208 209if (action === "support") {210  await db.user.set("input_mode", "support_message");211  edit(212    "💬 <b>RED EYE • PRIVATE SUPPORT</b>\n\nSend your message, screenshot or document in the next reply.\n\n<i>Your request goes directly to the support queue.</i>",213    [[{ text: "⌂ Main Menu", callback_data: "user_core home" }]]214  );215  return;216}217 218if (action === "apply") {219  let status = String(await db.user.get("application_status", ""));220  if (["submitted","under_review","more_info_required"].includes(status)) {221    ack("You already have an active application.", true);222    await userRouter("status");223    return;224  }225  if (status === "approved") {226    ack("Your application is already approved.", true);227    await userRouter("status");228    return;229  }230  let blacklist = await db.bot.get("blacklist", []); if (!Array.isArray(blacklist)) blacklist=[];231  if (status === "blacklisted" || blacklist.some(x=>x&&Number(x.user_id)===uid)) {232    await db.user.set("application_status","blacklisted");233    ack("Applications are unavailable for this account.", true);234    return;235  }236  if (status === "rejected") {237    let reapply = Number(await db.user.get("reapply_after", 0));238    if (reapply && now < reapply) {239      ack("Reapplication cooldown is still active.", true);240      return;241    }242  }243  if (s.maintenance_applications_paused === true) {244    ack("New applications are temporarily paused.", true);245    edit("🛠 <b>APPLICATIONS TEMPORARILY PAUSED</b>\n\n" + String(s.maintenance_message || "Please check again later."), [[{text:"⌂ Main Menu",callback_data:"user_core home"}]]);246    return;247  }248  // A re-application is a fresh application. Preserve history, but never silently reuse old answers/proofs.249  if (["rejected","abandoned","cancelled"].includes(status)) {250    let oldSnapshot={application_id:String(await db.user.get("application_id","")||""),status:status,activities:await loadList("activities"),assets:await loadList("assets"),wallets:await loadList("wallets"),ownership_proof:await db.user.get("ownership_proof",null),deal_proofs:await loadList("deal_proofs"),archived_at:now};251    let arch=await db.user.get("application_archives",[]);if(!Array.isArray(arch))arch=[];arch.push(oldSnapshot);await db.user.set("application_archives",arch.slice(-20));252    for (let k of ["activities","assets","wallets","ownership_proof","deal_proofs","membership_verified","premium_verified","username_verified","age_confirmed_18plus","application_id","application_stage","application_started_at","application_submitted_at","more_info_request","more_info_responses","admin_verified_crypto","admin_verified_deals","private_invite_link","auto_verified_crypto_total"]) await db.user.del(k);253    await reAudit("reapplication_fresh_draft",uid,{previous_status:status},uid);254  }255  await db.user.set("application_status", "started");256  let startedAt = Number(await db.user.get("application_started_at", 0)); if (!startedAt || ["rejected","abandoned","cancelled"].includes(status)) { startedAt=now; await db.user.set("application_started_at", now); }257  let q0=await db.bot.get("application_queue",[]);if(!Array.isArray(q0))q0=[];let qi=q0.findIndex(x=>x&&Number(x.user_id)===uid&&x.status==="started");let rec={application_id:String(await db.user.get("application_id","")||("DRAFT-"+uid)),user_id:uid,username:user.username||"",first_name:user.first_name||"",status:"started",started_at:startedAt,last_activity_at:now};if(qi>=0)q0[qi]=Object.assign({},q0[qi],rec);else q0.push(rec);await db.bot.set("application_queue",q0);258  await setStage("membership");259  edit(260    "🔐 <b>STEP 1 • VERIFY YOUR ACCESS</b>\n\nJoin the official RED EYE channel, then tap verification below.\n\n<i>This takes only a moment.</i>",261    [262      [{ text: "↗ Join Official Channel", url: OFFICIAL_CHANNEL_URL }],263      [{ text: "✓ Check Membership", callback_data: "user_core membership" }],264      [{ text: "⌂ Main Menu", callback_data: "user_core home" }]265    ]266  );267  return;268}269 270if (action === "membership") {271  ack();272  let r = await Api.call("getChatMember", { chat_id: OFFICIAL_CHANNEL, user_id: uid });273  if (!r || !r.ok) {274    edit("⚠️ <b>VERIFICATION TEMPORARILY UNAVAILABLE</b>\n\nMembership could not be checked right now. Please try again.", [[{text:"↻ Try Again",callback_data:"user_core membership"}],[{text:"← Back",callback_data:"user_core apply"}]]);275    return;276  }277  let st = r.result && r.result.status;278  let ok = ["member","administrator","creator"].includes(st);279  await db.user.set("membership_verified", ok);280  if (!ok) {281    edit("❌ <b>MEMBERSHIP NOT VERIFIED</b>\n\nJoin the official channel, then verify again.", [[{text:"↗ Join Channel",url:OFFICIAL_CHANNEL_URL}],[{text:"↻ Verify Again",callback_data:"user_core membership"}]]);282    return;283  }284  await db.user.set("membership_verified_at", now);285  await setStage("eligibility");286  edit("✅ <b>CHANNEL ACCESS VERIFIED</b>\n\nPerfect. Your official-channel membership is confirmed.\n\nNext: Telegram identity check.", [[{text:"Continue  →",callback_data:"user_core eligibility"}]]);287  return;288}289 290if (action === "eligibility") {291  let usernameOk = !!user.username;292  let premiumOk = user.is_premium === true;293  await db.user.set("username_verified", usernameOk);294  await db.user.set("premium_verified", premiumOk);295  let reqUsername = s.username_required !== false;296  let reqPremium = s.premium_required !== false;297  if ((reqUsername && !usernameOk) || (reqPremium && !premiumOk)) {298    let lines = [];299    if (reqUsername && !usernameOk) lines.push("• Public Telegram username is required.");300    if (reqPremium && !premiumOk) lines.push("• Telegram Premium is required.");301    edit("❌ <b>IDENTITY REQUIREMENTS NOT MET</b>\n\n" + lines.join("\n") + "\n\nFix the requirement and retry.", [[{text:"↻ Check Again",callback_data:"user_core eligibility"}],[{text:"⌂ Main Menu",callback_data:"user_core home"}]]);302    return;303  }304  if (s.age_required === false) { await db.user.set("age_confirmed_18plus", true); await setStage("activities"); edit("✅ <b>TELEGRAM IDENTITY VERIFIED</b>\n\nIdentity requirements are satisfied.", [[{text:"Continue  →",callback_data:"user_core activities"}]]); return; }305  await setStage("age");306  edit("✅ <b>IDENTITY VERIFIED</b>\n\nTelegram Premium and public username checks are complete.\n\nNext: age confirmation.", [[{text:"Continue  →",callback_data:"user_core age"}]]);307  return;308}309 310if (action === "age") {311  edit("🔞 <b>STEP 3 • AGE CONFIRMATION</b>\n\nYou must confirm that you are at least 18 years old to continue.", [[{text:"✓ I am 18+",callback_data:"user_core age_yes"}],[{text:"✕ I am under 18",callback_data:"user_core age_no"}]]);312  return;313}314if (action === "age_yes") {315  await db.user.set("age_confirmed_18plus", true);316  await setStage("activities");317  await renderActivities();318  return;319}320if (action === "age_no") {321  await db.user.set("age_confirmed_18plus", false);322  await db.user.set("application_status", "cancelled");323  let q=await db.bot.get("application_queue",[]);if(Array.isArray(q)){for(let x of q)if(x&&Number(x.user_id)===uid&&x.status==="started"){x.status="cancelled";x.cancelled_at=Date.now();}await db.bot.set("application_queue",q);}324  await reAudit("application_cancelled_under18",uid,{},uid);325  edit("⛔ <b>APPLICATION ENDED</b>\n\nRED EYE access is available only to users who confirm they are 18+.", [[{text:"⌂ Main Menu",callback_data:"user_core home"}]]);326  return;327}328 329if (action === "activities") { await renderActivities(); return; }330if (action.indexOf("activity:") === 0) {331  let key = action.split(":")[1];332  let items = await loadList("activities");333  if (items.includes(key)) items = items.filter(x => x !== key); else items.push(key);334  await db.user.set("activities", items);335  await renderActivities();336  return;337}338if (action === "activity_done") {339  let items = await loadList("activities");340  if (!items.length) { ack("Select at least one activity.", true); return; }341  await setStage("assets");342  await renderAssets();343  return;344}345 346if (action === "assets") { await renderAssets(); return; }347if (action.indexOf("asset:") === 0) {348  let key = action.slice(6).toUpperCase();349  let items = await loadList("assets");350  if (s.multiple_assets_allowed === false) { items = items.includes(key) ? [] : [key]; }351  else if (items.includes(key)) items = items.filter(x => x !== key); else items.push(key);352  await db.user.set("assets", items);353  await renderAssets();354  return;355}356if (action === "asset_other") {357  await db.user.set("input_mode", "other_asset_name");358  edit("+ <b>OTHER CRYPTOCURRENCY</b>\n\nSend the asset name/symbol as your next message. Example: <code>AVAX</code>.", [[{text:"← Back",callback_data:"user_core assets"}]]);359  return;360}361if (action === "asset_done") {362  let items = await loadList("assets");363  if (!items.length) { ack("Select at least one asset.", true); return; }364  await setStage("wallets");365  await userRouter("wallets");366  return;367}368 369if (action === "wallets") {370  let wallets = await loadList("wallets");371  let assets = await loadList("assets");372  let memberStatus=String(await db.user.get("member_status",""));let isMember=["active","approved_pending_join"].includes(memberStatus);373  if(isMember&&s.maintenance_wallet_changes_paused===true){edit("🛠 <b>WALLET CHANGES TEMPORARILY PAUSED</b>\n\nYour existing wallet history remains preserved. Please try again later.",[[{text:"‹ Status",callback_data:"user_core status"}]]);return;}374  let rows = assets.map(a => [{text:"+ Add " + a + " Wallet", callback_data:"user_core wallet_asset:" + a}]);375  if (wallets.length) rows.push([{text:"👛 View My Wallets (" + wallets.length + ")",callback_data:"user_core wallet_list"}]);376  if(isMember) rows.push([{text:"‹ Member Status",callback_data:"user_core status"}]);377  else {rows.push([{text:"Continue to Ownership Proof  ›",callback_data:"user_core ownership"}]);rows.push([{text:"← Back",callback_data:"user_core assets"}]);}378  edit(isMember?"👛 <b>MEMBER WALLET MANAGEMENT</b>\n\nAdd or archive public wallets here. Any wallet change remains pending for admin verification; historical wallets are retained.":"👛 <b>STEP 6 • WALLET VERIFICATION</b>\n\nAdd one or more public wallet addresses. Never send a seed phrase, private key or password.", rows);379  return;380}381if (action.indexOf("wallet_asset:") === 0) {382  let memberStatus=String(await db.user.get("member_status",""));if(["active","approved_pending_join"].includes(memberStatus)&&s.maintenance_wallet_changes_paused===true){ack("Wallet changes are temporarily frozen.",true);return;}383  let existingWallets=await loadList("wallets"); if(s.multiple_wallets_allowed===false && existingWallets.length>=1){ack("Only one wallet is currently allowed by admin settings.",true);return;}384  let asset = action.slice(13).toUpperCase();385  await db.user.set("current_wallet_asset", asset);386  let networks = await reNetworksFor(asset);387  let rows = networks.map(n => [{text:n, callback_data:"user_core wallet_network:" + n}]);388  rows.push([{text:"← Back",callback_data:"user_core wallets"}]);389  edit("🌐 <b>SELECT NETWORK</b>\n\nAsset: <b>" + asset + "</b>\nChoose the network for this wallet.", rows);390  return;391}392if (action.indexOf("wallet_network:") === 0) {393  let network = action.slice(15).toUpperCase();394  await db.user.set("current_wallet_network", network);395  await db.user.set("input_mode", "wallet_address");396  let asset = String(await db.user.get("current_wallet_asset", ""));397  edit("📋 <b>SEND PUBLIC WALLET ADDRESS</b>\n\nAsset: <b>" + asset + "</b>\nNetwork: <b>" + network + "</b>\n\nSend only the public address. <b>Never</b> send a seed phrase or private key.", [[{text:"‹ Cancel",callback_data:"user_core wallets"}]]);398  return;399}400if (action === "wallet_list") {401  let wallets = await loadList("wallets");402  if (!wallets.length) { edit("👛 <b>MY WALLETS</b>\n\nNo wallets added yet.", [[{text:"+ Add Wallet",callback_data:"user_core wallets"}]]); return; }403  let body = wallets.map((w,i) => { let av=w&&w.auto_verification?w.auto_verification:{}; let status=av.ok?("✅ $"+Number(av.usd_value||0).toFixed(2)):(av.status==="manual_review"?"🟠 Manual review":"🟡 Verification unavailable"); return (i+1)+". <b>"+reHtml(w.asset)+"</b> • "+reHtml(w.network)+"\n<code>"+reHtml(w.address)+"</code>\n"+status; }).join("\n\n");404  let total=Number(await db.user.get("auto_verified_crypto_total",0)||0);405  let rows=[[{text:"+ Add Another",callback_data:"user_core wallets"}]];406  for(let i=0;i<wallets.length;i++) rows.push([{text:"Archive Wallet #"+(i+1),callback_data:"user_core wallet_archive:"+i}]);407  rows.push([{text:"↻ Recheck Wallet Values",callback_data:"user_core wallet_recheck"}]);408  let memberStatus=String(await db.user.get("member_status",""));if(["active","approved_pending_join"].includes(memberStatus))rows.push([{text:"‹ Member Status",callback_data:"user_core status"}]);else rows.push([{text:"Continue  →",callback_data:"user_core ownership"}]);409  edit("👛 <b>MY WALLETS</b>\n\n"+body+"\n\nAutomatic verified total: <b>$"+total.toFixed(2)+"</b>\n<i>Unsupported or temporarily unavailable assets remain for manual admin review.</i>", rows);410  return;411}412 413if (action.indexOf("wallet_archive:")===0) {414  let s2=await reSettings(); if(s2.maintenance_wallet_changes_paused===true){ack("Wallet changes are temporarily frozen.",true);return;}415  let i=Number(action.split(":")[1]); let wallets=await loadList("wallets"); if(!wallets[i]){ack("Wallet not found.",true);return;}416  let history=await loadList("wallet_history"); history.push(Object.assign({},wallets[i],{archived_at:Date.now(),archived_reason:"user_change"})); await db.user.set("wallet_history",history.slice(-100));417  wallets.splice(i,1); await db.user.set("wallets",wallets); let vr=await reVerifyWalletList(wallets); await db.user.set("wallets",vr.wallets); await db.user.set("auto_verified_crypto_total",vr.total_usd); let ms=String(await db.user.get("member_status","")||"");if(["active","approved_pending_join"].includes(ms)){await db.user.set("wallet_change_pending",true);await db.user.set("reverification_status","requested");await db.user.set("reverification_type","wallet");let rr=await db.bot.get("reverification_requests",[]);if(!Array.isArray(rr))rr=[];if(!rr.some(x=>x&&Number(x.user_id)===uid&&!['completed','cancelled'].includes(String(x.status))&&x.reason==="wallet_change")){rr.push({id:"RV-WALLET-"+uid+"-"+Date.now(),user_id:uid,type:"wallet",reason:"wallet_change",status:"requested",requested_at:Date.now(),requested_by:"system"});await db.bot.set("reverification_requests",rr);}Api.sendMessage({chat_id:OWNER_ID,text:"👛 <b>MEMBER WALLET CHANGE</b>\n\nMember <code>"+uid+"</code> archived a wallet. History is retained and the wallet set is pending admin verification.",parse_mode:"HTML"});}await reAudit("wallet_archived",uid,{index:i,member_change:["active","approved_pending_join"].includes(ms)},uid); await userRouter("wallet_list"); return;418}419if (action === "wallet_recheck") {420  let wallets=await loadList("wallets"); if(!wallets.length){ack("No wallets to check.",true);return;} ack("Checking public balances…",false); let vr=await reVerifyWalletList(wallets); await db.user.set("wallets",vr.wallets); await db.user.set("auto_verified_crypto_total",vr.total_usd); await db.user.set("wallet_last_checked_at",Date.now()); await userRouter("wallet_list"); return;421}422 423if (action === "ownership") {424  let wallets = await loadList("wallets");425  if (!wallets.length) { ack("Add at least one wallet first.", true); return; }426  await db.user.set("input_mode", "ownership_proof");427  await setStage("ownership_proof");428  edit("🎥 <b>STEP 7 • OWNERSHIP PROOF</b>\n\nSend a screen recording/video or document showing your Telegram account context together with the relevant wallet/address context.\n\n<i>Never reveal a seed phrase or private key.</i>", [[{text:"← Back",callback_data:"user_core wallets"}]]);429  return;430}431if (action === "deal_proof") {432  await db.user.set("input_mode", "deal_proof");433  await setStage("deal_proof");434  let proofs = await loadList("deal_proofs");435  edit("📊 <b>STEP 8 • DEAL HISTORY PROOF</b>\n\nSend screenshot(s), document(s) or video(s) showing your relevant P2P/deal stats. Multiple proofs are allowed.\n\nCurrent received: <b>"+proofs.length+"</b>", [[{text:"✓ Finish Proof Upload",callback_data:"user_core summary"}],[{text:"← Back",callback_data:"user_core ownership"}]]);436  return;437}438 439if (action === "summary") {440  let [ownership,proofs,wallets,activities,assets,membership,premium,username,age] = await Promise.all([441    db.user.get("ownership_proof", null), db.user.get("deal_proofs", []), db.user.get("wallets", []),442    db.user.get("activities", []), db.user.get("assets", []), db.user.get("membership_verified", false),443    db.user.get("premium_verified", false), db.user.get("username_verified", false), db.user.get("age_confirmed_18plus", false)444  ]);445  if(!Array.isArray(proofs))proofs=[]; if(!Array.isArray(wallets))wallets=[]; if(!Array.isArray(activities))activities=[]; if(!Array.isArray(assets))assets=[];446  let complete = membership && (s.premium_required===false || premium) && (s.username_required===false || username) && (s.age_required===false || age) && activities.length && assets.length && wallets.length && ownership && proofs.length;447  await setStage("summary");448  edit(449    "🧾 <b>APPLICATION SUMMARY</b>\n\n"+450    "Channel: <b>"+(membership?"✓":"Pending")+"</b>\n"+451    "Premium: <b>"+(premium?"✓":"Pending")+"</b>\n"+452    "Username: <b>"+(username?"✓":"Pending")+"</b>\n"+453    "18+: <b>"+(age?"✓":"Pending")+"</b>\n"+454    "Activities: <b>"+activities.length+"</b>\nAssets: <b>"+assets.length+"</b>\nWallets: <b>"+wallets.length+"</b>\n"+455    "Ownership Proof: <b>"+(ownership?"Received":"Pending")+"</b>\nDeal Proofs: <b>"+proofs.length+"</b>\n\n"+456    (complete ? "Everything required for submission is present." : "Complete the pending items before submitting."),457    complete ? [[{text:"🚀 Submit Application",callback_data:"user_core submit"}],[{text:"← Back",callback_data:"user_core deal_proof"}]] : [[{text:"‹ Continue Application",callback_data:"user_core apply"}]]458  );459  return;460}461 462if (action === "submit") {463  let membership = await db.user.get("membership_verified", false);464  // Re-check official-channel membership at the final submission boundary.465  try{let cm=await Api.call("getChatMember",{chat_id:OFFICIAL_CHANNEL,user_id:uid});let st=cm&&cm.ok&&cm.result?String(cm.result.status||""):"";membership=["creator","administrator","member","restricted"].includes(st);await db.user.set("membership_verified",membership);}catch(e){membership=false;}466  let premium = await db.user.get("premium_verified", false);467  let username = await db.user.get("username_verified", false);468  let age = await db.user.get("age_confirmed_18plus", false);469  let activities = await loadList("activities"), assets = await loadList("assets"), wallets = await loadList("wallets"), proofs = await loadList("deal_proofs");470  let ownership = await db.user.get("ownership_proof", null);471  if (!(membership && (s.premium_required===false || premium) && (s.username_required===false || username) && (s.age_required===false || age) && activities.length && assets.length && wallets.length && ownership && proofs.length)) { ack("Application is incomplete.", true); return; }472  let appId = "RE-" + uid + "-" + now;473  await db.user.set("application_id", appId);474  await db.user.set("application_status", "submitted");475  await db.user.set("application_submitted_at", now);476  await db.user.set("application_stage", "submitted");477  let queue = await db.bot.get("application_queue", []); if (!Array.isArray(queue)) queue = [];478  queue = queue.filter(x => Number(x.user_id) !== uid || !["started","submitted","under_review","more_info_required"].includes(x.status));479  queue.push({ application_id: appId, user_id: uid, username: user.username || "", first_name: user.first_name || "", status: "submitted", submitted_at: now });480  await db.bot.set("application_queue", queue);481  let ah=await db.user.get("application_history",[]);if(!Array.isArray(ah))ah=[];ah.push({application_id:appId,status:"submitted",at:now,username:user.username||"",first_name:user.first_name||""});await db.user.set("application_history",ah.slice(-50));482  await reAudit("application_submitted",uid,{application_id:appId},uid);483  await reNotify({ chat_id: OWNER_ID, text: "📥 <b>NEW RED EYE APPLICATION</b>\n\nUser: "+(user.username?"@"+user.username:(user.first_name||"Unknown"))+"\nID: <code>"+uid+"</code>\nApplication: <code>"+appId+"</code>", parse_mode:"HTML", reply_markup:{inline_keyboard:[[{text:"🧿 Review Application",callback_data:"admin_core app:"+uid,style:"primary"}]]} },"new_application",OWNER_ID);484  edit("🚀 <b>APPLICATION SECURED & SUBMITTED</b>\n\nYour RED EYE application is now in the private review queue.\n\n<i>You can check live status anytime from /start.</i>", [[{text:"📡 Live Application Status",callback_data:"user_core status"}],[{text:"⌂ Main Menu",callback_data:"user_core home"}]]);485  return;486}487 488if (action === "status") {489  let [stRaw,reasonRaw,moreRaw,inviteRaw,rvRaw,rvTypeRaw,memberStatusRaw,membership,premium,uname,age,acts,assets,wallets,own,proofs,stageRaw] = await Promise.all([490    db.user.get("application_status", "not_started"), db.user.get("rejection_reason", ""), db.user.get("more_info_request", ""),491    db.user.get("private_invite_link", ""), db.user.get("reverification_status", ""), db.user.get("reverification_type", ""),492    db.user.get("member_status", ""), db.user.get("membership_verified",false), db.user.get("premium_verified",false),493    db.user.get("username_verified",false), db.user.get("age_confirmed_18plus",false), db.user.get("activities",[]),494    db.user.get("assets",[]), db.user.get("wallets",[]), db.user.get("ownership_proof",null), db.user.get("deal_proofs",[]),495    db.user.get("application_stage","")496  ]);497  let st=String(stRaw||"not_started"), reason=String(reasonRaw||""), more=String(moreRaw||""), invite=String(inviteRaw||"");498  let rv=String(rvRaw||""), rvType=String(rvTypeRaw||""), memberStatus=String(memberStatusRaw||""), stage=String(stageRaw||"");499  if(!Array.isArray(acts))acts=[]; if(!Array.isArray(assets))assets=[]; if(!Array.isArray(wallets))wallets=[]; if(!Array.isArray(proofs))proofs=[];500  let extra = "";501  if (st === "rejected" && reason) extra = "\n\nReason: " + reason;502  if (st === "more_info_required" && more) extra = "\n\nAdmin request: " + more;503  if (["requested","in_progress","submitted"].includes(rv)) extra += "\n\nRe-verification: <b>" + reHtml(rv.toUpperCase()) + " • " + reHtml(rvType.toUpperCase()) + "</b>";504  let rows = [];505  if (["requested","in_progress"].includes(rv)) rows.push([{text:"🔄 Continue Re-verification",callback_data:"user_core reverify_start"}]);506  if (st === "more_info_required") rows.push([{text:"📝 Provide Information",callback_data:"user_core more_info",style:"success"}]);507  if (st === "approved" && invite) rows.push([{text:"🔐 Join Private Community",url:invite}]);508  if(["active","approved_pending_join"].includes(memberStatus))rows.push([{text:"👛 Manage Wallets",callback_data:"user_core wallets"}]);509  if (["not_started","cancelled","abandoned","rejected"].includes(st)) rows.push([{text:"✦ Apply for Private Access",callback_data:"user_core apply"}]);510  rows.push([{text:"⌂ Main Menu",callback_data:"user_core home"}]);511  let sec="\n\n<b>Verification progress</b>\n"+"Channel: "+(membership?"✅":"⏳")+"\n"+"Premium: "+((s.premium_required===false||premium)?"✅":"⏳")+"\n"+"Username: "+((s.username_required===false||uname)?"✅":"⏳")+"\n"+"18+: "+((s.age_required===false||age)?"✅":"⏳")+"\n"+"Activities: "+(acts.length?"✅":"⏳")+"\nAssets: "+(assets.length?"✅":"⏳")+"\nWallets: "+(wallets.length?"✅":"⏳")+"\nOwnership proof: "+(own?"✅":"⏳")+"\nDeal proof: "+(proofs.length?"✅":"⏳");512  let displayStatus=(st==="started"&&stage&&stage!=="membership")?"IN PROGRESS":st.split("_").join(" ").toUpperCase();513  edit("📡 <b>APPLICATION STATUS • LIVE</b>\n\nCurrent status: <b>"+displayStatus+"</b>"+extra+sec, rows);514  return;515}516 517if (action === "reverify_start") {518  let rv=String(await db.user.get("reverification_status","")),type=String(await db.user.get("reverification_type","full"));519  if(!["requested","in_progress"].includes(rv)){ack("No active re-verification request.",true);return;}520  if(s.maintenance_reverification_paused===true){edit("🛠 <b>RE-VERIFICATION TEMPORARILY PAUSED</b>\n\nPlease try again later.",[[{text:"‹ Status",callback_data:"user_core status"}]]);return;}521  await db.user.set("reverification_status","in_progress");522  let rows=[];523  if(type==="wallet"||type==="full")rows.push([{text:"👛 Update / Recheck Wallets",callback_data:"user_core wallets"}]);524  if(type==="deals"||type==="full")rows.push([{text:"📊 Upload Deal Proof",callback_data:"user_core reverify_deals"}]);525  if(type==="ownership"||type==="full")rows.push([{text:"🎥 Upload Ownership Proof",callback_data:"user_core reverify_ownership"}]);526  rows.push([{text:"✅ Submit Re-verification",callback_data:"user_core reverify_submit"}]); rows.push([{text:"‹ Status",callback_data:"user_core status"}]);527  edit("🔄 <b>RE-VERIFICATION</b>\n\nRequested type: <b>"+reHtml(type.toUpperCase())+"</b>\nComplete the required updated evidence, then submit.",rows);return;528}529if (action === "reverify_deals") { await db.user.set("input_mode","reverify_deal_proof"); let p=await loadList("reverify_deal_proofs"); edit("📊 <b>RE-VERIFICATION • DEAL HISTORY</b>\n\nSend updated screenshot(s), video(s) or document(s). Received: <b>"+p.length+"</b>",[[{text:"✅ Done",callback_data:"user_core reverify_start"}]]);return; }530if (action === "reverify_ownership") { await db.user.set("input_mode","reverify_ownership_proof"); edit("🎥 <b>RE-VERIFICATION • OWNERSHIP PROOF</b>\n\nSend a new screen recording/video or document showing Telegram identity and wallet context.",[[{text:"← Back",callback_data:"user_core reverify_start"}]]);return; }531if (action === "reverify_submit") {532  let type=String(await db.user.get("reverification_type","full")),wallets=await loadList("wallets"),dp=await loadList("reverify_deal_proofs"),op=await db.user.get("reverify_ownership_proof",null);533  if((type==="wallet"||type==="full")&&!wallets.length){ack("At least one wallet is required.",true);return;}534  if((type==="deals"||type==="full")&&!dp.length){ack("Updated deal proof is required.",true);return;}535  if((type==="ownership"||type==="full")&&!op){ack("Updated ownership proof is required.",true);return;}536  await db.user.set("reverification_status","submitted"); await db.user.set("reverification_submitted_at",Date.now());537  let rr=await db.bot.get("reverification_requests",[]);if(!Array.isArray(rr))rr=[];for(let x of rr){if(x&&Number(x.user_id)===uid&&!['completed','cancelled'].includes(String(x.status))){x.status="submitted";x.submitted_at=Date.now();}}await db.bot.set("reverification_requests",rr);538  await reAudit("reverification_submitted",uid,{type:type},uid); Api.sendMessage({chat_id:OWNER_ID,text:"🔄 <b>RE-VERIFICATION SUBMITTED</b>\n\nUser: <code>"+uid+"</code>\nType: <b>"+reHtml(type.toUpperCase())+"</b>",parse_mode:"HTML",reply_markup:{inline_keyboard:[[{text:"🧿 Review Member",callback_data:"admin_core member:"+uid,style:"primary"}]]}}); edit("✅ <b>RE-VERIFICATION SUBMITTED</b>\n\nYour updated evidence is awaiting admin review.",[[{text:"📡 Live Status",callback_data:"user_core status",style:"primary"}]]);return;539}540 541if (action === "more_info") {542  await db.user.set("input_mode", "more_info_response");543  edit("📝 <b>PROVIDE ADDITIONAL INFORMATION</b>\n\nSend the requested information as your next message. Text, photo, video or document is accepted.", [[{text:"‹ Status",callback_data:"user_core status"}]]);544  return;545}546 547ack("Unknown action.", false);548 549}550 551async function adminRouter(action) {552let s = await db.bot.get("system_settings", {}); if (!s || typeof s !== "object") s = {};553const OWNER_ID = Number(s.owner_id || 771142220);554const PRIVATE_GROUP_ID = Number(s.private_group_id || -1004382007648);555const uid = (typeof user !== "undefined" && user) ? Number(user.telegramid || user.id) : 0;556 557function ack(text, alert) { if (request && request.id) Api.answerCallbackQuery({callback_query_id:request.id,text:text||undefined,show_alert:!!alert}); }558function show(text, kb) {559  if (request && request.message) return Api.editMessageText({chat_id:chat.id,message_id:request.message.message_id,text:text,parse_mode:"HTML",reply_markup:kb?{inline_keyboard:rePremiumKeyboard(kb)}:undefined});560  return Api.sendMessage({chat_id:chat.id,text:text,parse_mode:"HTML",reply_markup:kb?{inline_keyboard:rePremiumKeyboard(kb)}:undefined});561}562 563let adminRecord=await reAdminRecord(uid); if(!adminRecord){ if(uid) Api.sendMessage({chat_id:chat.id,text:"⛔ Admin access denied."}); return; }564let adminRole=String(adminRecord.role||"support"), adminPerms=reRolePerms(adminRole);565function hasPerm(p){return adminPerms.includes(p);}566let authActions=["auth","auth_setpin","auth_login","auth_logout"];567let sessionOK=await reSessionOK(uid,adminRole);568if(!sessionOK && !authActions.includes(action||"")){569  show("🔐 <b>STAFF AUTHENTICATION REQUIRED</b>\n\nYour Telegram identity is authorized, but a valid second-factor session is required.",[[{text:"🔑 Login",callback_data:"admin_core auth_login"}],[{text:"⚙ Authentication",callback_data:"admin_core auth"}]]);return;570}571if (action === "auth") { let hash=String(await db.user.get("staff_pin_hash","")||""); let until=Number(await db.user.get("staff_session_until",0)||0); show("🔐 <b>STAFF AUTHENTICATION</b>\n\nRole: <b>"+reHtml(adminRole)+"</b>\nPIN configured: <b>"+(hash?"YES":"NO")+"</b>\nSession: <b>"+(until>Date.now()?"ACTIVE":"LOCKED")+"</b>",[[{text:hash?"🔄 Change PIN":"➕ Set PIN",callback_data:"admin_core auth_setpin"}],[{text:until>Date.now()?"🚪 Logout":"🔑 Login",callback_data:until>Date.now()?"admin_core auth_logout":"admin_core auth_login"}],[{text:"‹ Admin Home",callback_data:"admin_core home"}]]);return; }572if (action === "auth_setpin") { let hash=String(await db.user.get("staff_pin_hash","")||"");let active=Number(await db.user.get("staff_session_until",0)||0)>Date.now();if(hash&&!active){ack("Login with your current PIN before changing it.",true);await adminRouter("auth");return;}await db.user.set("input_mode","staff_set_pin"); show("🔐 <b>SET STAFF PIN</b>\n\nSend a new 6–12 digit PIN. It will be stored using bcrypt hashing.",[[{text:"‹ Authentication",callback_data:"admin_core auth"}]]);return; }573if (action === "auth_login") { let lock=Number(await db.user.get("staff_auth_lock_until",0)||0); if(lock>Date.now()){ack("Login temporarily locked after failed attempts.",true);return;} let hash=String(await db.user.get("staff_pin_hash","")||""); if(!hash){ack("Set a staff PIN first.",true);await adminRouter("auth");return;} await db.user.set("input_mode","staff_login_pin"); show("🔑 <b>STAFF LOGIN</b>\n\nSend your staff PIN as the next message.",[[{text:"‹ Authentication",callback_data:"admin_core auth"}]]);return; }574if (action === "auth_logout") { await db.user.del("staff_session_until"); await reAudit("staff_logout",uid,{role:adminRole},uid); await adminRouter("auth");return; }575 576function actionPerm(a){577  a=String(a||"home");578  if(a==="home"||a.startsWith("auth"))return "dashboard";579  if(a==="applications"||a.startsWith("app:"))return "applications";580  if(a.startsWith("approve:"))return "approve";581  if(a.startsWith("reject"))return "reject";582  if(a.startsWith("moreinfo")||a.startsWith("message:"))return "more_info";583  if(a.startsWith("override"))return "override";584  if(a==="members"||a.startsWith("member:")||a.startsWith("note:"))return "members";585  if(a.startsWith("reverify")||a==="reverifications")return "reverify";586  if(a==="blacklist"||a.startsWith("blacklist")||a.startsWith("unblacklist"))return "blacklist";587  if(a.startsWith("rule")||a==="rules")return "rules";588  if(a==="settings"||a.startsWith("setting:")||a.startsWith("toggle:"))return "settings";589  if(a==="assets"||a.startsWith("asset_")||a==="networks"||a.startsWith("network_"))return "assets";590  if(a==="p2p"||a.startsWith("p2p_"))return "p2p";591  if(a.startsWith("announcement")||a==="announcements")return "announcements";592  if(a==="alerts"||a.startsWith("alert_")||a.startsWith("risk_"))return "alerts";593  if(a.startsWith("maintenance")||a.startsWith("mt_"))return "maintenance";594  if(a==="analytics")return "analytics";595  if(a==="audit")return "audit";596  if(a==="backup"||a.startsWith("backup_")||a.startsWith("export_"))return "backup";597  if(a==="monitor_scan"||a==="wallets_admin"||a.startsWith("wallet_user:")||a.startsWith("evidence:")||a.startsWith("setcrypto:")||a.startsWith("setdeals:"))return "wallets";598  if(a==="admins"||a.startsWith("admin_"))return "admins";599  if(a==="system"||a.startsWith("system_")||a==="provider_test"||a==="production_check"||a==="worker_webhook")return "system";600  if(a==="lifecycle_scan")return "system";601  return "dashboard";602}603let __need=actionPerm(action);if(__need&&!hasPerm(__need)){ack("Your admin role does not allow this action.",true);return;}604 605if (!action || action === "home") {606  let [q,members,alerts,reverify] = await Promise.all([607    db.bot.get("application_queue", []), db.bot.get("member_registry", []),608    db.bot.get("alerts", []), db.bot.get("reverification_requests", [])609  ]);610  if (!Array.isArray(q)) q=[]; if (!Array.isArray(members)) members=[];611  if (!Array.isArray(alerts)) alerts=[]; if (!Array.isArray(reverify)) reverify=[];612  let pending = q.filter(x=>x && ["submitted","under_review","more_info_required"].includes(x.status)).length;613  let openAlerts = alerts.filter(x=>x && x.status!=="resolved").length;614  let openReverify = reverify.filter(x=>x && x.status!=="completed" && x.status!=="cancelled").length;615  show("🛡️ <b>RED EYE • COMMAND CENTER</b>\n\nPending applications: <b>"+pending+"</b>\nActive members: <b>"+members.filter(x=>x&&x.status!=="removed").length+"</b>\nOpen alerts: <b>"+openAlerts+"</b>\nRe-verifications: <b>"+openReverify+"</b>\n\nEligibility: <b>$"+Number(s.min_crypto_networth||1000)+" crypto / $"+Number(s.min_deal_volume||3000)+" deals</b>", [616    [{text:"📥 Applications ("+pending+")",callback_data:"admin_core applications"},{text:"👥 Members",callback_data:"admin_core members"}],617    [{text:"👛 Wallets",callback_data:"admin_core wallets_admin"},{text:"🔄 Re-verification",callback_data:"admin_core reverifications"}],618    [{text:"🚨 Alerts ("+openAlerts+")",callback_data:"admin_core alerts"},{text:"🚫 Blacklist",callback_data:"admin_core blacklist"}],619    [{text:"📜 Rules",callback_data:"admin_core rules"},{text:"🪙 Assets",callback_data:"admin_core assets"}],620    [{text:"📣 Announcements",callback_data:"admin_core announcements"},{text:"📊 Analytics",callback_data:"admin_core analytics"}],621    [{text:"⚙ Eligibility Settings",callback_data:"admin_core settings"},{text:"🛠 Maintenance",callback_data:"admin_core maintenance_page"}],622    [{text:"🧾 Audit Logs",callback_data:"admin_core audit"},{text:"💾 Backup / Export",callback_data:"admin_core backup"}],623    [{text:"⌛ Lifecycle Scan",callback_data:"admin_core lifecycle_scan"},{text:"👛 Wallet Monitoring",callback_data:"admin_core monitor_scan"}],624    [{text:"🌐 Networks",callback_data:"admin_core networks"},{text:"🔗 P2P Group Manager",callback_data:"admin_core p2p"}],625    [{text:"👮 Admins & Roles",callback_data:"admin_core admins"},{text:"🔐 Authentication",callback_data:"admin_core auth"}],626    [{text:"⚙ System Settings",callback_data:"admin_core system"}]627  ]);628  return;629}630 631if (action === "applications") {632  let q = await db.bot.get("application_queue", []); if (!Array.isArray(q)) q=[];633  let pending = q.filter(x=>x && ["submitted","under_review","more_info_required"].includes(x.status)).slice(-20).reverse();634  let rows = pending.map(x=>[{text:(x.first_name||x.username||String(x.user_id))+" • "+x.status,callback_data:"admin_core app:"+x.user_id}]);635  rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);636  show("📥 <b>APPLICATION CONTROL • REVIEW QUEUE</b>\n\nSelect an applicant to open the full verification file.", rows);637  return;638}639 640if (action.indexOf("app:") === 0) {641  let target = Number(action.split(":")[1]); if (!target) {ack("Invalid applicant",true);return;}642  await db.user.set("admin_selected_user", target);643  let [stRaw,acts,assets,wallets,proofs,own,cRaw,dRaw] = await Promise.all([644    db.user.get("application_status","",{user_id:target}), db.user.get("activities",[],{user_id:target}),645    db.user.get("assets",[],{user_id:target}), db.user.get("wallets",[],{user_id:target}),646    db.user.get("deal_proofs",[],{user_id:target}), db.user.get("ownership_proof",null,{user_id:target}),647    db.user.get("admin_verified_crypto",0,{user_id:target}), db.user.get("admin_verified_deals",0,{user_id:target})648  ]);649  let st=String(stRaw||""); if(!Array.isArray(acts)) acts=[]; if(!Array.isArray(assets)) assets=[];650  if(!Array.isArray(wallets)) wallets=[]; if(!Array.isArray(proofs)) proofs=[]; let c=Number(cRaw||0), d=Number(dRaw||0);651  await db.user.set("application_status", st === "submitted" ? "under_review" : st, {user_id:target});652  let q=await db.bot.get("application_queue",[]);if(Array.isArray(q)){for(let x of q)if(Number(x.user_id)===target&&x.status==="submitted")x.status="under_review";await db.bot.set("application_queue",q);}653  show("🧿 <b>APPLICATION INTELLIGENCE • REVIEW</b>\n\nUser ID: <code>"+target+"</code>\nStatus: <b>"+st+"</b>\nActivities: <b>"+acts.join(", ")+"</b>\nAssets: <b>"+assets.join(", ")+"</b>\nWallets: <b>"+wallets.length+"</b>\nOwnership proof: <b>"+(own?"Received":"Missing")+"</b>\nDeal proofs: <b>"+proofs.length+"</b>\n\nVerified crypto: <b>$"+c+"</b>\nVerified deals: <b>$"+d+"</b>", [654    [{text:"💰 Set Verified Crypto",callback_data:"admin_core setcrypto:"+target},{text:"📊 Set Verified Deals",callback_data:"admin_core setdeals:"+target}],655    [{text:"✅ Approve",callback_data:"admin_core approve:"+target},{text:"❌ Reject",callback_data:"admin_core reject:"+target}],656    [{text:"⚠ Reject Failed Criteria",callback_data:"admin_core reject_auto:"+target},{text:"✉ Message Applicant",callback_data:"admin_core message:"+target}],657    [{text:"📝 Request More Info",callback_data:"admin_core moreinfo:"+target},{text:"👛 Wallets / Proofs",callback_data:"admin_core evidence:"+target}],658    [{text:"⚡ Admin Override",callback_data:"admin_core override:"+target},{text:"🚫 Blacklist",callback_data:"admin_core blacklist_user:"+target}],659    [{text:"‹ Applications",callback_data:"admin_core applications"}]660  ]);661  return;662}663 664if (action.indexOf("setcrypto:")===0 || action.indexOf("setdeals:")===0) {665  let target=Number(action.split(":")[1]); await db.user.set("admin_selected_user",target); await db.user.set("input_mode",action.startsWith("setcrypto")?"admin_set_crypto":"admin_set_deals");666  show(action.startsWith("setcrypto")?"💰 <b>VERIFIED CRYPTO VALUE</b>\n\nSend the verified USD value as your next message.":"📊 <b>VERIFIED DEAL VOLUME</b>\n\nSend the verified total USD deal volume as your next message.", [[{text:"← Back",callback_data:"admin_core app:"+target}]]);667  return;668}669 670if (action.indexOf("approve:")===0) {671  let target=Number(action.split(":")[1]);672  let c=Number(await db.user.get("admin_verified_crypto",0,{user_id:target})||0), d=Number(await db.user.get("admin_verified_deals",0,{user_id:target})||0);673  let minC=Number(s.min_crypto_networth||1000), minD=Number(s.min_deal_volume||3000);674  if(c<minC){ack("Verified crypto must be at least $"+minC,true);return;} if(d<minD){ack("Verified deals must be at least $"+minD,true);return;}675  let old=String(await db.user.get("private_invite_link","",{user_id:target})); if(old){try{await Api.call("revokeChatInviteLink",{chat_id:PRIVATE_GROUP_ID,invite_link:old});}catch(e){}}676  let exp=Math.floor(Date.now()/1000)+3600;677  let r=await Api.call("createChatInviteLink",{chat_id:PRIVATE_GROUP_ID,name:"RED EYE • "+target,expire_date:exp,creates_join_request:true});678  if(!r||!r.ok||!r.result||!r.result.invite_link){ack("Could not create secure invite link.",true);return;}679  let link=r.result.invite_link;680  await db.user.set("application_status","approved",{user_id:target}); await db.user.set("approved_at",Date.now(),{user_id:target}); await db.user.set("approved_by",uid,{user_id:target}); await db.user.set("private_invite_link",link,{user_id:target});681  let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];682  let mi=members.findIndex(x=>x&&Number(x.user_id)===target);683  let prof=await db.user.get("telegram_profile",{}, {user_id:target});if(!prof||typeof prof!=="object")prof={};684  let memberRecord={user_id:target,username:prof.username||"",first_name:prof.first_name||"",status:"approved_pending_join",approved_at:Date.now(),verified_at:Date.now(),verified_crypto:c,verified_deals:d,updated_at:Date.now()};685  if(mi>=0) members[mi]=Object.assign({},members[mi],memberRecord); else members.push(memberRecord);686  await db.bot.set("member_registry",members);687  await db.user.set("member_status","approved_pending_join",{user_id:target});688  let invites=await db.bot.get("secure_invites",[]);if(!Array.isArray(invites))invites=[];invites.push({user_id:target,invite_link:link,expires_at:exp,used:false,created_at:Date.now()});await db.bot.set("secure_invites",invites);689  let q=await db.bot.get("application_queue",[]);if(Array.isArray(q)){for(let x of q)if(Number(x.user_id)===target){x.status="approved";x.reviewed_at=Date.now();x.reviewed_by=uid;}await db.bot.set("application_queue",q);}690  let ah2=await db.user.get("application_history",[],{user_id:target});if(!Array.isArray(ah2))ah2=[];ah2.push({application_id:String(await db.user.get("application_id","",{user_id:target})),status:"approved",at:Date.now(),by:uid});await db.user.set("application_history",ah2.slice(-50),{user_id:target});691  let vh2=await db.user.get("verification_history",[],{user_id:target});if(!Array.isArray(vh2))vh2=[];vh2.push({type:"initial",status:"approved",verified_crypto:c,verified_deals:d,at:Date.now(),by:uid});await db.user.set("verification_history",vh2.slice(-100),{user_id:target});692  await reAudit("application_approved",target,{verified_crypto:c,verified_deals:d},uid);693  await reNotify({chat_id:target,text:"✅ <b>APPLICATION APPROVED</b>\n\nYour RED EYE application has been approved. This private access link is authorized only for your Telegram account and expires in 1 hour.",parse_mode:"HTML",reply_markup:{inline_keyboard:[[{text:"🔐 Enter Private Community",url:link,style:"success"}],[{text:"📡 Live Status",callback_data:"user_core status",style:"primary"}]]}},"application_approved",target);694  ack("Approved and secure invite created.",false); Bot.runCommand("/handle_callback_query",{route:"admin_core app:"+target}); return;695}696 697if(action.indexOf("reject_auto:")===0){let target=Number(action.split(":")[1]),reasons=[];let c=Number(await db.user.get("admin_verified_crypto",0,{user_id:target})||0),d=Number(await db.user.get("admin_verified_deals",0,{user_id:target})||0),minC=Number(s.min_crypto_networth||1000),minD=Number(s.min_deal_volume||3000);if(c<minC)reasons.push("Verified crypto value is below $"+minC+".");if(d<minD)reasons.push("Verified deal volume is below $"+minD+".");let own=await db.user.get("ownership_proof",null,{user_id:target}),proofs=await db.user.get("deal_proofs",[],{user_id:target});if(!own)reasons.push("Wallet ownership proof is missing.");if(!Array.isArray(proofs)||!proofs.length)reasons.push("Deal-history proof is missing.");if(!reasons.length){ack("No failed automatic criterion is currently recorded. Use custom rejection if needed.",true);return;}await adminRouter("reject_do:"+target+":"+encodeURIComponent(reasons.join(" ")));return;}698if(action.indexOf("message:")===0){let target=Number(action.split(":")[1]);await db.user.set("admin_selected_user",target);await db.user.set("input_mode","admin_custom_message");show("✉ <b>MESSAGE APPLICANT</b>\n\nSend the custom message as your next message.",[[{text:"‹ Cancel",callback_data:"admin_core app:"+target}]]);return;}699if (action.indexOf("reject:")===0) { let target=Number(action.split(":")[1]);await db.user.set("admin_selected_user",target);await db.user.set("input_mode","admin_reject_reason");show("❌ <b>REJECTION REASON</b>\n\nSend the reason as your next message.",[[{text:"‹ Cancel",callback_data:"admin_core app:"+target}]]);return; }700if (action.indexOf("reject_do:")===0) {701  let p=action.split(":"),target=Number(p[1]),reason=decodeURIComponent(p.slice(2).join(":"));702  let count=Number(await db.user.get("rejection_count",0,{user_id:target})||0)+1; let hours=count>=5?Number(s.extended_cooldown_hours||24):Number(s.rejection_cooldown_hours||1); let reapply=Date.now()+hours*3600000;703  await db.user.set("application_status","rejected",{user_id:target});await db.user.set("rejection_reason",reason,{user_id:target});await db.user.set("rejection_count",count,{user_id:target});await db.user.set("rejected_at",Date.now(),{user_id:target});await db.user.set("reapply_after",reapply,{user_id:target});704  let q=await db.bot.get("application_queue",[]);if(Array.isArray(q)){for(let x of q)if(Number(x.user_id)===target){x.status="rejected";x.reviewed_at=Date.now();x.reviewed_by=uid;}await db.bot.set("application_queue",q);}705  let ah=await db.user.get("application_history",[],{user_id:target});if(!Array.isArray(ah))ah=[];ah.push({application_id:String(await db.user.get("application_id","",{user_id:target})),status:"rejected",reason:reason,at:Date.now(),by:uid});await db.user.set("application_history",ah.slice(-50),{user_id:target});await reAudit("application_rejected",target,{reason:reason,cooldown_hours:hours,rejection_count:count},uid);706  await reNotify({chat_id:target,text:"❌ <b>APPLICATION REJECTED</b>\n\nReason: "+reHtml(reason)+"\n\nReapply cooldown: <b>"+hours+" hour(s)</b>.",parse_mode:"HTML"},"application_rejected",target);707  await adminRouter("applications");return;708}709 710if (action.indexOf("moreinfo:")===0) {let target=Number(action.split(":")[1]);await db.user.set("admin_selected_user",target);await db.user.set("input_mode","admin_more_info");show("📝 <b>REQUEST MORE INFORMATION</b>\n\nSend the exact message/question for the applicant.",[[{text:"‹ Cancel",callback_data:"admin_core app:"+target}]]);return;}711if (action.indexOf("moreinfo_do:")===0) {712  let p=action.split(":"),target=Number(p[1]),msg=decodeURIComponent(p.slice(2).join(":"));713  await db.user.set("application_status","more_info_required",{user_id:target});await db.user.set("more_info_request",msg,{user_id:target});await db.user.set("more_info_requested_at",Date.now(),{user_id:target});714  let q=await db.bot.get("application_queue",[]);if(Array.isArray(q)){for(let x of q)if(Number(x.user_id)===target)x.status="more_info_required";await db.bot.set("application_queue",q);}715  let ah=await db.user.get("application_history",[],{user_id:target});if(!Array.isArray(ah))ah=[];ah.push({application_id:String(await db.user.get("application_id","",{user_id:target})),status:"more_info_required",message:msg,at:Date.now(),by:uid});await db.user.set("application_history",ah.slice(-50),{user_id:target});await reAudit("application_more_info_requested",target,{message:msg},uid);716  await reNotify({chat_id:target,text:"📝 <b>MORE INFORMATION REQUIRED</b>\n\n"+reHtml(msg),parse_mode:"HTML",reply_markup:{inline_keyboard:[[{text:"📝 Provide Information",callback_data:"user_core more_info",style:"success"}],[{text:"📡 Live Status",callback_data:"user_core status",style:"primary"}]]}},"more_info_required",target);717  Bot.runCommand("/handle_callback_query",{route:"admin_core app:"+target});return;718}719 720if (action === "settings") {721  if(!hasPerm("settings")){ack("Permission denied.",true);return;}722  let defs=[723    ["Minimum Crypto","min_crypto_networth",s.min_crypto_networth||1000],["Minimum Deals","min_deal_volume",s.min_deal_volume||3000],724    ["Low Wallet Threshold","low_wallet_threshold",s.low_wallet_threshold||500],["Low Wallet Clear","low_wallet_clear_threshold",s.low_wallet_clear_threshold||600],["Low Wallet Days","low_wallet_duration_days",s.low_wallet_duration_days||7],725    ["Normal Cooldown Hours","rejection_cooldown_hours",s.rejection_cooldown_hours||1],["Extended Cooldown Hours","extended_cooldown_hours",s.extended_cooldown_hours||24],726    ["Reminder Minutes","application_reminder_minutes",s.application_reminder_minutes||60],["Expiry Hours","application_expiry_hours",s.application_expiry_hours||24],["Verification Expiry Days","verification_expiry_days",s.verification_expiry_days||30]727  ];728  let rows=defs.map(d=>[{text:d[0]+": "+d[2],callback_data:"admin_core setting:"+d[1]}]);729  rows.push([{text:"Premium: "+(s.premium_required===false?"OFF":"ON"),callback_data:"admin_core toggle:premium_required"},{text:"Username: "+(s.username_required===false?"OFF":"ON"),callback_data:"admin_core toggle:username_required"}]);730  rows.push([{text:"18+: "+(s.age_required===false?"OFF":"ON"),callback_data:"admin_core toggle:age_required"},{text:"Multi Wallets: "+(s.multiple_wallets_allowed===false?"OFF":"ON"),callback_data:"admin_core toggle:multiple_wallets_allowed"}]);731  rows.push([{text:"Multi Assets: "+(s.multiple_assets_allowed===false?"OFF":"ON"),callback_data:"admin_core toggle:multiple_assets_allowed"},{text:"Verification Expiry: "+(s.verification_expiry_enabled===true?"ON":"OFF"),callback_data:"admin_core toggle:verification_expiry_enabled"}]);732  rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);733  show("⚙ <b>ELIGIBILITY & LIFECYCLE SETTINGS</b>\n\nAll important thresholds and requirements are database-configurable.",rows);return;734}735if (action.indexOf("setting:")===0){if(!hasPerm("settings")){ack("Permission denied.",true);return;}let key=action.slice(8);await db.user.set("input_mode","admin_setting_"+key);show("⚙ <b>UPDATE SETTING</b>\n\nSend the new numeric value as your next message.",[[{text:"← Back",callback_data:"admin_core settings"}]]);return;}736if(action.indexOf("toggle:")===0){if(!hasPerm("settings")){ack("Permission denied.",true);return;}let key=action.slice(7),allowed=["premium_required","username_required","age_required","multiple_wallets_allowed","multiple_assets_allowed","verification_expiry_enabled"];if(!allowed.includes(key)){ack("Unknown setting.",true);return;}let old=s[key];s[key]=!(old===true);if(typeof old==="undefined")s[key]=false;await db.bot.set("system_settings",s);await reAudit("setting_toggled",0,{key:key,old:old,new_value:s[key]},uid);await adminRouter("settings");return;}737 738if (action === "maintenance") {s.maintenance_applications_paused=!s.maintenance_applications_paused;await db.bot.set("system_settings",s);ack(s.maintenance_applications_paused?"New applications paused.":"New applications resumed.",false);await adminRouter("home");return;}739 740if (action.indexOf("evidence:")===0) {741  let target=Number(action.split(":")[1]);742  let wallets=await db.user.get("wallets",[],{user_id:target}); if(!Array.isArray(wallets))wallets=[];743  let proofs=await db.user.get("deal_proofs",[],{user_id:target}); if(!Array.isArray(proofs))proofs=[];744  let own=await db.user.get("ownership_proof",null,{user_id:target});745  let body=wallets.length?wallets.map((w,i)=>(i+1)+". <b>"+reHtml(w.asset)+"</b> • "+reHtml(w.network)+"\n<code>"+reHtml(w.address)+"</code>").join("\n\n"):"No wallets submitted.";746  let rows=[]; if(own)rows.push([{text:"🎥 Open Ownership Proof",callback_data:"admin_core evidence_file:"+target+":ownership:0"}]); for(let i=0;i<proofs.length;i++)rows.push([{text:"📊 Open Deal Proof #"+(i+1),callback_data:"admin_core evidence_file:"+target+":deal:"+i}]); rows.push([{text:"‹ Application",callback_data:"admin_core app:"+target}]);747  show("👛 <b>WALLETS & PROOFS</b>\n\n"+body+"\n\nOwnership proof: <b>"+(own?"Received":"Missing")+"</b>\nDeal proofs: <b>"+proofs.length+"</b>\n\nProof files remain referenced by Telegram file ID and are only sent to authorized staff on request.",rows);return;748}749if(action.indexOf("evidence_file:")===0){750  let p=action.split(":"),target=Number(p[1]),kind=String(p[2]),index=Number(p[3]||0),item=null;if(kind==="ownership")item=await db.user.get("ownership_proof",null,{user_id:target});else{let arr=await db.user.get("deal_proofs",[],{user_id:target});if(Array.isArray(arr))item=arr[index];}if(!item||!item.file_id){ack("Proof file not found.",true);return;}let method=item.type==="photo"?"sendPhoto":item.type==="video"?"sendVideo":item.type==="animation"?"sendAnimation":"sendDocument",key=item.type==="photo"?"photo":item.type==="video"?"video":item.type==="animation"?"animation":"document",payload={chat_id:chat.id,caption:"RED EYE proof • user "+target};payload[key]=item.file_id;await Api.call(method,payload);ack("Proof sent below.",false);return;751}752 753if (action.indexOf("override:")===0) { let target=Number(action.split(":")[1]);await db.user.set("admin_selected_user",target);await db.user.set("input_mode","admin_override_reason");show("⚡ <b>ADMIN OVERRIDE</b>\n\nThis bypasses eligibility thresholds for an exceptional case. Send the mandatory override reason as your next message.",[[{text:"‹ Cancel",callback_data:"admin_core app:"+target}]]);return; }754if (action.indexOf("override_do:")===0) {755  let p=action.split(":"),target=Number(p[1]),reason=decodeURIComponent(p.slice(2).join(":"));756  let old=String(await db.user.get("private_invite_link","",{user_id:target}));if(old){try{await Api.call("revokeChatInviteLink",{chat_id:PRIVATE_GROUP_ID,invite_link:old});}catch(e){}}757  let exp=Math.floor(Date.now()/1000)+3600;let r=await Api.call("createChatInviteLink",{chat_id:PRIVATE_GROUP_ID,name:"RED EYE OVERRIDE • "+target,expire_date:exp,creates_join_request:true});758  if(!r||!r.ok||!r.result||!r.result.invite_link){ack("Could not create invite.",true);return;} let link=r.result.invite_link;759  await db.user.set("application_status","approved",{user_id:target});await db.user.set("approved_at",Date.now(),{user_id:target});await db.user.set("approved_by",uid,{user_id:target});await db.user.set("admin_override_reason",reason,{user_id:target});await db.user.set("private_invite_link",link,{user_id:target});await db.user.set("member_status","approved_pending_join",{user_id:target});760  let invites=await db.bot.get("secure_invites",[]);if(!Array.isArray(invites))invites=[];invites.push({user_id:target,invite_link:link,expires_at:exp,used:false,override:true,created_at:Date.now()});await db.bot.set("secure_invites",invites);761  let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];let i=members.findIndex(x=>x&&Number(x.user_id)===target);let mr={user_id:target,status:"approved_pending_join",approved_at:Date.now(),verified_at:Date.now(),override_reason:reason,updated_at:Date.now()};if(i>=0)members[i]=Object.assign({},members[i],mr);else members.push(mr);await db.bot.set("member_registry",members);762  let q=await db.bot.get("application_queue",[]);if(Array.isArray(q)){for(let x of q)if(Number(x.user_id)===target){x.status="approved";x.reviewed_at=Date.now();x.reviewed_by=uid;x.override=true;}await db.bot.set("application_queue",q);}763  let ah=await db.user.get("application_history",[],{user_id:target});if(!Array.isArray(ah))ah=[];ah.push({application_id:String(await db.user.get("application_id","",{user_id:target})),status:"approved_override",reason:reason,at:Date.now(),by:uid});await db.user.set("application_history",ah.slice(-50),{user_id:target});764  let vh=await db.user.get("verification_history",[],{user_id:target});if(!Array.isArray(vh))vh=[];vh.push({type:"admin_override",status:"approved",reason:reason,at:Date.now(),by:uid});await db.user.set("verification_history",vh.slice(-100),{user_id:target});765  await reAudit("admin_override_approval",target,{reason:reason},uid);766  await reNotify({chat_id:target,text:"✅ <b>APPLICATION APPROVED</b>\n\nYour application was approved by an administrator. Your personal access link expires in 1 hour.",parse_mode:"HTML",reply_markup:{inline_keyboard:[[{text:"🔐 Enter Private Community",url:link,style:"success"}]]}},"application_override_approved",target);Bot.runCommand("/handle_callback_query",{route:"admin_core app:"+target});return;767}768 769if(action==="wallets_admin"){let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];let rows=[];for(let m of members.slice(-40).reverse()){if(!m||!m.user_id)continue;let total=Number(await db.user.get("auto_verified_crypto_total",0,{user_id:Number(m.user_id)})||0);rows.push([{text:String(m.user_id)+" • $"+total.toFixed(2),callback_data:"admin_core wallet_user:"+m.user_id}]);}rows.push([{text:"↻ Run Monitoring Scan",callback_data:"admin_core monitor_scan"}]);rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);show("👛 <b>MEMBER WALLETS</b>\n\nSelect a member. Values shown are latest automatic public checks; admin-verified values remain separate.",rows);return;}770if(action.indexOf("wallet_user:")===0){let target=Number(action.split(":")[1]),wallets=await db.user.get("wallets",[],{user_id:target});if(!Array.isArray(wallets))wallets=[];let hist=await db.user.get("wallet_history",[],{user_id:target});if(!Array.isArray(hist))hist=[];let body=wallets.map((w,i)=>{let av=w.auto_verification||{};return (i+1)+". <b>"+reHtml(w.asset)+"</b> • "+reHtml(w.network)+"\n<code>"+reHtml(w.address)+"</code>\n"+(av.ok?("$"+Number(av.usd_value||0).toFixed(2)+" • verified public data"):reHtml(av.status||"pending"));}).join("\n\n")||"No current wallets.";show("👛 <b>MEMBER WALLETS</b>\n\nUser: <code>"+target+"</code>\nArchived history: <b>"+hist.length+"</b>\n\n"+body,[[{text:"‹ Member",callback_data:"admin_core member:"+target}]]);return;}771 772if (action === "members") {773  let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];let list=members.filter(x=>x&&x.status!=="removed").slice(-30).reverse();let rows=list.map(x=>[{text:String(x.user_id)+" • "+String(x.status||"active"),callback_data:"admin_core member:"+x.user_id}]);rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);show("👥 <b>MEMBERS</b>\n\nSelect a member.",rows);return;774}775if (action.indexOf("member:")===0) {776  let target=Number(action.split(":")[1]);let status=String(await db.user.get("member_status","active",{user_id:target}));let c=Number(await db.user.get("admin_verified_crypto",0,{user_id:target})||0),d=Number(await db.user.get("admin_verified_deals",0,{user_id:target})||0),auto=Number(await db.user.get("auto_verified_crypto_total",0,{user_id:target})||0);let wallets=await db.user.get("wallets",[],{user_id:target});if(!Array.isArray(wallets))wallets=[];let notes=await db.user.get("admin_notes",[],{user_id:target});if(!Array.isArray(notes))notes=[];let rv=String(await db.user.get("reverification_status","",{user_id:target})),joined=Number(await db.user.get("community_joined_at",0,{user_id:target})||0),alerts=await db.bot.get("alerts",[]);if(!Array.isArray(alerts))alerts=[];let ac=alerts.filter(a=>a&&Number(a.user_id)===target&&a.status!=="resolved").length;let prof=await db.user.get("telegram_profile",{},{user_id:target});if(!prof||typeof prof!=="object")prof={};let ah=await db.user.get("application_history",[],{user_id:target});if(!Array.isArray(ah))ah=[];let vh=await db.user.get("verification_history",[],{user_id:target});if(!Array.isArray(vh))vh=[];777  let rows=[[{text:"👛 Wallets",callback_data:"admin_core wallet_user:"+target},{text:"📋 Application",callback_data:"admin_core app:"+target}],[{text:"🔄 Request Re-verification",callback_data:"admin_core reverify:"+target},{text:"🚫 Blacklist",callback_data:"admin_core blacklist_user:"+target}],[{text:"📝 Add Note",callback_data:"admin_core note:"+target}]];778  if(rv==="submitted")rows.push([{text:"✅ Complete Re-verification",callback_data:"admin_core reverify_complete:"+target},{text:"✕ Cancel",callback_data:"admin_core reverify_cancel:"+target}]);779  rows.push([{text:"‹ Members",callback_data:"admin_core members"}]);780  show("👤 <b>MEMBER PROFILE</b>\n\nUser ID: <code>"+target+"</code>\nTelegram: <b>"+reHtml(prof.first_name||"")+"</b> "+(prof.username?("@"+reHtml(prof.username)):"—")+"\nStatus: <b>"+reHtml(status)+"</b>\nJoined: <b>"+(joined?new Date(joined).toISOString():"Pending/unknown")+"</b>\nVerified crypto (admin): <b>$"+c+"</b>\nAutomatic public total: <b>$"+auto.toFixed(2)+"</b>\nVerified deals: <b>$"+d+"</b>\nWallets: <b>"+wallets.length+"</b>\nVerification history: <b>"+vh.length+"</b>\nApplication history: <b>"+ah.length+"</b>\nOpen alerts: <b>"+ac+"</b>\nNotes: <b>"+notes.length+"</b>\nRe-verification: <b>"+reHtml(rv||"none")+"</b>",rows);return;781}782if (action.indexOf("note:")===0){let target=Number(action.split(":")[1]);await db.user.set("admin_selected_user",target);await db.user.set("input_mode","admin_member_note");show("📝 <b>MEMBER NOTE</b>\n\nSend the private admin note.",[[{text:"‹ Cancel",callback_data:"admin_core member:"+target}]]);return;}783if (action.indexOf("reverify:")===0){let target=Number(action.split(":")[1]);show("🔄 <b>RE-VERIFICATION TYPE</b>",[[{text:"Wallet Only",callback_data:"admin_core reverify_do:"+target+":wallet"},{text:"Deal History",callback_data:"admin_core reverify_do:"+target+":deals"}],[{text:"Ownership Proof",callback_data:"admin_core reverify_do:"+target+":ownership"},{text:"Full Verification",callback_data:"admin_core reverify_do:"+target+":full"}],[{text:"‹ Member",callback_data:"admin_core member:"+target}]]);return;}784if (action.indexOf("reverify_do:")===0){let p=action.split(":"),target=Number(p[1]),type=String(p[2]||"full");let rr=await db.bot.get("reverification_requests",[]);if(!Array.isArray(rr))rr=[];let id="RV-"+target+"-"+Date.now();rr.push({id:id,user_id:target,type:type,status:"requested",requested_at:Date.now(),requested_by:uid});await db.bot.set("reverification_requests",rr);await db.user.set("reverification_status","requested",{user_id:target});await db.user.set("reverification_type",type,{user_id:target});await reNotify({chat_id:target,text:"🔄 <b>RE-VERIFICATION REQUESTED</b>\n\nType: <b>"+reHtml(type.toUpperCase())+"</b>\n\nOpen /start and use Application Status to continue. An administrator requested updated verification evidence.",parse_mode:"HTML"},"reverification_requested",target);ack("Re-verification requested.",false);Bot.runCommand("/handle_callback_query",{route:"admin_core member:"+target});return;}785if(action.indexOf("reverify_complete:")===0){let target=Number(action.split(":")[1]),type=String(await db.user.get("reverification_type","full",{user_id:target}));await db.user.set("reverification_status","completed",{user_id:target});if(type==="wallet"||type==="full")await db.user.del("wallet_change_pending",{user_id:target});await db.user.set("reverification_completed_at",Date.now(),{user_id:target});let rr=await db.bot.get("reverification_requests",[]);if(!Array.isArray(rr))rr=[];for(let x of rr)if(x&&Number(x.user_id)===target&&!['completed','cancelled'].includes(String(x.status))){x.status="completed";x.completed_at=Date.now();x.completed_by=uid;}await db.bot.set("reverification_requests",rr);let vh=await db.user.get("verification_history",[],{user_id:target});if(!Array.isArray(vh))vh=[];vh.push({type:type,status:"completed",at:Date.now(),by:uid});await db.user.set("verification_history",vh.slice(-100),{user_id:target});let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];let mi=members.findIndex(x=>x&&Number(x.user_id)===target);if(mi>=0){members[mi].verified_at=Date.now();members[mi].updated_at=Date.now();await db.bot.set("member_registry",members);}await reAudit("reverification_completed",target,{type:type},uid);await reNotify({chat_id:target,text:"✅ <b>RE-VERIFICATION COMPLETED</b>\n\nYour updated verification has been accepted.",parse_mode:"HTML"},"reverification_completed",target);await adminRouter("member:"+target);return;}786if(action.indexOf("reverify_cancel:")===0){let target=Number(action.split(":")[1]);await db.user.set("reverification_status","cancelled",{user_id:target});let rr=await db.bot.get("reverification_requests",[]);if(!Array.isArray(rr))rr=[];for(let x of rr)if(x&&Number(x.user_id)===target&&!['completed','cancelled'].includes(String(x.status))){x.status="cancelled";x.cancelled_at=Date.now();x.cancelled_by=uid;}await db.bot.set("reverification_requests",rr);await reAudit("reverification_cancelled",target,{},uid);await adminRouter("member:"+target);return;}787if (action === "reverifications"){let rr=await db.bot.get("reverification_requests",[]);if(!Array.isArray(rr))rr=[];let open=rr.filter(x=>x&&!["completed","cancelled"].includes(x.status)).slice(-30).reverse();let rows=open.map(x=>[{text:String(x.user_id)+" • "+String(x.type)+" • "+String(x.status),callback_data:"admin_core member:"+x.user_id}]);rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);show("🔄 <b>RE-VERIFICATIONS</b>\n\nOpen requests: <b>"+open.length+"</b>",rows);return;}788 789if (action === "blacklist") {let bl=await db.bot.get("blacklist",[]);if(!Array.isArray(bl))bl=[];let rows=bl.slice(-30).reverse().map(x=>[{text:String(x.user_id)+" • Remove",callback_data:"admin_core unblacklist:"+x.user_id}]);rows.unshift([{text:"+ Add User",callback_data:"admin_core blacklist_add"}]);rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);show("🚫 <b>BLACKLIST</b>\n\nBlocked users: <b>"+bl.length+"</b>",rows);return;}790if (action === "blacklist_add"){await db.user.set("input_mode","admin_blacklist_id");show("🚫 <b>BLACKLIST USER</b>\n\nSend the Telegram numeric user ID.",[[{text:"← Back",callback_data:"admin_core blacklist"}]]);return;}791if (action.indexOf("blacklist_user:")===0){let target=Number(action.split(":")[1]);await db.user.set("admin_selected_user",target);await db.user.set("input_mode","admin_blacklist_reason");show("🚫 <b>BLACKLIST REASON</b>\n\nSend the reason for user <code>"+target+"</code>.",[[{text:"‹ Cancel",callback_data:"admin_core member:"+target}]]);return;}792if (action.indexOf("unblacklist:")===0){let target=Number(action.split(":")[1]);let bl=await db.bot.get("blacklist",[]);if(!Array.isArray(bl))bl=[];let rec=bl.find(x=>x&&Number(x.user_id)===target)||{};bl=bl.filter(x=>Number(x.user_id)!==target);await db.bot.set("blacklist",bl);let prevApp=String(await db.user.get("pre_blacklist_application_status","",{user_id:target})||rec.previous_application_status||"not_started"),prevMember=String(await db.user.get("pre_blacklist_member_status","",{user_id:target})||rec.previous_member_status||"");await db.user.set("application_status",prevApp||"not_started",{user_id:target});if(prevMember)await db.user.set("member_status",prevMember,{user_id:target});else await db.user.del("member_status",{user_id:target});let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];for(let m of members)if(m&&Number(m.user_id)===target){m.status=String(m.pre_blacklist_status||prevMember||"active");delete m.pre_blacklist_status;m.updated_at=Date.now();}await db.bot.set("member_registry",members);await db.user.del("pre_blacklist_application_status",{user_id:target});await db.user.del("pre_blacklist_member_status",{user_id:target});await db.user.del("blacklist_reason",{user_id:target});await reAudit("user_unblacklisted",target,{restored_application_status:prevApp,restored_member_status:prevMember},uid);ack("Removed from blacklist.",false);await adminRouter("blacklist");return;}793 794if (action === "rules"){if(!hasPerm("rules")){ack("Permission denied.",true);return;}let rules=await db.bot.get("rules",[]);if(!Array.isArray(rules))rules=[];let rows=rules.map((r,i)=>[{text:(r.enabled===false?"○ ":"✓ ")+(i+1)+". "+String(r.title||"Rule").slice(0,28),callback_data:"admin_core rule_view:"+i}]);rows.unshift([{text:"+ Add Rule",callback_data:"admin_core rule_add"}]);rows.push([{text:"📚 Version History",callback_data:"admin_core rule_history"}]);rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);show("📜 <b>COMMUNITY RULES</b>\n\nRules can be added, edited, enabled/disabled, reordered and deleted. Every change is written to history/audit.",rows);return;}795if (action === "rule_add"){if(!hasPerm("rules")){ack("Permission denied.",true);return;}await db.user.set("input_mode","admin_rule_add");show("+ <b>ADD RULE</b>\n\nSend: <code>Category | Title | Full rule text</code>\nCategories: General, P2P, OTC, NFT, Advertising, DM, Scam/Fraud, Conduct",[[{text:"← Back",callback_data:"admin_core rules"}]]);return;}796if (action.indexOf("rule_view:")===0){let i=Number(action.split(":")[1]);let rules=await db.bot.get("rules",[]);if(!Array.isArray(rules)||!rules[i]){ack("Rule not found",true);return;}let r=rules[i];show("📜 <b>RULE #"+(i+1)+"</b>\n\nCategory: <b>"+reHtml(r.category||"General")+"</b>\nTitle: <b>"+reHtml(r.title||"Rule")+"</b>\nStatus: <b>"+(r.enabled===false?"DISABLED":"ENABLED")+"</b>\nVersion: <b>"+Number(r.version||1)+"</b>\n\n"+reHtml(r.text||""),[[{text:r.enabled===false?"✅ Enable":"⏸ Disable",callback_data:"admin_core rule_toggle:"+i}],[{text:"✏ Edit Title",callback_data:"admin_core rule_edit_title:"+i},{text:"✏ Edit Text",callback_data:"admin_core rule_edit_text:"+i}],[{text:"⬆ Move Up",callback_data:"admin_core rule_up:"+i},{text:"⬇ Move Down",callback_data:"admin_core rule_down:"+i}],[{text:"🗑 Delete",callback_data:"admin_core rule_delete:"+i}],[{text:"‹ Rules",callback_data:"admin_core rules"}]]);return;}797if (action.indexOf("rule_toggle:")===0){if(!hasPerm("rules")){ack("Permission denied.",true);return;}let i=Number(action.split(":")[1]);let rules=await db.bot.get("rules",[]);if(!Array.isArray(rules)||!rules[i]){ack("Rule not found",true);return;}let old=rules[i].enabled!==false;rules[i].enabled=!old;rules[i].version=Number(rules[i].version||1)+1;rules[i].updated_at=Date.now();rules[i].updated_by=uid;await db.bot.set("rules",rules);let h=await db.bot.get("rule_history",[]);if(!Array.isArray(h))h=[];h.push({rule_id:rules[i].id,change:"toggle",old_value:old,new_value:!old,version:rules[i].version,by:uid,at:Date.now()});await db.bot.set("rule_history",h.slice(-500));await reAudit("rule_toggled",0,{rule_id:rules[i].id,enabled:!old},uid);await adminRouter("rule_view:"+i);return;}798if (action.indexOf("rule_edit_title:")===0||action.indexOf("rule_edit_text:")===0){if(!hasPerm("rules")){ack("Permission denied.",true);return;}let i=Number(action.split(":")[1]);await db.user.set("admin_selected_rule",i);await db.user.set("input_mode",action.startsWith("rule_edit_title")?"admin_rule_edit_title":"admin_rule_edit_text");show("✏ <b>EDIT RULE</b>\n\nSend the new "+(action.startsWith("rule_edit_title")?"title":"rule text")+" as your next message.",[[{text:"‹ Cancel",callback_data:"admin_core rule_view:"+i}]]);return;}799if (action.indexOf("rule_up:")===0||action.indexOf("rule_down:")===0){if(!hasPerm("rules")){ack("Permission denied.",true);return;}let i=Number(action.split(":")[1]),rules=await db.bot.get("rules",[]);if(!Array.isArray(rules)||!rules[i]){ack("Rule not found",true);return;}let j=action.startsWith("rule_up")?i-1:i+1;if(j<0||j>=rules.length){ack("Already at edge.",false);return;}let t=rules[i];rules[i]=rules[j];rules[j]=t;await db.bot.set("rules",rules);await reAudit("rule_reordered",0,{from:i,to:j},uid);await adminRouter("rules");return;}800if (action.indexOf("rule_delete:")===0){if(!hasPerm("rules")){ack("Permission denied.",true);return;}let i=Number(action.split(":")[1]);show("🗑 <b>DELETE RULE?</b>\n\nThis removes the active rule but keeps history/audit records.",[[{text:"✅ Delete",callback_data:"admin_core rule_delete_do:"+i},{text:"✕ Cancel",callback_data:"admin_core rule_view:"+i}]]);return;}801if (action.indexOf("rule_delete_do:")===0){if(!hasPerm("rules")){ack("Permission denied.",true);return;}let i=Number(action.split(":")[1]),rules=await db.bot.get("rules",[]);if(!Array.isArray(rules)||!rules[i]){ack("Rule not found",true);return;}let old=rules.splice(i,1)[0];await db.bot.set("rules",rules);let h=await db.bot.get("rule_history",[]);if(!Array.isArray(h))h=[];h.push({rule_id:old.id,change:"deleted",snapshot:old,by:uid,at:Date.now()});await db.bot.set("rule_history",h.slice(-500));await reAudit("rule_deleted",0,{rule_id:old.id,title:old.title},uid);await adminRouter("rules");return;}802if (action === "rule_history"){let h=await db.bot.get("rule_history",[]);if(!Array.isArray(h))h=[];let b=h.slice(-15).reverse().map(x=>"• <b>"+reHtml(x.change||"change")+"</b> • "+reHtml(x.rule_id||"")+" • <code>"+new Date(Number(x.at||Date.now())).toISOString()+"</code>").join("\n")||"No history yet.";show("📚 <b>RULE VERSION HISTORY</b>\n\n"+b,[[{text:"‹ Rules",callback_data:"admin_core rules"}]]);return;}803 804if (action === "assets"){let assets=Array.isArray(s.featured_assets)?s.featured_assets:["USDT","SOL","ETH","BTC","TON"];let rows=assets.map(a=>[{text:"− "+a,callback_data:"admin_core asset_remove:"+a}]);rows.unshift([{text:"+ Add Featured Asset",callback_data:"admin_core asset_add"}]);rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);show("🪙 <b>FEATURED ASSETS</b>\n\nThese appear in the applicant asset selector. Other cryptocurrencies are still allowed for manual review.",rows);return;}805if (action === "asset_add"){await db.user.set("input_mode","admin_asset_add");show("🪙 <b>ADD FEATURED ASSET</b>\n\nSend the symbol, e.g. <code>AVAX</code>.",[[{text:"← Back",callback_data:"admin_core assets"}]]);return;}806if (action.indexOf("asset_remove:")===0){let a=action.slice(13).toUpperCase();let assets=Array.isArray(s.featured_assets)?s.featured_assets:["USDT","SOL","ETH","BTC","TON"];s.featured_assets=assets.filter(x=>String(x).toUpperCase()!==a);await db.bot.set("system_settings",s);await reAudit("asset_removed",0,{symbol:a},uid);await adminRouter("assets");return;}807 808if (action === "announcements"){await db.user.set("input_mode","admin_announcement");show("📣 <b>ANNOUNCEMENT</b>\n\nSend the announcement text as your next message. It will be broadcast only after a confirmation button.",[[{text:"‹ Admin Home",callback_data:"admin_core home"}]]);return;}809if (action === "announcement_confirm"){let text=String(await db.user.get("pending_announcement",""));if(!text){ack("No pending announcement",true);return;}let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];let sent=0,queued=0;for(let m of members){if(!m||!m.user_id||["removed","blacklisted"].includes(String(m.status)))continue;let ok=await reNotify({chat_id:Number(m.user_id),text:"📣 <b>RED EYE ANNOUNCEMENT</b>\n\n"+text,parse_mode:"HTML"},"announcement",Number(m.user_id));if(ok)sent++;else queued++;}await db.user.del("pending_announcement");let hist=await db.bot.get("announcements",[]);if(!Array.isArray(hist))hist=[];hist.push({text:text,sent_at:Date.now(),sent_by:uid,delivered_now:sent,retry_queued:queued});await db.bot.set("announcements",hist.slice(-100));await reAudit("announcement_sent",0,{delivered_now:sent,retry_queued:queued},uid);show("✅ <b>ANNOUNCEMENT PROCESSED</b>\n\nDelivered now: <b>"+sent+"</b>\nQueued for safe retry: <b>"+queued+"</b>",[[{text:"‹ Admin Home",callback_data:"admin_core home"}]]);return;}810if (action === "announcement_cancel"){await db.user.del("pending_announcement");await adminRouter("home");return;}811 812if (action === "alerts"){let alerts=await db.bot.get("alerts",[]);if(!Array.isArray(alerts))alerts=[];let flags=await db.bot.get("risk_flags",[]);if(!Array.isArray(flags))flags=[];let open=alerts.filter(x=>x&&x.status!=="resolved").slice(-30).reverse(),openFlags=flags.filter(x=>x&&x.status!=="resolved").length;let rows=open.map((x,i)=>[{text:(x.type||"Alert")+" • "+String(x.user_id||"system"),callback_data:"admin_core alert_resolve:"+String(x.id||i)}]);rows.unshift([{text:"⚑ Risk Flags ("+openFlags+")",callback_data:"admin_core risk_flags"}]);rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);show("🚨 <b>ALERTS</b>\n\nOpen alerts: <b>"+open.length+"</b>\nRisk flags: <b>"+openFlags+"</b>\n\nRisk flags are review signals only and never automatically label or remove a member.",rows);return;}813if(action==="risk_flags"){let f=await db.bot.get("risk_flags",[]);if(!Array.isArray(f))f=[];let open=f.filter(x=>x&&x.status!=="resolved").slice(-30).reverse();let rows=open.map(x=>[{text:String(x.type||"Risk")+" • "+String(x.user_id||""),callback_data:"admin_core risk_resolve:"+String(x.id)}]);rows.push([{text:"‹ Alerts",callback_data:"admin_core alerts"}]);show("⚑ <b>RISK FLAGS</b>\n\nSignals for admin review: <b>"+open.length+"</b>\n\nNo risk flag causes automatic rejection/removal.",rows);return;}814if(action.indexOf("risk_resolve:")===0){let id=action.slice(13),f=await db.bot.get("risk_flags",[]);if(!Array.isArray(f))f=[];for(let x of f)if(x&&String(x.id)===id){x.status="resolved";x.resolved_at=Date.now();x.resolved_by=uid;}await db.bot.set("risk_flags",f);await reAudit("risk_flag_resolved",0,{id:id},uid);await adminRouter("risk_flags");return;}815if (action.indexOf("alert_resolve:")===0){let id=action.slice(14);let alerts=await db.bot.get("alerts",[]);if(!Array.isArray(alerts))alerts=[];for(let a of alerts)if(String(a.id)===id){a.status="resolved";a.resolved_at=Date.now();a.resolved_by=uid;}await db.bot.set("alerts",alerts);await reAudit("alert_resolved",0,{id:id},uid);await adminRouter("alerts");return;}816 817if (action === "maintenance_page"){show("🛠 <b>MAINTENANCE</b>\n\nNew applications: <b>"+(s.maintenance_applications_paused?"PAUSED":"OPEN")+"</b>\nWallet changes: <b>"+(s.maintenance_wallet_changes_paused?"PAUSED":"OPEN")+"</b>\nRe-verification: <b>"+(s.maintenance_reverification_paused?"PAUSED":"OPEN")+"</b>",[[{text:"Toggle Applications",callback_data:"admin_core mt_app"}],[{text:"Toggle Wallet Changes",callback_data:"admin_core mt_wallet"}],[{text:"Toggle Re-verification",callback_data:"admin_core mt_reverify"}],[{text:"✏ Maintenance Message",callback_data:"admin_core mt_message"}],[{text:"‹ Admin Home",callback_data:"admin_core home"}]]);return;}818if (["mt_app","mt_wallet","mt_reverify"].includes(action)){if(action==="mt_app")s.maintenance_applications_paused=!s.maintenance_applications_paused;if(action==="mt_wallet")s.maintenance_wallet_changes_paused=!s.maintenance_wallet_changes_paused;if(action==="mt_reverify")s.maintenance_reverification_paused=!s.maintenance_reverification_paused;await db.bot.set("system_settings",s);await reAudit("maintenance_toggle",0,{action:action,value:action==="mt_app"?s.maintenance_applications_paused:action==="mt_wallet"?s.maintenance_wallet_changes_paused:s.maintenance_reverification_paused},uid);await adminRouter("maintenance_page");return;}819if (action === "mt_message"){await db.user.set("input_mode","admin_maintenance_message");show("✏ <b>MAINTENANCE MESSAGE</b>\n\nSend the message applicants should see while applications are paused.",[[{text:"← Back",callback_data:"admin_core maintenance_page"}]]);return;}820 821if (action === "analytics"){let q=await db.bot.get("application_queue",[]);if(!Array.isArray(q))q=[];let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];let count={};for(let x of q)if(x)count[x.status]=(count[x.status]||0)+1;show("📊 <b>ANALYTICS</b>\n\nApplications total: <b>"+q.length+"</b>\nSubmitted/review: <b>"+((count.submitted||0)+(count.under_review||0))+"</b>\nApproved: <b>"+(count.approved||0)+"</b>\nRejected: <b>"+(count.rejected||0)+"</b>\nAbandoned: <b>"+(count.abandoned||0)+"</b>\nMembers: <b>"+members.length+"</b>",[[{text:"‹ Admin Home",callback_data:"admin_core home"}]]);return;}822if (action === "audit"){let logs=await db.bot.get("audit_logs",[]);if(!Array.isArray(logs))logs=[];let recent=logs.slice(-15).reverse();let body=recent.length?recent.map(x=>"• <b>"+String(x.action||"event")+"</b> • "+String(x.target_user_id||"")+"\n<code>"+new Date(Number(x.at||Date.now())).toISOString()+"</code>").join("\n\n"):"No audit records yet.";show("🧾 <b>AUDIT LOGS</b>\n\n"+body,[[{text:"‹ Admin Home",callback_data:"admin_core home"}]]);return;}823if (action === "backup"){let backups=await db.bot.get("backups",[]);if(!Array.isArray(backups))backups=[];show("💾 <b>BACKUP / SAFE EXPORT</b>\n\nSnapshots retained: <b>"+backups.length+"</b>\n\nExports intentionally exclude proof file IDs, private credentials and wallet addresses from casual output.",[[{text:"💾 Create Backup",callback_data:"admin_core backup_create"}],[{text:"👥 Export Members",callback_data:"admin_core export_members"},{text:"📥 Export Applications",callback_data:"admin_core export_applications"}],[{text:"✅ Export Verification History",callback_data:"admin_core export_verifications"},{text:"🧾 Export Audit",callback_data:"admin_core export_audit"}],[{text:"⚙ Export Settings & Rules",callback_data:"admin_core export_settings"}],[{text:"‹ Admin Home",callback_data:"admin_core home"}]]);return;}824if(action==="backup_create"){let q=await db.bot.get("application_queue",[]);if(!Array.isArray(q))q=[];let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];let rules=await db.bot.get("rules",[]);if(!Array.isArray(rules))rules=[];let audit=await db.bot.get("audit_logs",[]);if(!Array.isArray(audit))audit=[];let blacklist=await db.bot.get("blacklist",[]);if(!Array.isArray(blacklist))blacklist=[];let alerts=await db.bot.get("alerts",[]);if(!Array.isArray(alerts))alerts=[];let rv=await db.bot.get("reverification_requests",[]);if(!Array.isArray(rv))rv=[];let admins=await db.bot.get("admin_registry",[]);if(!Array.isArray(admins))admins=[];let p2p=await db.bot.get("p2p_groups",[]);if(!Array.isArray(p2p))p2p=[];let backups=await db.bot.get("backups",[]);if(!Array.isArray(backups))backups=[];let safeMembers=members.map(m=>({user_id:m.user_id,username:m.username||"",first_name:m.first_name||"",status:m.status,joined_at:m.joined_at||0,approved_at:m.approved_at||0,verified_at:m.verified_at||0,verified_crypto:m.verified_crypto||0,verified_deals:m.verified_deals||0})),safeQueue=q.map(x=>({application_id:x.application_id,user_id:x.user_id,username:x.username||"",status:x.status,started_at:x.started_at||0,submitted_at:x.submitted_at||0,reviewed_at:x.reviewed_at||0}));let b={id:"BKP-"+Date.now(),created_at:Date.now(),created_by:uid,summary:{applications:q.length,members:members.length,rules:rules.length,audit_events:audit.length,blacklist:blacklist.length,alerts:alerts.length,reverifications:rv.length,admins:admins.length},settings:s,rules:rules,application_queue:safeQueue,member_registry:safeMembers,blacklist:blacklist,alerts:alerts.slice(-500),reverification_requests:rv.slice(-500),admin_registry:admins.map(a=>({user_id:a.user_id,role:a.role,revoked:a.revoked===true,created_at:a.created_at||0})),p2p_groups:p2p};backups.push(b);await db.bot.set("backups",backups.slice(-30));await reAudit("backup_created",0,{id:b.id,summary:b.summary},uid);show("✅ <b>BACKUP CREATED</b>\n\nID: <code>"+b.id+"</code>\nApplications: <b>"+q.length+"</b>\nMembers: <b>"+members.length+"</b>\nRules: <b>"+rules.length+"</b>\n\n<i>Sensitive proof file IDs, private credentials and wallet addresses are intentionally excluded from this safe snapshot.</i>",[[{text:"‹ Backup / Export",callback_data:"admin_core backup"}]]);return;}825async function sendExport(title,data){let raw=JSON.stringify(data,null,2),max=3200,total=Math.max(1,Math.ceil(raw.length/max));for(let i=0;i<total;i++){await Api.sendMessage({chat_id:chat.id,text:"📦 <b>"+reHtml(title)+"</b> • "+(i+1)+"/"+total+"\n<pre>"+reHtml(raw.slice(i*max,(i+1)*max))+"</pre>",parse_mode:"HTML"});}}826if(action==="export_members"){let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];let safe=members.map(m=>({user_id:m.user_id,username:m.username||"",first_name:m.first_name||"",status:m.status,joined_at:m.joined_at||0,approved_at:m.approved_at||0,verified_crypto:m.verified_crypto||0,verified_deals:m.verified_deals||0}));await sendExport("MEMBERS EXPORT",safe);await reAudit("export_members",0,{count:safe.length},uid);return;}827if(action==="export_applications"){let q=await db.bot.get("application_queue",[]);if(!Array.isArray(q))q=[];let safe=q.map(x=>({application_id:x.application_id,user_id:x.user_id,username:x.username||"",first_name:x.first_name||"",status:x.status,started_at:x.started_at||0,submitted_at:x.submitted_at||0,reviewed_at:x.reviewed_at||0}));await sendExport("APPLICATIONS EXPORT",safe);await reAudit("export_applications",0,{count:safe.length},uid);return;}828if(action==="export_audit"){let a=await db.bot.get("audit_logs",[]);if(!Array.isArray(a))a=[];await sendExport("AUDIT EXPORT",a.slice(-500));await reAudit("export_audit",0,{count:Math.min(a.length,500)},uid);return;}829if(action==="export_settings"){let r=await db.bot.get("rules",[]);if(!Array.isArray(r))r=[];await sendExport("SETTINGS & RULES EXPORT",{settings:s,rules:r});await reAudit("export_settings_rules",0,{rules:r.length},uid);return;}830if(action==="export_verifications"){let users=await Bot.getUsers({chatType:"private"});if(!Array.isArray(users))users=[];let out=[];for(let u of users.slice(0,500)){let id=Number(typeof u==="object"?u.user_id:u);if(!id)continue;let h=await db.user.get("verification_history",[],{user_id:id});if(Array.isArray(h)&&h.length)out.push({user_id:id,history:h});}await sendExport("VERIFICATION HISTORY EXPORT",out);await reAudit("export_verifications",0,{users:out.length},uid);return;}831 832if (action === "networks") { if(!hasPerm("assets")){ack("Permission denied.",true);return;} let map=s.asset_networks; if(!map||typeof map!=="object")map={USDT:["TRON","ETHEREUM","SOLANA","TON"],ETH:["ETHEREUM"],BTC:["BITCOIN"],SOL:["SOLANA"],TON:["TON"]}; let rows=[]; for(let a of Object.keys(map)){rows.push([{text:"🌐 "+a+" • "+map[a].join(", ").slice(0,35),callback_data:"admin_core network_asset:"+a}]);} rows.unshift([{text:"+ Add / Configure Asset Networks",callback_data:"admin_core network_add"}]);rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);show("🌐 <b>ASSETS & NETWORKS</b>\n\nConfigure which networks appear for each asset.",rows);return; }833if(action==="network_add"){await db.user.set("input_mode","admin_network_add");show("🌐 <b>CONFIGURE NETWORKS</b>\n\nSend: <code>ASSET | NETWORK1, NETWORK2</code>\nExample: <code>USDT | TRON, ETHEREUM</code>",[[{text:"← Back",callback_data:"admin_core networks"}]]);return;}834if(action.indexOf("network_asset:")===0){let a=action.slice(14).toUpperCase(),map=s.asset_networks||{},list=Array.isArray(map[a])?map[a]:[];show("🌐 <b>"+reHtml(a)+" NETWORKS</b>\n\n"+reHtml(list.join(", ")||"None"),[[{text:"✏ Replace Networks",callback_data:"admin_core network_add"}],[{text:"‹ Networks",callback_data:"admin_core networks"}]]);return;}835 836if(action==="p2p"){if(!hasPerm("p2p")){ack("Permission denied.",true);return;}let g=await db.bot.get("p2p_groups",[]);if(!Array.isArray(g))g=[];let rows=g.map((x,i)=>[{text:(x.enabled===false?"○ ":"✓ ")+String(x.name||x.username||x.chat_id),callback_data:"admin_core p2p_view:"+i}]);rows.unshift([{text:"+ Add P2P Group",callback_data:"admin_core p2p_add"}]);rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);show("🔗 <b>P2P GROUP MANAGER</b>\n\nReserved for future eligibility use; current entry flow does not require membership in these groups.",rows);return;}837if(action==="p2p_add"){await db.user.set("input_mode","admin_p2p_add");show("🔗 <b>ADD P2P GROUP</b>\n\nSend: <code>Name | @username_or_chat_id</code>",[[{text:"← Back",callback_data:"admin_core p2p"}]]);return;}838if(action.indexOf("p2p_view:")===0){let i=Number(action.split(":")[1]),g=await db.bot.get("p2p_groups",[]);if(!Array.isArray(g)||!g[i]){ack("Group not found.",true);return;}let x=g[i];show("🔗 <b>P2P GROUP</b>\n\nName: <b>"+reHtml(x.name)+"</b>\nReference: <code>"+reHtml(x.reference)+"</code>\nStatus: <b>"+(x.enabled===false?"DISABLED":"ENABLED")+"</b>",[[{text:x.enabled===false?"✅ Enable":"⏸ Disable",callback_data:"admin_core p2p_toggle:"+i}],[{text:"🗑 Delete",callback_data:"admin_core p2p_delete:"+i}],[{text:"‹ Groups",callback_data:"admin_core p2p"}]]);return;}839if(action.indexOf("p2p_toggle:")===0){let i=Number(action.split(":")[1]),g=await db.bot.get("p2p_groups",[]);if(!Array.isArray(g)||!g[i])return;g[i].enabled=g[i].enabled===false;g[i].updated_at=Date.now();await db.bot.set("p2p_groups",g);await reAudit("p2p_group_toggled",0,{index:i,enabled:g[i].enabled},uid);await adminRouter("p2p_view:"+i);return;}840if(action.indexOf("p2p_delete:")===0){let i=Number(action.split(":")[1]),g=await db.bot.get("p2p_groups",[]);if(!Array.isArray(g)||!g[i])return;let old=g.splice(i,1)[0];await db.bot.set("p2p_groups",g);await reAudit("p2p_group_deleted",0,{name:old.name},uid);await adminRouter("p2p");return;}841 842if(action==="admins"){if(adminRole!=="owner"){ack("Owner permission required.",true);return;}let a=await db.bot.get("admin_registry",[]);if(!Array.isArray(a))a=[];let rows=a.map((x,i)=>[{text:(x.revoked===true?"🚫 ":"✅ ")+String(x.user_id)+" • "+String(x.role),callback_data:"admin_core admin_view:"+i}]);rows.unshift([{text:"+ Add Admin",callback_data:"admin_core admin_add"}]);rows.push([{text:"‹ Admin Home",callback_data:"admin_core home"}]);show("👮 <b>ADMINS & ROLES</b>\n\nOwner: <code>"+OWNER_ID+"</code>\nAdditional admins: <b>"+a.length+"</b>",rows);return;}843if(action==="admin_add"){if(adminRole!=="owner"){ack("Owner permission required.",true);return;}await db.user.set("input_mode","admin_add_staff_id");show("+ <b>ADD ADMIN</b>\n\nSend the Telegram numeric user ID.",[[{text:"← Back",callback_data:"admin_core admins"}]]);return;}844if(action.indexOf("admin_view:")===0){if(adminRole!=="owner"){ack("Owner permission required.",true);return;}let i=Number(action.split(":")[1]),a=await db.bot.get("admin_registry",[]);if(!Array.isArray(a)||!a[i])return;let x=a[i];show("👮 <b>ADMIN PROFILE</b>\n\nUser: <code>"+Number(x.user_id)+"</code>\nRole: <b>"+reHtml(x.role)+"</b>\nStatus: <b>"+(x.revoked===true?"REVOKED":"ACTIVE")+"</b>",[[{text:"👑 Super Admin",callback_data:"admin_core admin_role:"+i+":super_admin"}],[{text:"🧾 Verification Staff",callback_data:"admin_core admin_role:"+i+":verification_staff"}],[{text:"🛡 Moderator",callback_data:"admin_core admin_role:"+i+":moderator"}],[{text:"💬 Support",callback_data:"admin_core admin_role:"+i+":support"}],[{text:x.revoked===true?"✅ Restore":"🚫 Revoke",callback_data:"admin_core admin_revoke:"+i}],[{text:"‹ Admins",callback_data:"admin_core admins"}]]);return;}845if(action.indexOf("admin_role:")===0){if(adminRole!=="owner")return;let p=action.split(":"),i=Number(p[1]),role=String(p[2]),allowed=["super_admin","verification_staff","moderator","support"],a=await db.bot.get("admin_registry",[]);if(!allowed.includes(role)||!Array.isArray(a)||!a[i])return;let old=a[i].role;a[i].role=role;a[i].updated_at=Date.now();await db.bot.set("admin_registry",a);await reAudit("admin_role_changed",a[i].user_id,{old_role:old,new_role:role},uid);await adminRouter("admin_view:"+i);return;}846if(action.indexOf("admin_revoke:")===0){if(adminRole!=="owner")return;let i=Number(action.split(":")[1]),a=await db.bot.get("admin_registry",[]);if(!Array.isArray(a)||!a[i])return;a[i].revoked=a[i].revoked!==true;a[i].session_revoked_at=Date.now();await db.bot.set("admin_registry",a);await db.user.del("staff_session_until",{user_id:Number(a[i].user_id)});await reAudit("admin_access_toggled",a[i].user_id,{revoked:a[i].revoked},uid);await adminRouter("admin_view:"+i);return;}847 848if(action==="system"){if(!hasPerm("system")){ack("Permission denied.",true);return;}let last=Number(await db.bot.get("scheduler_last_run",0)||0),backs=await db.bot.get("backups",[]);if(!Array.isArray(backs))backs=[];show("⚙ <b>SYSTEM SETTINGS / HEALTH</b>\n\nOfficial channel: <code>"+reHtml(String(s.official_channel||"@red_eye_official"))+"</code>\nPrivate group: <code>"+reHtml(String(s.private_group_id||-1004382007648))+"</code>\nLast lifecycle scan: <b>"+(last?new Date(last).toISOString():"Never")+"</b>\nBackups retained: <b>"+backs.length+"</b>\n\nProvider failures never automatically reject applicants.",[[{text:"📝 Set Channel",callback_data:"admin_core system_channel"},{text:"📝 Set Private Group",callback_data:"admin_core system_group"}],[{text:"🧪 Provider Test",callback_data:"admin_core provider_test"},{text:"✅ Production Check",callback_data:"admin_core production_check"}],[{text:"⏱ Background Worker URL",callback_data:"admin_core worker_webhook"}],[{text:"‹ Admin Home",callback_data:"admin_core home"}]]);return;}849if(action==="worker_webhook"){if(typeof Webhook==="undefined"||!Webhook||typeof Webhook.getGlobalUrl!=="function"){show("⏱ <b>BACKGROUND WORKER</b>\n\nGlobal Webhook is unavailable in this runtime. Lifecycle still runs opportunistically on updates and can be launched manually from Admin.",[[{text:"‹ System",callback_data:"admin_core system"}]]);return;}let url=Webhook.getGlobalUrl("/worker",{options:{worker:true}});show("⏱ <b>BACKGROUND WORKER URL</b>\n\nUse this signed URL with a cron/system trigger every 5–15 minutes. When invoked without a Telegram user, the @ hook performs lifecycle work, notification retries, wallet monitoring and daily snapshots.\n\n<code>"+reHtml(String(url||""))+"</code>",[[{text:"‹ System",callback_data:"admin_core system"}]]);return;}850if(action==="provider_test"){let btc=await rePriceUSD("BTC"),eth=await rePriceUSD("ETH"),sol=await rePriceUSD("SOL"),ton=await rePriceUSD("TON"),usdt=await rePriceUSD("USDT");show("🧪 <b>PROVIDER TEST</b>\n\nBTC pricing: <b>"+(btc.ok?"OK • "+reHtml(btc.source):reHtml(btc.status))+"</b>\nETH pricing: <b>"+(eth.ok?"OK • "+reHtml(eth.source):reHtml(eth.status))+"</b>\nSOL pricing: <b>"+(sol.ok?"OK • "+reHtml(sol.source):reHtml(sol.status))+"</b>\nTON pricing: <b>"+(ton.ok?"OK • "+reHtml(ton.source):reHtml(ton.status))+"</b>\nUSDT pricing: <b>"+(usdt.ok?"OK • "+reHtml(usdt.source):reHtml(usdt.status))+"</b>\n\nFailure here does not reject applicants; affected wallets fall back to temporary-unavailable/manual review.",[[{text:"‹ System",callback_data:"admin_core system"}]]);return;}851if(action==="production_check"){let checks=[];checks.push(["Owner configured",!!OWNER_ID]);checks.push(["Official channel configured",!!String(s.official_channel||"@red_eye_official")]);checks.push(["Private group configured",Number(s.private_group_id||-1004382007648)<0]);checks.push(["Minimum crypto valid",Number(s.min_crypto_networth||1000)>0]);checks.push(["Minimum deals valid",Number(s.min_deal_volume||3000)>0]);checks.push(["Reminder valid",Number(s.application_reminder_minutes||60)>0]);checks.push(["Expiry valid",Number(s.application_expiry_hours||24)>0]);checks.push(["Low wallet thresholds valid",Number(s.low_wallet_threshold||500)>0&&Number(s.low_wallet_clear_threshold||600)>Number(s.low_wallet_threshold||500)]);checks.push(["Staff 2FA configured",!!String(await db.user.get("staff_pin_hash","")||"")]);let rules=await db.bot.get("rules",[]);checks.push(["Rules manager available",Array.isArray(rules)]);let passed=checks.filter(x=>x[1]).length,body=checks.map(x=>(x[1]?"✅ ":"⚠️ ")+x[0]).join("\n");show("✅ <b>PRODUCTION CHECK</b>\n\nPassed: <b>"+passed+"/"+checks.length+"</b>\n\n"+body+"\n\n<i>This diagnostic is non-destructive.</i>",[[{text:"‹ System",callback_data:"admin_core system"}]]);return;}852if(action==="system_channel"){await db.user.set("input_mode","admin_system_channel");show("📝 Send official channel username, e.g. <code>@red_eye_official</code>.",[[{text:"← Back",callback_data:"admin_core system"}]]);return;}853if(action==="system_group"){await db.user.set("input_mode","admin_system_group");show("📝 Send private community numeric chat ID, e.g. <code>-100...</code>.",[[{text:"← Back",callback_data:"admin_core system"}]]);return;}854 855if(action==="monitor_scan"){if(!hasPerm("wallets")){ack("Permission denied.",true);return;}let users=await Bot.getUsers({full:true,chatType:"private",excludeBlocked:true,limit:10000});if(!Array.isArray(users))users=[];let low=Number(s.low_wallet_threshold||500),clear=Number(s.low_wallet_clear_threshold||600),days=Number(s.low_wallet_duration_days||7),now=Date.now(),scanned=0,members=0,alerts=await db.bot.get("alerts",[]);if(!Array.isArray(alerts))alerts=[];for(let u of users){let id=Number(u&&u.user_id);if(!id)continue;let ms=String(await db.user.get("member_status","",{user_id:id}));if(!["active","approved_pending_join"].includes(ms))continue;members++;let wallets=await db.user.get("wallets",[],{user_id:id});if(!Array.isArray(wallets)||!wallets.length)continue;let vr=await reVerifyWalletList(wallets);await db.user.set("wallets",vr.wallets,{user_id:id});await db.user.set("auto_verified_crypto_total",vr.total_usd,{user_id:id});scanned++;let since=Number(await db.user.get("low_wallet_since",0,{user_id:id})||0);if(vr.total_usd<low){if(!since){since=now;await db.user.set("low_wallet_since",since,{user_id:id});}if(now-since>=days*86400000&&!alerts.some(a=>a&&a.status!=="resolved"&&a.type==="low_wallet"&&Number(a.user_id)===id)){alerts.push({id:"ALERT-"+id+"-"+now,type:"low_wallet",user_id:id,status:"open",value:vr.total_usd,threshold:low,since:since,created_at:now});await reNotify({chat_id:OWNER_ID,text:"🚨 <b>LOW WALLET ALERT</b>\n\nMember: <code>"+id+"</code>\nVerified public value: <b>$"+vr.total_usd.toFixed(2)+"</b>\nBelow threshold for configured duration. No automatic removal was performed.",parse_mode:"HTML"},"low_wallet_alert",OWNER_ID);}}else if(since&&vr.total_usd>=clear){await db.user.del("low_wallet_since",{user_id:id});for(let a of alerts)if(a&&a.type==="low_wallet"&&Number(a.user_id)===id&&a.status!=="resolved"){a.status="resolved";a.resolved_at=now;a.resolve_reason="balance_recovered";}}}await db.bot.set("alerts",alerts.slice(-1000));await db.bot.set("wallet_monitor_last_run",now);await reAudit("wallet_monitor_scan",0,{members:members,scanned:scanned},uid);show("👛 <b>WALLET MONITOR COMPLETE</b>\n\nMembers considered: <b>"+members+"</b>\nWallet sets checked: <b>"+scanned+"</b>\nLow threshold: <b>$"+low+"</b>\nClear threshold: <b>$"+clear+"</b>\n\nNo member is automatically removed by monitoring.",[[{text:"‹ Admin Home",callback_data:"admin_core home"}]]);return;}856 857if (action === "lifecycle_scan") {858  let now=Date.now(),q=await db.bot.get("application_queue",[]);if(!Array.isArray(q))q=[];let reminderMs=Number(s.application_reminder_minutes||60)*60000,expiryMs=Number(s.application_expiry_hours||24)*3600000,rem=0,exp=0;859  for(let item of q){if(!item||!item.user_id)continue;let status=String(item.status||"");if(status!=="started")continue;let started=Number(item.started_at||item.last_activity_at||0),last=Number(item.last_activity_at||started);if(started&&now-started>=expiryMs){item.status="abandoned";item.abandoned_at=now;await db.user.set("application_status","abandoned",{user_id:Number(item.user_id)});let ah=await db.user.get("application_history",[],{user_id:Number(item.user_id)});if(!Array.isArray(ah))ah=[];ah.push({application_id:item.application_id||"",status:"abandoned",at:now,reason:"expiry"});await db.user.set("application_history",ah.slice(-50),{user_id:Number(item.user_id)});await reNotify({chat_id:Number(item.user_id),text:"⌛ Your RED EYE application expired after the configured inactivity window."},"application_expired",Number(item.user_id));exp++;}else if(last&&!item.reminder_sent_at&&now-last>=reminderMs){item.reminder_sent_at=now;await reNotify({chat_id:Number(item.user_id),text:"⏰ Reminder: your RED EYE application is still incomplete. Open /start to continue."},"application_reminder",Number(item.user_id));rem++;}}860  await db.bot.set("application_queue",q);await db.bot.set("scheduler_last_run",now);show("⌛ <b>LIFECYCLE SCAN COMPLETE</b>\n\nReminders sent: <b>"+rem+"</b>\nApplications expired: <b>"+exp+"</b>",[[{text:"‹ Admin Home",callback_data:"admin_core home"}]]);return;861}862 863ack("Unknown admin action.",false);864 865}866 867let data = (options && options.route) ? String(options.route) : "";868if (!data && update && update.callback_query) data = String(update.callback_query.data || "").trim();869if (!data) return;870 871if (data === "user_core" || data.startsWith("user_core ")) {872  let action = data === "user_core" ? "home" : data.slice(10).trim();873  await userRouter(action);874  return;875}876 877if (data === "admin_core" || data.startsWith("admin_core ")) {878  let action = data === "admin_core" ? "home" : data.slice(11).trim();879  await adminRouter(action);880  return;881}882 883Api.answerCallbackQuery({ callback_query_id: update.callback_query.id, text: "This action is unavailable." });