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/_.js

javascript · 246 lines

Raw
1/**#command2name: *3answer: 4keyboard: 5parse_mode: markdown6aliases: 7allow_only_group: false8need_reply: false9is_web: 010#command**/11 12/**#command13name: *14answer:15keyboard:16parse_mode: markdown17aliases:18allow_only_group: false19need_reply: 020case_insensitive: false21is_web: 022#command**/23 24let uid = Number(user.telegramid || user.id);25let mode = String(await db.user.get("input_mode", ""));26if (!mode) return;27let msg = (update && update.message) ? update.message : (typeof message !== "undefined" ? message : null);28if (!msg) return;29let text = String(msg.text || msg.caption || "").trim();30 31function fileInfo(m) {32  if (m.video) return { type:"video", file_id:m.video.file_id };33  if (m.document) return { type:"document", file_id:m.document.file_id };34  if (m.photo && m.photo.length) return { type:"photo", file_id:m.photo[m.photo.length-1].file_id };35  if (m.animation) return { type:"animation", file_id:m.animation.file_id };36  return null;37}38 39async function inputAudit(action,target,details){40  let logs=await db.bot.get("audit_logs",[]);if(!Array.isArray(logs))logs=[];41  logs.push({id:"AUD-"+Date.now()+"-"+Math.floor(Math.random()*100000),action:String(action),target_user_id:Number(target||0)||undefined,details:details||{},by:uid,at:Date.now()});42  await db.bot.set("audit_logs",logs.slice(-1000));43}44 45async function inputNotify(payload,kind,target){46  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;}47}48 49if (mode === "other_asset_name") {50  if (!text || text.length > 20) { Bot.sendMessage("Send a short asset name/symbol, e.g. AVAX."); return; }51  let symbol = text.toUpperCase();52  let assets = await db.user.get("assets", []); if (!Array.isArray(assets)) assets = [];53  if (!assets.includes(symbol)) assets.push(symbol);54  await db.user.set("assets", assets);55  await db.user.del("input_mode");56  Bot.runCommand("/handle_callback_query", { route: "user_core assets" });57  return;58}59 60if (mode === "wallet_address") {61  if (!text || text.length < 12 || text.length > 140 || /\s/.test(text)) {62    Bot.sendMessage("⚠️ That does not look like a valid public wallet address. Check it and send it again.");63    return;64  }65  let asset = String(await db.user.get("current_wallet_asset", "OTHER"));66  let network = String(await db.user.get("current_wallet_network", "MANUAL"));67  let wallets = await db.user.get("wallets", []); if (!Array.isArray(wallets)) wallets = [];68  if (wallets.some(w => String(w.address).toLowerCase() === text.toLowerCase() && w.network === network)) {69    Bot.sendMessage("That wallet is already added.");70    return;71  }72  wallets.push({ asset:asset, network:network, address:text, added_at:Date.now(), verification_status:"pending" });73  await db.user.set("wallets", wallets);74  let memberStatus=String(await db.user.get("member_status","")||"");75  if(["active","approved_pending_join"].includes(memberStatus)){76    await db.user.set("wallet_change_pending",true);await db.user.set("reverification_status","requested");await db.user.set("reverification_type","wallet");77    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);}78    let settings=await db.bot.get("system_settings",{});if(!settings||typeof settings!=="object")settings={};let owner=Number(settings.owner_id||771142220);await inputNotify({chat_id:owner,text:"👛 <b>MEMBER WALLET CHANGE</b>\n\nMember <code>"+uid+"</code> added a new public wallet. It is pending admin verification; previous wallet history is retained.",parse_mode:"HTML"},"member_wallet_change",owner);await inputAudit("member_wallet_added_pending",uid,{asset:asset,network:network});79  }80  await db.user.del("input_mode");81  Bot.sendMessage("✅ Wallet saved. Checking public balance/value where supported…"+(memberStatus?" Admin verification remains pending.":""));82  Bot.runCommand("/handle_callback_query", { route: "user_core wallet_recheck" });83  return;84}85 86if (mode === "ownership_proof") {87  let f = fileInfo(msg);88  if (!f || !["video","document","animation"].includes(f.type)) {89    Bot.sendMessage("Send a video/screen recording, document or animation as ownership proof.");90    return;91  }92  f.submitted_at = Date.now();93  await db.user.set("ownership_proof", f);94  await db.user.del("input_mode");95  Bot.sendMessage("✅ Ownership proof received.");96  Bot.runCommand("/handle_callback_query", { route: "user_core deal_proof" });97  return;98}99 100if (mode === "deal_proof") {101  let f = fileInfo(msg);102  if (!f) { Bot.sendMessage("Send a photo, video or document containing your deal-history proof."); return; }103  f.submitted_at = Date.now();104  let proofs = await db.user.get("deal_proofs", []); if (!Array.isArray(proofs)) proofs = [];105  proofs.push(f);106  await db.user.set("deal_proofs", proofs);107  Bot.sendMessage("✅ Deal proof received. Total proofs: " + proofs.length + ". Send another proof or tap Finish Proof Upload.");108  return;109}110 111if (mode === "reverify_ownership_proof") {112  let f=fileInfo(msg); if(!f||!["video","document","animation"].includes(f.type)){Bot.sendMessage("Send a video/screen recording, document or animation.");return;} f.submitted_at=Date.now();await db.user.set("reverify_ownership_proof",f);await db.user.del("input_mode");Bot.sendMessage("✅ Updated ownership proof received.");Bot.runCommand("/handle_callback_query",{route:"user_core reverify_start"});return;113}114if (mode === "reverify_deal_proof") {115  let f=fileInfo(msg);if(!f){Bot.sendMessage("Send a photo, video or document.");return;}f.submitted_at=Date.now();let p=await db.user.get("reverify_deal_proofs",[]);if(!Array.isArray(p))p=[];p.push(f);await db.user.set("reverify_deal_proofs",p);Bot.sendMessage("✅ Updated deal proof received. Total: "+p.length+". Send another or tap Done.");return;116}117 118if (mode === "more_info_response") {119  let f = fileInfo(msg);120  let item = { text:text || "", file:f, submitted_at:Date.now() };121  let hist = await db.user.get("more_info_history", []); if (!Array.isArray(hist)) hist = [];122  hist.push(item);123  await db.user.set("more_info_history", hist);124  await db.user.set("latest_more_info_response", item);125  await db.user.set("application_status", "submitted");126  await db.user.del("input_mode");127  let queue = await db.bot.get("application_queue", []); if (!Array.isArray(queue)) queue = [];128  for (let q of queue) if (Number(q.user_id) === uid) { q.status = "submitted"; q.more_info_received_at = Date.now(); }129  await db.bot.set("application_queue", queue);130  let settings = await db.bot.get("system_settings", {}); if (!settings || typeof settings !== "object") settings = {};131  let owner = Number(settings.owner_id || 771142220);132  await inputNotify({ chat_id:owner, text:"📝 Additional information received from user <code>"+uid+"</code>.", parse_mode:"HTML", reply_markup:{inline_keyboard:[[{text:"🧿 Review",callback_data:"admin_core app:"+uid,style:"primary"}]]} },"more_info_response",owner);133  Bot.sendMessage("✅ Additional information submitted. Your application has returned to the review queue.");134  return;135}136 137if (mode === "support_message") {138  let settings = await db.bot.get("system_settings", {}); if (!settings || typeof settings !== "object") settings = {};139  let owner = Number(settings.owner_id || 771142220);140  let f = fileInfo(msg);141  await inputNotify({ chat_id:owner, text:"✉ <b>SUPPORT MESSAGE</b>\n\nFrom: <code>"+uid+"</code>\nUsername: "+(user.username?"@"+user.username:"—")+"\n\n"+(text||"[media attached]"), parse_mode:"HTML" },"support_message",owner);142  if (f) {143    let method = f.type === "photo" ? "sendPhoto" : f.type === "video" ? "sendVideo" : f.type === "animation" ? "sendAnimation" : "sendDocument";144    let key = f.type === "photo" ? "photo" : f.type;145    let payload = { chat_id:owner }; payload[key] = f.file_id;146    await Api.call(method, payload);147  }148  await db.user.del("input_mode");149  Bot.sendMessage("✅ Your support message has been sent.");150  return;151}152 153if (mode === "staff_set_pin" || mode === "staff_login_pin") {154  let authSettings=await db.bot.get("system_settings",{});if(!authSettings||typeof authSettings!=="object")authSettings={};let authOwner=Number(authSettings.owner_id||771142220);let authRegistry=await db.bot.get("admin_registry",[]);if(!Array.isArray(authRegistry))authRegistry=[];let authRec=uid===authOwner?{user_id:uid,role:"owner",revoked:false}:authRegistry.find(x=>x&&Number(x.user_id)===uid&&x.revoked!==true);if(!authRec){await db.user.del("input_mode");Bot.sendMessage("⛔ Admin access is not authorized for this account.");return;}155  let pin=text.trim(); if(!/^\d{6,12}$/.test(pin)){Bot.sendMessage("⚠️ PIN must contain 6–12 digits.");return;}156  if(!modules || !modules.bcrypt){Bot.sendMessage("⛔ Secure bcrypt module is unavailable in this runtime.");return;}157  if(mode==="staff_set_pin") { let hash=await modules.bcrypt.hash(pin,10);await db.user.set("staff_pin_hash",hash);await db.user.set("staff_session_until",Date.now()+30*60*1000);await db.user.del("staff_auth_failures");await db.user.del("staff_auth_lock_until");await db.user.del("input_mode");await inputAudit("staff_pin_configured",uid,{});Bot.sendMessage("✅ Staff PIN saved. Secure session active for 30 minutes.");Bot.runCommand("/handle_callback_query",{route:"admin_core home"});return; }158  let lock=Number(await db.user.get("staff_auth_lock_until",0)||0);if(lock>Date.now()){await db.user.del("input_mode");Bot.sendMessage("⛔ Login is temporarily locked.");return;}159  let hash=String(await db.user.get("staff_pin_hash","")||""),valid=hash?await modules.bcrypt.compare(pin,hash):false;160  if(!valid){let failures=Number(await db.user.get("staff_auth_failures",0)||0)+1;if(failures>=5){await db.user.set("staff_auth_lock_until",Date.now()+15*60*1000);failures=0;}await db.user.set("staff_auth_failures",failures);Bot.sendMessage("❌ Invalid PIN."+(failures===0?" Login locked for 15 minutes.":""));return;}161  await db.user.set("staff_session_until",Date.now()+30*60*1000);await db.user.del("staff_auth_failures");await db.user.del("staff_auth_lock_until");await db.user.del("input_mode");await inputAudit("staff_login_success",uid,{});Bot.sendMessage("✅ Staff authentication successful. Session active for 30 minutes.");Bot.runCommand("/handle_callback_query",{route:"admin_core home"});return;162}163 164if (mode.indexOf("admin_") === 0) {165  let settings = await db.bot.get("system_settings", {}); if (!settings || typeof settings !== "object") settings = {};166  let owner = Number(settings.owner_id || 771142220);167  let registry = await db.bot.get("admin_registry", []); if (!Array.isArray(registry)) registry = [];168  let rec = uid === owner ? {user_id:uid,role:"owner",revoked:false} : registry.find(x=>x&&Number(x.user_id)===uid&&x.revoked!==true);169  if (!rec) { await db.user.del("input_mode"); return; }170  let allPerms=["dashboard","applications","review","approve","reject","more_info","override","members","wallets","reverify","alerts","blacklist","rules","settings","assets","p2p","announcements","analytics","admins","audit","backup","maintenance","system"];171  let role=String(rec.role||"support"), perms = (role==="owner"||role==="super_admin") ? allPerms : role==="verification_staff" ? ["dashboard","applications","review","approve","reject","more_info","members","wallets","reverify","alerts","analytics"] : role==="moderator" ? ["dashboard","members","alerts","blacklist","rules","announcements","audit"] : role==="support" ? ["dashboard","applications","members"] : [];172  let need = mode==="admin_set_crypto"||mode==="admin_set_deals" ? "wallets" : mode==="admin_reject_reason" ? "reject" : mode==="admin_custom_message"||mode==="admin_more_info" ? "more_info" : mode.startsWith("admin_setting_") ? "settings" : mode==="admin_override_reason" ? "override" : mode==="admin_member_note" ? "members" : mode==="admin_blacklist_id"||mode==="admin_blacklist_reason" ? "blacklist" : mode.startsWith("admin_rule_") ? "rules" : mode.startsWith("admin_asset_")||mode.startsWith("admin_network_") ? "assets" : mode==="admin_announcement" ? "announcements" : mode==="admin_maintenance_message" ? "maintenance" : mode.startsWith("admin_p2p_") ? "p2p" : mode.startsWith("admin_add_staff") ? "admins" : mode.startsWith("admin_system_") ? "system" : "dashboard";173  let sessionUntil=Number(await db.user.get("staff_session_until",0)||0);174  if (!perms.includes(need) || sessionUntil<=Date.now()) { await db.user.del("input_mode"); Bot.sendMessage("⛔ This staff session is not authorized for that action."); return; }175  let target = Number(await db.user.get("admin_selected_user", 0));176  let noTargetModes = ["admin_blacklist_id","admin_rule_add","admin_rule_edit_title","admin_rule_edit_text","admin_asset_add","admin_announcement","admin_maintenance_message","admin_network_add","admin_p2p_add","admin_add_staff_id","admin_system_channel","admin_system_group"];177  if (!target && !mode.startsWith("admin_setting_") && !noTargetModes.includes(mode)) { Bot.sendMessage("No applicant selected."); return; }178 179  if (mode === "admin_set_crypto") {180    let n = Number(text.replace(/[$,]/g,"")); if (!Number.isFinite(n) || n < 0) { Bot.sendMessage("Send a valid USD amount."); return; }181    let old=Number(await db.user.get("admin_verified_crypto",0,{user_id:target})||0);await db.user.set("admin_verified_crypto", n, {user_id:target}); await db.user.del("input_mode");await inputAudit("verified_crypto_changed",target,{old_value:old,new_value:n});182    Bot.sendMessage("✅ Verified crypto value saved: $"+n); Bot.runCommand("/handle_callback_query",{route:"admin_core app:"+target}); return;183  }184  if (mode === "admin_set_deals") {185    let n = Number(text.replace(/[$,]/g,"")); if (!Number.isFinite(n) || n < 0) { Bot.sendMessage("Send a valid USD amount."); return; }186    let old=Number(await db.user.get("admin_verified_deals",0,{user_id:target})||0);await db.user.set("admin_verified_deals", n, {user_id:target}); await db.user.del("input_mode");await inputAudit("verified_deals_changed",target,{old_value:old,new_value:n});187    Bot.sendMessage("✅ Verified deal volume saved: $"+n); Bot.runCommand("/handle_callback_query",{route:"admin_core app:"+target}); return;188  }189  if (mode === "admin_reject_reason") {190    if (!text) { Bot.sendMessage("Send a rejection reason."); return; }191    await db.user.del("input_mode"); Bot.runCommand("/handle_callback_query", {route:"admin_core reject_do:"+target+":"+encodeURIComponent(text)}); return;192  }193  if (mode === "admin_custom_message") {194    if (!text) { Bot.sendMessage("Send the message text."); return; }195    await db.user.del("input_mode");196    Api.sendMessage({chat_id:target,text:"✉ <b>MESSAGE FROM RED EYE ADMIN</b>\n\n"+text,parse_mode:"HTML"});197    let hist=await db.user.get("admin_message_history",[],{user_id:target});if(!Array.isArray(hist))hist=[];hist.push({text:text,by:uid,at:Date.now()});await db.user.set("admin_message_history",hist.slice(-100),{user_id:target});198    let audit=await db.bot.get("audit_logs",[]);if(!Array.isArray(audit))audit=[];audit.push({id:"AUD-"+Date.now(),action:"admin_custom_message",target_user_id:target,by:uid,at:Date.now()});await db.bot.set("audit_logs",audit.slice(-1000));199    Bot.sendMessage("✅ Message sent."); Bot.runCommand("/handle_callback_query",{route:"admin_core app:"+target}); return;200  }201  if (mode === "admin_more_info") {202    if (!text) { Bot.sendMessage("Send the information request."); return; }203    await db.user.del("input_mode"); Bot.runCommand("/handle_callback_query", {route:"admin_core moreinfo_do:"+target+":"+encodeURIComponent(text)}); return;204  }205  if (mode.startsWith("admin_setting_")) {206    let key = mode.replace("admin_setting_","");207    let n = Number(text.replace(/[$,]/g,""));208    if (!["min_crypto_networth","min_deal_volume","low_wallet_threshold","low_wallet_clear_threshold","low_wallet_duration_days","rejection_cooldown_hours","extended_cooldown_hours","application_reminder_minutes","application_expiry_hours","verification_expiry_days"].includes(key) || !Number.isFinite(n) || n < 0) { Bot.sendMessage("Send a valid numeric setting value."); return; }209    let old=settings[key];settings[key] = n; await db.bot.set("system_settings", settings); await db.user.del("input_mode");await inputAudit("setting_changed",0,{key:key,old_value:old,new_value:n}); Bot.sendMessage("✅ Setting updated."); Bot.runCommand("/handle_callback_query", { route: "admin_core settings" }); return;210  }211  if (mode === "admin_override_reason") {212    if (!text) { Bot.sendMessage("Send a mandatory override reason."); return; }213    await db.user.del("input_mode"); Bot.runCommand("/handle_callback_query", {route:"admin_core override_do:"+target+":"+encodeURIComponent(text)}); return;214  }215  if (mode === "admin_member_note") {216    if (!text) { Bot.sendMessage("Send a note."); return; }217    let notes=await db.user.get("admin_notes",[],{user_id:target});if(!Array.isArray(notes))notes=[];notes.push({text:text,by:uid,at:Date.now()});await db.user.set("admin_notes",notes.slice(-100),{user_id:target});await db.user.del("input_mode");await inputAudit("member_note_added",target,{});Bot.sendMessage("✅ Note saved.");Bot.runCommand("/handle_callback_query",{route:"admin_core member:"+target});return;218  }219  if (mode === "admin_blacklist_id") {220    let id=Number(text);if(!id||id<=0){Bot.sendMessage("Send a valid numeric Telegram user ID.");return;}await db.user.set("admin_selected_user",id);await db.user.set("input_mode","admin_blacklist_reason");Bot.sendMessage("Now send the blacklist reason.");return;221  }222  if (mode === "admin_blacklist_reason") {223    if(!text){Bot.sendMessage("Send the blacklist reason.");return;}let bl=await db.bot.get("blacklist",[]);if(!Array.isArray(bl))bl=[];let prevApp=String(await db.user.get("application_status","",{user_id:target})||""),prevMember=String(await db.user.get("member_status","",{user_id:target})||"");bl=bl.filter(x=>Number(x.user_id)!==target);bl.push({user_id:target,reason:text,blacklisted_at:Date.now(),blacklisted_by:uid,previous_application_status:prevApp,previous_member_status:prevMember});await db.bot.set("blacklist",bl);await db.user.set("pre_blacklist_application_status",prevApp,{user_id:target});await db.user.set("pre_blacklist_member_status",prevMember,{user_id:target});await db.user.set("application_status","blacklisted",{user_id:target});if(prevMember)await db.user.set("member_status","blacklisted",{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.pre_blacklist_status=m.status;m.status="blacklisted";m.updated_at=Date.now();}await db.bot.set("member_registry",members);await db.user.set("blacklist_reason",text,{user_id:target});await db.user.del("input_mode");await inputAudit("user_blacklisted",target,{reason:text,previous_application_status:prevApp,previous_member_status:prevMember});await inputNotify({chat_id:target,text:"⛔ <b>RED EYE ACCESS RESTRICTED</b>\n\nYour account has been blocked from the application system.\nReason: "+text,parse_mode:"HTML"},"blacklist_notice",target);Bot.sendMessage("✅ User blacklisted.");Bot.runCommand("/handle_callback_query", { route: "admin_core blacklist" });return;224  }225  if (mode === "admin_rule_add") {226    let parts=text.split("|");if(parts.length<3){Bot.sendMessage("Use: Category | Title | Full rule text");return;}let category=parts.shift().trim(),title=parts.shift().trim(),body=parts.join("|").trim();let cats=["General","P2P","OTC","NFT","Advertising","DM","Scam/Fraud","Conduct"];if(!cats.includes(category)){Bot.sendMessage("Category must be one of: "+cats.join(", "));return;}if(!title||!body){Bot.sendMessage("Title and rule text are required.");return;}let rules=await db.bot.get("rules",[]);if(!Array.isArray(rules))rules=[];let rec={id:"RULE-"+Date.now(),category:category,title:title,text:body,enabled:true,version:1,created_at:Date.now(),created_by:uid};rules.push(rec);await db.bot.set("rules",rules);let h=await db.bot.get("rule_history",[]);if(!Array.isArray(h))h=[];h.push({rule_id:rec.id,change:"created",snapshot:rec,by:uid,at:Date.now()});await db.bot.set("rule_history",h.slice(-500));let audit=await db.bot.get("audit_logs",[]);if(!Array.isArray(audit))audit=[];audit.push({id:"AUD-"+Date.now(),action:"rule_added",details:{title:title,category:category},by:uid,at:Date.now()});await db.bot.set("audit_logs",audit.slice(-1000));await db.user.del("input_mode");Bot.runCommand("/handle_callback_query", { route: "admin_core rules" });return;227  }228  if (mode === "admin_rule_edit_title" || mode === "admin_rule_edit_text") {229    let i=Number(await db.user.get("admin_selected_rule",-1));let rules=await db.bot.get("rules",[]);if(!Array.isArray(rules)||!rules[i]){Bot.sendMessage("Rule not found.");await db.user.del("input_mode");return;}if(!text){Bot.sendMessage("Value cannot be empty.");return;}let field=mode==="admin_rule_edit_title"?"title":"text",old=rules[i][field];rules[i][field]=text;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:"edit_"+field,old_value:old,new_value:text,version:rules[i].version,by:uid,at:Date.now()});await db.bot.set("rule_history",h.slice(-500));await db.user.del("input_mode");await inputAudit("rule_edited",0,{rule_id:rules[i].id,field:field,old_value:old,new_value:text});Bot.runCommand("/handle_callback_query",{route:"admin_core rule_view:"+i});return;230  }231  if (mode === "admin_asset_add") {232    let symbol=text.toUpperCase().replace(/[^A-Z0-9._-]/g,"").slice(0,15);if(!symbol){Bot.sendMessage("Send a valid asset symbol.");return;}let assets=Array.isArray(settings.featured_assets)?settings.featured_assets:["USDT","SOL","ETH","BTC","TON"];if(!assets.includes(symbol))assets.push(symbol);settings.featured_assets=assets;await db.bot.set("system_settings",settings);await db.user.del("input_mode");await inputAudit("asset_added",0,{symbol:symbol});Bot.runCommand("/handle_callback_query", { route: "admin_core assets" });return;233  }234  if (mode === "admin_announcement") {235    if(!text){Bot.sendMessage("Announcement text cannot be empty.");return;}await db.user.set("pending_announcement",text);await db.user.del("input_mode");Api.sendMessage({chat_id:chat.id,text:"📣 <b>CONFIRM ANNOUNCEMENT</b>\n\n"+text,parse_mode:"HTML",reply_markup:{inline_keyboard:[[{text:"✅ Send to Members",callback_data:"admin_core announcement_confirm",style:"success"},{text:"✕ Cancel",callback_data:"admin_core announcement_cancel",style:"danger"}]]}});return;236  }237  if (mode === "admin_network_add") { let parts=text.split("|");if(parts.length<2){Bot.sendMessage("Use: ASSET | NETWORK1, NETWORK2");return;}let asset=parts.shift().trim().toUpperCase(),nets=parts.join("|").split(",").map(x=>x.trim().toUpperCase()).filter(Boolean);if(!asset||!nets.length){Bot.sendMessage("Asset and at least one network are required.");return;}let map=settings.asset_networks;if(!map||typeof map!=="object")map={};map[asset]=Array.from(new Set(nets));settings.asset_networks=map;await db.bot.set("system_settings",settings);await db.user.del("input_mode");await inputAudit("asset_networks_changed",0,{asset:asset,networks:map[asset]});Bot.runCommand("/handle_callback_query",{route:"admin_core networks"});return; }238  if (mode === "admin_p2p_add") { let parts=text.split("|");if(parts.length<2){Bot.sendMessage("Use: Name | @username_or_chat_id");return;}let name=parts.shift().trim(),ref=parts.join("|").trim();if(!name||!ref){Bot.sendMessage("Both values are required.");return;}let g=await db.bot.get("p2p_groups",[]);if(!Array.isArray(g))g=[];g.push({id:"P2P-"+Date.now(),name:name,reference:ref,enabled:true,created_at:Date.now(),created_by:uid});await db.bot.set("p2p_groups",g);await db.user.del("input_mode");await inputAudit("p2p_group_added",0,{name:name,reference:ref});Bot.runCommand("/handle_callback_query",{route:"admin_core p2p"});return; }239  if (mode === "admin_add_staff_id") { let id=Number(text);if(!id||id<=0){Bot.sendMessage("Send a valid numeric Telegram user ID.");return;}let a=await db.bot.get("admin_registry",[]);if(!Array.isArray(a))a=[];if(a.some(x=>x&&Number(x.user_id)===id)){Bot.sendMessage("Admin already exists.");return;}a.push({user_id:id,role:"support",revoked:false,created_at:Date.now(),created_by:uid});await db.bot.set("admin_registry",a);await db.user.del("input_mode");await inputAudit("admin_added",id,{role:"support"});await inputNotify({chat_id:id,text:"👮 You were added as RED EYE staff with Support role. Open /admin and set a secure staff PIN before using protected actions."},"staff_added",id);Bot.runCommand("/handle_callback_query",{route:"admin_core admins"});return; }240  if (mode === "admin_system_channel") { let ch=text.trim();if(!/^@[A-Za-z0-9_]{5,}$/.test(ch)){Bot.sendMessage("Send a valid @channel username.");return;}let old=settings.official_channel;settings.official_channel=ch;settings.official_channel_url="https://t.me/"+ch.slice(1);await db.bot.set("system_settings",settings);await db.user.del("input_mode");await inputAudit("official_channel_changed",0,{old_value:old,new_value:ch});Bot.runCommand("/handle_callback_query",{route:"admin_core system"});return; }241  if (mode === "admin_system_group") { let id=Number(text);if(!Number.isFinite(id)||id>=0){Bot.sendMessage("Send a valid negative Telegram group/channel ID, usually -100…");return;}let old=settings.private_group_id;settings.private_group_id=id;await db.bot.set("system_settings",settings);await db.user.del("input_mode");await inputAudit("private_group_changed",0,{old_value:old,new_value:id});Bot.runCommand("/handle_callback_query",{route:"admin_core system"});return; }242  if (mode === "admin_maintenance_message") {243    if(!text){Bot.sendMessage("Message cannot be empty.");return;}let old=settings.maintenance_message;settings.maintenance_message=text;await db.bot.set("system_settings",settings);await db.user.del("input_mode");await inputAudit("maintenance_message_changed",0,{old_value:old,new_value:text});Bot.runCommand("/handle_callback_query", { route: "admin_core maintenance_page" });return;244  }245 246}