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 · 125 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: true21is_web: 022#command**/23 24let __s = await db.bot.get("system_settings", {}); if (!__s || typeof __s !== "object") __s = {};25const __OWNER = Number(__s.owner_id || 771142220);26const __PRIVATE = Number(__s.private_group_id || -1004382007648);27const __now = Date.now();28 29async function __audit(action,target,details){30  let logs=await db.bot.get("audit_logs",[]);if(!Array.isArray(logs))logs=[];31  logs.push({id:"AUD-"+Date.now()+"-"+Math.floor(Math.random()*100000),action:action,target_user_id:Number(target||0)||undefined,details:details||{},by:0,at:Date.now()});32  await db.bot.set("audit_logs",logs.slice(-1000));33}34 35async function __safeNotify(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){37    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;38  }39}40async function __retryNotifications(){41  let q=await db.bot.get("notification_retry_queue",[]);if(!Array.isArray(q)||!q.length)return {sent:0,pending:0,dropped:0};let now=Date.now(),out=[],sent=0,dropped=0;42  for(let n of q){if(!n||!n.payload)continue;if(Number(n.next_retry_at||0)>now){out.push(n);continue;}try{let r=await Api.sendMessage(n.payload);if(r&&r.ok===false)throw new Error("send_failed");sent++;}catch(e){n.attempts=Number(n.attempts||0)+1;if(n.attempts>=5){dropped++;await __audit("notification_retry_exhausted",n.target_user_id,{kind:n.kind,attempts:n.attempts});}else{n.next_retry_at=now+Math.min(60,5*Math.pow(2,n.attempts-1))*60000;out.push(n);}}}43  await db.bot.set("notification_retry_queue",out.slice(-500));return {sent:sent,pending:out.length,dropped:dropped};44}45 46// ======================================================47// SECURE JOIN REQUEST GATE48// ======================================================49if (typeof update_type !== "undefined" && update_type === "chat_join_request" && typeof update !== "undefined" && update && update.chat_join_request) {50  let jr=update.chat_join_request;51  if(Number(jr.chat && jr.chat.id)===__PRIVATE){52    let requester=Number(jr.from && jr.from.id),used=jr.invite_link&&jr.invite_link.invite_link?String(jr.invite_link.invite_link):"";53    let invites=await db.bot.get("secure_invites",[]);if(!Array.isArray(invites))invites=[];54    let rec=invites.find(x=>x&&String(x.invite_link)===used);55    if(!rec){56      await Api.call("declineChatJoinRequest",{chat_id:__PRIVATE,user_id:requester});57      await __audit("join_request_declined_unknown_link",requester,{});58    } else {59      let exp=Number(rec.expires_at||0)*1000,wrong=Number(rec.user_id)!==requester,expired=exp&&Date.now()>exp,already=rec.used===true;60      if(wrong||expired||already){61        await Api.call("declineChatJoinRequest",{chat_id:__PRIVATE,user_id:requester});62        if(wrong) {63          Api.sendMessage({chat_id:__OWNER,text:"🚨 <b>UNAUTHORIZED JOIN REQUEST BLOCKED</b>\n\nExpected: <code>"+Number(rec.user_id)+"</code>\nAttempted: <code>"+requester+"</code>\n\nThis is recorded only as a review signal, not an accusation.",parse_mode:"HTML"});64          let flags=await db.bot.get("risk_flags",[]);if(!Array.isArray(flags))flags=[];flags.push({id:"RISK-"+requester+"-"+Date.now(),user_id:requester,type:"unauthorized_invite_attempt",status:"open",details:{expected_user_id:Number(rec.user_id)},created_at:Date.now()});await db.bot.set("risk_flags",flags.slice(-1000));65        }66        await __audit("join_request_declined",requester,{wrong_user:wrong,expired:!!expired,already_used:already});67      } else {68        let r=await Api.call("approveChatJoinRequest",{chat_id:__PRIVATE,user_id:requester});69        if(r&&r.ok){70          rec.used=true;rec.used_at=Date.now();await db.bot.set("secure_invites",invites);71          await db.user.set("member_status","active",{user_id:requester});await db.user.set("community_joined_at",Date.now(),{user_id:requester});await db.user.set("private_invite_last_used",used,{user_id:requester});await db.user.del("private_invite_link",{user_id:requester});72          let members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];let i=members.findIndex(x=>x&&Number(x.user_id)===requester);if(i>=0){members[i].status="active";members[i].joined_at=Date.now();members[i].updated_at=Date.now();}else members.push({user_id:requester,status:"active",joined_at:Date.now(),updated_at:Date.now()});await db.bot.set("member_registry",members);73          try{await Api.call("revokeChatInviteLink",{chat_id:__PRIVATE,invite_link:used});}catch(e){}74          await __safeNotify({chat_id:requester,text:"✦ <b>WELCOME TO RED EYE</b>\n\nYour identity-matched join request was approved. Your personal invite has been consumed and revoked.",parse_mode:"HTML"},"member_joined",requester);75          await __safeNotify({chat_id:__OWNER,text:"✅ <b>VERIFIED MEMBER JOINED</b>\n\nUser: <code>"+requester+"</code>",parse_mode:"HTML"},"member_joined_admin",__OWNER);76          await __audit("secure_invite_consumed",requester,{invite:used});77        }78      }79    }80  }81}82 83// ======================================================84// OPPORTUNISTIC BACKGROUND LIFECYCLE TICK85// Runs at most once every five minutes while the bot is receiving updates.86// ======================================================87let __lastTick=Number(await db.bot.get("automatic_tick_last_run",0)||0);88if(!__lastTick || __now-__lastTick>=5*60*1000){89  await db.bot.set("automatic_tick_last_run",__now);90  let q=await db.bot.get("application_queue",[]);if(!Array.isArray(q))q=[];91  let reminderMs=Number(__s.application_reminder_minutes||60)*60000,expiryMs=Number(__s.application_expiry_hours||24)*3600000;92  let reminded=0,expired=0;93  for(let item of q){94    if(!item||!item.user_id||String(item.status)!=="started")continue;95    let started=Number(item.started_at||item.last_activity_at||0),last=Number(item.last_activity_at||started||0);96    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)});await __safeNotify({chat_id:Number(item.user_id),text:"⌛ Your RED EYE application expired after the configured application window. You can start a new application if eligible."},"application_expired",item.user_id);expired++;}97    else if(last&&!item.reminder_sent_at&&__now-last>=reminderMs){item.reminder_sent_at=__now;await __safeNotify({chat_id:Number(item.user_id),text:"⏰ Reminder: your RED EYE application is still incomplete. Open /start to continue."},"application_reminder",item.user_id);reminded++;}98  }99  await db.bot.set("application_queue",q);100  if(reminded||expired)await __audit("automatic_application_lifecycle",0,{reminded:reminded,expired:expired});101 102  // Expire unused personal invite links and remove stale join buttons from user status.103  let __inv=await db.bot.get("secure_invites",[]);if(!Array.isArray(__inv))__inv=[];let __invChanged=false;for(let rec of __inv){if(!rec||rec.used===true||rec.expired===true)continue;let t=Number(rec.expires_at||0)*1000;if(t&&__now>t){rec.expired=true;rec.expired_at=__now;__invChanged=true;let cur=String(await db.user.get("private_invite_link","",{user_id:Number(rec.user_id)})||"");if(cur&&cur===String(rec.invite_link))await db.user.del("private_invite_link",{user_id:Number(rec.user_id)});}}if(__invChanged)await db.bot.set("secure_invites",__inv);104 105  // Optional verification-expiry alert. Expiry never removes a member automatically.106  if(__s.verification_expiry_enabled===true){107    let days=Number(__s.verification_expiry_days||30),members=await db.bot.get("member_registry",[]);if(!Array.isArray(members))members=[];let alerts=await db.bot.get("alerts",[]);if(!Array.isArray(alerts))alerts=[];108    for(let m of members){if(!m||!m.user_id||m.status==="removed")continue;let at=Number(m.verified_at||m.approved_at||0);if(at&&__now-at>=days*86400000&&!alerts.some(a=>a&&a.status!=="resolved"&&a.type==="verification_expiry"&&Number(a.user_id)===Number(m.user_id))){alerts.push({id:"EXP-"+m.user_id+"-"+__now,type:"verification_expiry",user_id:Number(m.user_id),status:"open",created_at:__now});await __safeNotify({chat_id:__OWNER,text:"⏳ <b>VERIFICATION EXPIRY ALERT</b>\n\nMember: <code>"+Number(m.user_id)+"</code>\nAdmin review/re-verification may be requested. No automatic removal was performed.",parse_mode:"HTML"},"verification_expiry",__OWNER);}}109    await db.bot.set("alerts",alerts.slice(-1000));110  }111 112  // Automatic daily non-sensitive snapshot where bot storage is available.113  let __lastBackup=Number(await db.bot.get("automatic_backup_last_run",0)||0);114  if(!__lastBackup||__now-__lastBackup>=24*3600000){115    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 backs=await db.bot.get("backups",[]);if(!Array.isArray(backs))backs=[];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}));116    backs.push({id:"AUTO-BKP-"+__now,created_at:__now,created_by:"system",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});117    await db.bot.set("backups",backs.slice(-30));await db.bot.set("automatic_backup_last_run",__now);118  }119}120 121// Signed/global webhook entry point: delegate expensive monitoring to the dedicated worker.122// Normal Telegram updates never invoke this path.123if (typeof options !== "undefined" && options && options.worker === true) {124  Bot.runCommand("/worker", { source: "global_webhook" });125}