CREATORS/OnecreatorsbotPublic · Bot Template

ProfileTelegram

AIThe bot manages a membership club called CREATORS. Users can apply for membership, view their status, and receive payment instructions. Administrators can approve or reject applications, set subscription prices, configure payment details, and review pending payments. The bot stores data in a database, sends notifications to users and admins, and handles payment receipts via photo or document uploads.

Commercemembershipsubscriptionpaymentsadmincreatortelegram
22 commands1 envUpdated 20d agoCreated Oct 6, 2026
Back to folder

commands/_handle_callback_query.js

javascript · 1453 lines

Raw
1/**#command2name: /handle_callback_query3answer: 4keyboard: 5parse_mode: markdown6aliases: 7allow_only_group: false8need_reply: false9is_web: 010#command**/11 12const data = update.callback_query.data || "";13const callbackId = update.callback_query.id;14const callbackMessage = update.callback_query.message;15const adminId = String(process.env.ADMIN_ID);16 17if (data === "choose_weekly" || data === "choose_monthly") {18const selectedPlan = data === "choose_weekly" ? "weekly" : "monthly";19const planName = data === "choose_weekly" ? "اشتراک هفتگی" : "اشتراک ماهانه";20const duration = data === "choose_weekly" ? 7 : 30;21 22const rawPrice = data === "choose_weekly"23? "500000"24: await db.bot.get("subscription_price", "2000000");25 26const price = Number(rawPrice);27 28if (!Number.isFinite(price) || price <= 0) {29await Api.answerCallbackQuery({30callback_query_id: callbackId,31text: "قیمت این طرح معتبر نیست."32});33return;34}35 36const card = await db.bot.get("payment_card", "");37const owner = await db.bot.get("payment_owner", "");38const bank = await db.bot.get("payment_bank", "");39 40if (!card || !owner || !bank) {41await Api.answerCallbackQuery({42callback_query_id: callbackId,43text: "اطلاعات پرداخت هنوز کامل تنظیم نشده است."44});45return;46}47 48await db.user.set("selected_plan", selectedPlan, {49user_id: Number(user.id)50});51 52await db.user.set("selected_plan_price", String(price), {53user_id: Number(user.id)54});55 56await db.user.set("selected_plan_duration", String(duration), {57user_id: Number(user.id)58});59 60 61await db.user.set(62  "awaiting_payment_receipt",63  "yes",64  { user_id: Number(user.id) }65);66  67await Api.answerCallbackQuery({68callback_query_id: callbackId,69text: "طرح انتخاب شد."70});71 72await Api.sendMessage({73chat_id: callbackMessage.chat.id,74text:75"✦━━━━━━━━━━━━━━━━━━✦\n" +76"       C R E A T O R S\n" +77"✦━━━━━━━━━━━━━━━━━━✦\n\n" +78"👑 طرح انتخابی: " + planName + "\n" +79"🗓 مدت: " + duration + " روز\n" +80"💰 مبلغ: " + price.toLocaleString("fa-IR") + " تومان\n\n" +81 82  "🏦 بانک: " + bank + "\n" +83 84 85  86  "👤 صاحب کارت: " + owner + "\n" +87   "💳 شماره کارت:\n" + card + "\n\n" 88  +89 90  "پس از واریز لطفا رسيد پرداخت را ارسال كنيد .\n" +91 92  "اشتراک پس از بررسی فعال خواهد شد.",93reply_markup: {94inline_keyboard: [95[96{97text: "📤 ارسال رسید پرداخت",98callback_data: "payment_done"99 100}101]102]103}104});105 106return;107}108 109 110if (data === "payment_done") {111  const userId = Number(user.id);112 113  const selectedPlan = await db.user.get(114    "selected_plan",115    "",116    { user_id: userId }117  );118 119  if (!selectedPlan) {120    await Api.answerCallbackQuery({121      callback_query_id: callbackId,122      text: "لطفاً ابتدا یکی از طرح‌های اشتراک را انتخاب کن."123    });124    return;125  }126 127  await db.user.set(128    "awaiting_payment_receipt",129    "yes",130    { user_id: userId }131  );132 133  await Api.answerCallbackQuery({134    callback_query_id: callbackId,135    text: "منتظر ارسال رسید هستیم."136  });137 138  await Api.sendMessage({139    chat_id: callbackMessage.chat.id,140    text:141      "✦━━━━━━━━━━━━━━━━━━✦\n" +142      "       C R E A T O R S\n" +143      "✦━━━━━━━━━━━━━━━━━━✦\n\n" +144      "📤 لطفاً رسید پرداخت خود را ارسال کن.\n\n" +145      "می‌توانی یکی از این موارد را بفرستی:\n" +146      "📷 عکس رسید\n" +147      "📄 فایل رسید، مانند PDF\n" +148      "📝 متن رسید و اطلاعات تراکنش\n\n" +149      "پس از دریافت رسید، مدیر پرداخت را بررسی می‌کند.\n" +150      "اشتراک پس از تأیید مدیر فعال خواهد شد."151  });152 153  return;154}155 156// بررسی دسترسی مدیر؛ فقط یک‌بار157if (String(user.id) !== adminId) {158  await Api.answerCallbackQuery({159    callback_query_id: callbackId,160    text: "⛔ دسترسی مجاز نیست."161  });162  return;163}164 165// استخراج شناسه کاربر از callback166function getTargetId(prefix) {167  const rawId = data.substring(prefix.length);168 169  if (!/^\d+$/.test(rawId)) return null;170 171  const id = Number(rawId);172  return Number.isSafeInteger(id) && id > 0 ? id : null;173}174 175// بررسی نتیجه ذخیره‌سازی176function saveSucceeded(result) {177  return Boolean(result && result.ok === true);178}179 180 181/* =========================================182   صفحه‌بندی فهرست اعضا183   ========================================= */184 185if (data.startsWith("members_page_")) {186  const rawPage = data.substring("members_page_".length);187  const requestedPage = Number(rawPage);188 189  if (!/^\d+$/.test(rawPage) ||190      !Number.isSafeInteger(requestedPage) ||191      requestedPage < 1) {192    await Api.answerCallbackQuery({193      callback_query_id: callbackId,194      text: "شماره صفحه معتبر نیست."195    });196    return;197  }198 199  const users = await Bot.getUsers();200  const pageSize = 10;201  const totalPages = Math.max(1, Math.ceil(users.length / pageSize));202  const page = Math.min(requestedPage, totalPages);203  const pageUsers = users.slice((page - 1) * pageSize, page * pageSize);204  const keyboard = [];205 206  for (const rawId of pageUsers) {207    const targetId = Number(rawId);208    if (!Number.isSafeInteger(targetId) || targetId <= 0) continue;209 210    const name = await db.user.get(211      "profile_name", "", { user_id: targetId }212    );213    const username = await db.user.get(214      "profile_username", "", { user_id: targetId }215    );216 217    const labelName = String(name || username || "بدون نام")218      .replace(/[\r\n]+/g, " ")219      .slice(0, 30);220 221    keyboard.push([{222      text: "👤 " + labelName + " | " + targetId,223      callback_data: "member_profile_" + targetId224    }]);225  }226 227  const nav = [];228  if (page > 1) {229    nav.push({230      text: "⬅️ صفحه قبل",231      callback_data: "members_page_" + (page - 1)232    });233  }234  if (page < totalPages) {235    nav.push({236      text: "صفحه بعد ➡️",237      callback_data: "members_page_" + (page + 1)238    });239  }240  if (nav.length) keyboard.push(nav);241 242  await Api.answerCallbackQuery({243    callback_query_id: callbackId,244    text: "صفحه " + page245  });246 247  await Api.sendMessage({248    chat_id: callbackMessage.chat.id,249    text:250      "👑 پنل مدیریت اعضای CREATORS\n" +251      "━━━━━━━━━━━━━━━━━━\n\n" +252      "👥 تعداد کاربران: " + users.length +253      "\n📄 صفحه " + page + " از " + totalPages +254      "\n\nبرای مشاهده پرونده، روی عضو موردنظر بزن.",255    reply_markup: { inline_keyboard: keyboard }256  });257 258  return;259}260 261 262/* =========================================263   پرونده کامل عضو264   ========================================= */265 266if (data.startsWith("member_profile_")) {267  const rawId = data.substring("member_profile_".length);268 269  if (!/^\d+$/.test(rawId)) {270    await Api.answerCallbackQuery({271      callback_query_id: callbackId,272      text: "شناسه عضو معتبر نیست."273    });274    return;275  }276 277  const targetId = Number(rawId);278 279  if (!Number.isSafeInteger(targetId) || targetId <= 0) {280    await Api.answerCallbackQuery({281      callback_query_id: callbackId,282      text: "شناسه عضو معتبر نیست."283    });284    return;285  }286 287  const [288    name,289    username,290    creatorId,291    membershipStatus,292    paymentStatus,293    plan,294    price,295    duration,296    startDate,297    endDate,298    access,299    pendingReceipt300  ] = await Promise.all([301    db.user.get("profile_name", "", { user_id: targetId }),302    db.user.get("profile_username", "", { user_id: targetId }),303    db.user.get("creator_id", "ثبت نشده", { user_id: targetId }),304    db.user.get("membership_status", "ثبت نشده", { user_id: targetId }),305    db.user.get("payment_review_status", "ثبت نشده", { user_id: targetId }),306    db.user.get("selected_plan", "ثبت نشده", { user_id: targetId }),307    db.user.get("selected_plan_price", "", { user_id: targetId }),308    db.user.get("selected_plan_duration", "", { user_id: targetId }),309    db.user.get("subscription_start", "", { user_id: targetId }),310    db.user.get("subscription_end", "", { user_id: targetId }),311    db.user.get("access", {}, { user_id: targetId }),312    db.user.get("pending_payment_receipt", null, { user_id: targetId })313  ]);314 315  const archiveData = await db.bot.get("creators_confirmed_payments", []);316  const archive = Array.isArray(archiveData) ? archiveData : [];317  const memberPayments = archive.filter(318    item => Number(item.user_id) === targetId319  );320 321  function displayDate(value) {322    if (!value) return "ثبت نشده";323    const date = new Date(value);324    if (Number.isNaN(date.getTime())) return String(value);325    return date.toLocaleDateString("fa-IR");326  }327 328  const accessData = access || {};329  const enabledAccess = Object.keys(accessData)330    .filter(key => accessData[key] === true);331 332  let text =333    "👑 پرونده عضو CREATORS\n" +334    "━━━━━━━━━━━━━━━━━━\n\n" +335    "👤 نام: " + String(name || "ثبت نشده") + "\n" +336    "🔹 نام کاربری: " +337      (username ? "@" + String(username).replace(/^@/, "") : "ثبت نشده") + "\n" +338    "🆔 شناسه تلگرام: " + targetId + "\n" +339    "✨ Creator ID: " + String(creatorId || "ثبت نشده") + "\n\n" +340    "📌 وضعیت عضویت: " + String(membershipStatus) + "\n" +341    "💳 وضعیت پرداخت: " + String(paymentStatus) + "\n" +342    "📦 طرح انتخابی: " + String(plan) + "\n" +343    "💰 مبلغ طرح: " +344      (price ? Number(price).toLocaleString("fa-IR") + " تومان" : "ثبت نشده") + "\n" +345    "🗓 مدت طرح: " + (duration ? String(duration) + " روز" : "ثبت نشده") + "\n" +346    "📅 شروع اشتراک: " + displayDate(startDate) + "\n" +347    "📅 پایان اشتراک: " + displayDate(endDate) + "\n\n" +348    "🔓 تعداد دسترسی‌های فعال: " + enabledAccess.length + "\n" +349    (enabledAccess.length ? enabledAccess.join("، ") : "دسترسی فعالی ثبت نشده") + "\n\n" +350    "🧾 رسید در انتظار: " +351      (pendingReceipt && pendingReceipt.receipt_id352        ? pendingReceipt.receipt_id353        : "رسیدی ثبت نشده") + "\n" +354    "🗃 تعداد پرداخت‌های آرشیوشده: " + memberPayments.length;355 356  for (const payment of memberPayments.slice(-5).reverse()) {357    text +=358      "\n\n──────────────\n" +359      "🧾 رسید: " + String(payment.receipt_id || "نامشخص") + "\n" +360      "💰 مبلغ: " +361        (Number(payment.price) > 0362          ? Number(payment.price).toLocaleString("fa-IR") + " تومان"363          : "ثبت نشده") + "\n" +364      "📦 طرح: " + String(payment.plan || "ثبت نشده") + "\n" +365      "📍 وضعیت: " + String(payment.status || "ثبت نشده") + "\n" +366      "📅 زمان تأیید: " + displayDate(payment.approved_at);367  }368 369  await Api.answerCallbackQuery({370    callback_query_id: callbackId,371    text: "پرونده عضو باز شد."372  });373 374  await Api.sendMessage({375    chat_id: callbackMessage.chat.id,376    text: text,377    reply_markup: {378      inline_keyboard: [379        [380          {381            text: "🔐 مدیریت دسترسی‌های این عضو",382            callback_data: "open_manage_" + targetId383          }384        ],385        [386          {387            text: "⬅️ بازگشت به صفحه اول اعضا",388            callback_data: "members_page_1"389          }390        ]391      ]392    }393  });394 395  return;396}397 398 399/* =========================================400   بازکردن پنل مدیریت از پرونده عضو401   ========================================= */402 403if (data.startsWith("open_manage_")) {404  const targetId = getTargetId("open_manage_");405 406  if (!targetId) {407    await Api.answerCallbackQuery({408      callback_query_id: callbackId,409      text: "شناسه عضو معتبر نیست."410    });411    return;412  }413 414  await Api.answerCallbackQuery({415    callback_query_id: callbackId,416    text: "پنل مدیریت عضو باز می‌شود."417  });418 419  await updateManagePanel(targetId);420  return;421}422 423/* =========================================424   فهرست درخواست‌های عضویت و پرداخت425   ========================================= */426 427if (428  data === "requests_membership" ||429  data === "requests_payments"430) {431  const isMembership = data === "requests_membership";432  const users = await Bot.getUsers();433 434  const groups = isMembership435    ? [436        { status: "pending", title: "🕒 در انتظار بررسی" },437        { status: "approved", title: "✅ تأییدشده‌ها" },438        { status: "rejected", title: "❌ ردشده‌ها" }439      ]440    : [441        { status: "pending", title: "🕒 در انتظار بررسی" },442        { status: "approved", title: "✅ تأییدشده‌ها" },443        { status: "rejected", title: "❌ ردشده‌ها" }444      ];445 446  let text = isMembership447    ? "👥 فهرست درخواست‌های عضویت\n"448    : "💳 فهرست رسیدهای پرداخت\n";449 450  text += "━━━━━━━━━━━━━━━━━━\n\n";451 452  for (const group of groups) {453    const matches = [];454 455    for (const id of users) {456      const targetId = Number(id);457 458      const status = await db.user.get(459        isMembership460          ? "membership_status"461          : "payment_review_status",462        "unknown",463        { user_id: targetId }464      );465 466      let belongs = false;467 468      if (isMembership) {469        if (group.status === "approved") {470          belongs = ["approved", "active", "paid"].includes(status);471        } else {472          belongs = status === group.status;473        }474      } else {475        belongs = status === group.status;476      }477 478      if (belongs) matches.push(targetId);479    }480 481    text += group.title + "\n";482 483    if (matches.length === 0) {484      text += "موردی ثبت نشده است.\n\n";485      continue;486    }487 488    text += "تعداد: " + matches.length + "\n";489 490    // برای جلوگیری از طولانی شدن پیام، حداکثر ۲۰ شناسه491    // در هر بخش نمایش داده می‌شود.492    for (const targetId of matches.slice(0, 20)) {493      text += "• شناسه تلگرام: " + targetId + "\n";494    }495 496    if (matches.length > 20) {497      text += "۲۰ مورد اول نمایش داده شده‌اند؛ تعداد کل: " +498        matches.length + "\n";499    }500 501    text += "\n";502  }503 504  await Api.answerCallbackQuery({505    callback_query_id: callbackId,506    text: "فهرست به‌روزرسانی شد."507  });508 509  await Api.sendMessage({510    chat_id: callbackMessage.chat.id,511    text: text,512    reply_markup: {513      inline_keyboard: [514        [515          {516            text: "👥 درخواست‌های عضویت",517            callback_data: "requests_membership"518          }519        ],520        [521          {522            text: "💳 رسیدهای پرداخت",523            callback_data: "requests_payments"524          }525        ],526        [527          {528            text: "🔄 بازگشت به پنل",529            callback_data: "requests_refresh"530          }531        ]532      ]533    }534  });535 536  return;537}538 539if (data === "requests_refresh") {540  await Api.answerCallbackQuery({541    callback_query_id: callbackId,542    text: "برای دیدن آمار جدید، دستور /requests را بفرست."543  });544 545  await Api.sendMessage({546    chat_id: callbackMessage.chat.id,547    text: "برای مشاهده آمار به‌روز پنل مدیریت، دستور زیر را ارسال کن:\n/requests"548  });549 550  return;551}552 553/* =========================================554   تأیید و رد پرداخت اشتراک555   ========================================= */556 557if (558  data.startsWith("payapprove_") ||559  data.startsWith("payreject_")560) {561  const isApproval = data.startsWith("payapprove_");562  const prefix = isApproval ? "payapprove_" : "payreject_";563  const targetUserId = getTargetId(prefix);564 565  if (!targetUserId) {566    await Api.answerCallbackQuery({567      callback_query_id: callbackId,568      text: "شناسه کاربر نامعتبر است."569    });570    return;571  }572 573  const reviewStatus = await db.user.get(574    "payment_review_status",575    "",576    { user_id: targetUserId }577  );578 579  if (reviewStatus !== "pending") {580    await Api.answerCallbackQuery({581      callback_query_id: callbackId,582      text: "این رسید قبلاً بررسی شده یا در انتظار بررسی نیست."583    });584    return;585  }586 587  if (!isApproval) {588    const rejectResult = await db.user.set(589      "payment_review_status",590      "rejected",591      { user_id: targetUserId }592    );593 594    if (!saveSucceeded(rejectResult)) {595      await Api.answerCallbackQuery({596        callback_query_id: callbackId,597        text: "ذخیره نتیجه رد پرداخت ناموفق بود."598      });599      return;600    }601 602    await Api.answerCallbackQuery({603      callback_query_id: callbackId,604      text: "پرداخت رد شد."605    });606 607    try {608      await Api.editMessageCaption({609        chat_id: callbackMessage.chat.id,610        message_id: callbackMessage.message_id,611        caption: "❌ رسید پرداخت رد شد.\nشناسه کاربر: " + targetUserId612      });613    } catch (error) {614      try {615        await Api.editMessageText({616          chat_id: callbackMessage.chat.id,617          message_id: callbackMessage.message_id,618          text: "❌ رسید پرداخت رد شد.\nشناسه کاربر: " + targetUserId619        });620      } catch (ignored) {}621    }622 623    await Api.sendMessage({624      chat_id: targetUserId,625      text:626        "❌ رسید پرداخت شما تأیید نشد.\n\n" +627        "لطفاً اطلاعات پرداخت را بررسی کن و برای ارسال مجدد، " +628        "دکمه «ارسال رسید پرداخت» را در ربات بزن."629    });630 631    return;632  }633 634  const plan = await db.user.get(635    "selected_plan",636    "",637    { user_id: targetUserId }638  );639 640  const duration = Number(await db.user.get(641    "selected_plan_duration",642    "0",643    { user_id: targetUserId }644  ));645 646  const price = Number(await db.user.get(647    "selected_plan_price",648    "0",649    { user_id: targetUserId }650  ));651 652  if (653    !["weekly", "monthly"].includes(plan) ||654    !Number.isInteger(duration) ||655    duration <= 0 ||656    !Number.isFinite(price) ||657    price <= 0658  ) {659    await Api.answerCallbackQuery({660      callback_query_id: callbackId,661      text: "اطلاعات طرح معتبر نیست؛ پرداخت تأیید نشد."662    });663    return;664  }665 666  const start = new Date();667  const end = new Date(668    start.getTime() + duration * 24 * 60 * 60 * 1000669  );670 671  const oldAccess = await db.user.get(672    "access",673    {},674    { user_id: targetUserId }675  );676 677  const access = Object.assign({}, oldAccess || {});678 679  access.membership = true;680  access.profile = true;681  access.challenges = true;682  access.vc = true;683  access.streak = true;684  access.achievements = true;685  access.rewards = true;686  access.private_content = true;687  access.private_group = true;688 689  // ابتدا نتیجه بررسی را ثبت می‌کنیم تا کلیک مجدد عادی رد شود.690  const markResult = await db.user.set(691    "payment_review_status",692    "approved",693    { user_id: targetUserId }694  );695 696  if (!saveSucceeded(markResult)) {697    await Api.answerCallbackQuery({698      callback_query_id: callbackId,699      text: "ثبت نتیجه پرداخت ناموفق بود."700    });701    return;702  }703 704  const accessResult = await db.user.set(705    "access",706    access,707    { user_id: targetUserId }708  );709 710  const statusResult = await db.user.set(711    "membership_status",712    "active",713    { user_id: targetUserId }714  );715 716  const startResult = await db.user.set(717    "subscription_start",718    start.toISOString(),719    { user_id: targetUserId }720  );721 722  const endResult = await db.user.set(723    "subscription_end",724    end.toISOString(),725    { user_id: targetUserId }726  );727 728  if (729    !saveSucceeded(accessResult) ||730    !saveSucceeded(statusResult) ||731    !saveSucceeded(startResult) ||732    !saveSucceeded(endResult)733  ) {734    await Api.answerCallbackQuery({735      callback_query_id: callbackId,736      text: "خطا در ذخیره اشتراک؛ اطلاعات را بررسی کن."737    });738 739    await Api.sendMessage({740      chat_id: Number(process.env.ADMIN_ID),741      text:742        "⚠️ خطا هنگام فعال‌سازی اشتراک\n" +743        "شناسه کاربر: " + targetUserId +744        "\nوضعیت پرداخت approved ثبت شده است؛ پیش از اقدام مجدد، " +745        "وضعیت دسترسی و تاریخ‌ها را بررسی کن."746    });747 748    return;749  }750 751 752const pendingReceipt = await db.user.get(753  "pending_payment_receipt",754  null,755  { user_id: targetUserId }756);757 758if (!pendingReceipt || !pendingReceipt.receipt_id) {759  await Api.sendMessage({760    chat_id: Number(process.env.ADMIN_ID),761    text:762      "⚠️ اشتراک فعال شده، اما اطلاعات رسید برای آرشیو پیدا نشد.\n" +763      "شناسه کاربر: " + targetUserId +764      "\nلطفاً پرونده این پرداخت را بررسی کن."765  });766} else {767  const archiveKey = "creators_confirmed_payments";768  const archive = await db.bot.get(archiveKey, []);769 770  const payments = Array.isArray(archive) ? archive : [];771 772  const alreadySaved = payments.some(773    item => item.receipt_id === pendingReceipt.receipt_id774  );775 776  if (!alreadySaved) {777    payments.push({778      receipt_id: pendingReceipt.receipt_id,779      user_id: targetUserId,780      name: String(781        await db.user.get("profile_name", "", {782          user_id: targetUserId783        })784      ),785      username: String(786        await db.user.get("profile_username", "", {787          user_id: targetUserId788        })789      ),790      plan: plan,791      price: price,792      duration: duration,793      receipt_type: pendingReceipt.type,794      receipt_file_id: pendingReceipt.file_id || "",795      receipt_file_name: pendingReceipt.file_name || "",796      receipt_text: pendingReceipt.text || "",797      receipt_submitted_at: pendingReceipt.submitted_at || "",798      approved_at: new Date().toISOString(),799      subscription_start: start.toISOString(),800      subscription_end: end.toISOString(),801      status: "approved"802    });803 804    await db.bot.set(archiveKey, payments);805 806    const verifyArchive = await db.bot.get(archiveKey, []);807    const verified = Array.isArray(verifyArchive) &&808      verifyArchive.some(809        item => item.receipt_id === pendingReceipt.receipt_id810      );811 812    if (!verified) {813      await Api.sendMessage({814        chat_id: Number(process.env.ADMIN_ID),815        text:816          "⚠️ اشتراک فعال شده، اما ثبت نهایی پرداخت تأیید نشد.\n" +817          "شناسه کاربر: " + targetUserId +818          "\nشناسه رسید: " + pendingReceipt.receipt_id819      });820    }821  }822}823  824  await Api.answerCallbackQuery({825    callback_query_id: callbackId,826    text: "پرداخت تأیید و اشتراک فعال شد."827  });828 829  try {830    await Api.editMessageCaption({831      chat_id: callbackMessage.chat.id,832      message_id: callbackMessage.message_id,833      caption:834        "✅ پرداخت تأیید شد.\n\n" +835        "شناسه کاربر: " + targetUserId +836        "\nطرح: " + (plan === "weekly" ? "هفتگی" : "ماهانه") +837        "\nمبلغ: " + price.toLocaleString("fa-IR") + " تومان" +838        "\nپایان اشتراک: " + end.toLocaleDateString("fa-IR")+ "تمديد همين اشتراك عضويت از طريق لينك زير" });839  } catch (error) {840    try {841      await Api.editMessageText({842        chat_id: callbackMessage.chat.id,843        message_id: callbackMessage.message_id,844        text:845          "✅ پرداخت تأیید شد.\n" +846          "شناسه کاربر: " + targetUserId +847          "\nپایان اشتراک: " + end.toLocaleDateString("fa-IR")848      });849    } catch (ignored) {}850  }851 852  try {853    await Api.sendMessage({854      chat_id: targetUserId,855      text:856        "👑 CREATORS\n\n" +857        "✅ پرداخت شما تأیید شد و اشتراک فعال گردید.\n\n" +858        "طرح: " + (plan === "weekly" ? "هفتگی" : "ماهانه") +859        "\nمدت: " + duration + " روز" +860        "\nمبلغ پرداختی: " + price.toLocaleString("fa-IR") + " تومان" +861        "\nتاریخ شروع: " + start.toLocaleDateString("fa-IR") +862        "\nتاریخ پایان: " + end.toLocaleDateString("fa-IR") +863        "\n\nقفل دسترسي ها و امكانات اختصاصي باز شدند 🔓✔️"864    });865  } catch (error) {866    await Api.sendMessage({867      chat_id: Number(process.env.ADMIN_ID),868      text:869        "⚠️ اشتراک فعال شد، اما ارسال پیام به کاربر ناموفق بود.\n" +870        "شناسه کاربر: " + targetUserId871    });872  }873 874  return;875}876 877// ==================================================878// تأیید عضویت879// ==================================================880 881if (data.startsWith("approve_")) {882  const targetUserId = getTargetId("approve_");883 884  if (!targetUserId) {885    await Api.answerCallbackQuery({886      callback_query_id: callbackId,887      text: "شناسه کاربر نامعتبر است."888    });889    return;890  }891 892  const currentStatus = await db.user.get(893    "membership_status",894    "unknown",895    { user_id: targetUserId }896  );897 898  if (["approved", "active", "paid"].includes(currentStatus)) {899    await Api.answerCallbackQuery({900      callback_query_id: callbackId,901      text: "این عضو قبلاً تأیید شده است."902    });903    return;904  }905 906  // دریافت یا ساخت Creator ID907  let creatorId = await db.user.get(908    "creator_id",909    null,910    { user_id: targetUserId }911  );912 913  if (!creatorId) {914    let attempts = 0;915 916    while (!creatorId && attempts < 20) {917      attempts++;918 919      const code = modules.randomstring.generate({920        length: 6,921        charset: "alphanumeric",922        readable: true923      }).toUpperCase();924 925      const candidate = "CREATOR-" + code;926      const ids = await Bot.getUsers();927      let duplicate = false;928 929      for (const id of ids) {930        const existingId = await db.user.get(931          "creator_id",932          null,933          { user_id: Number(id) }934        );935 936        if (existingId === candidate) {937          duplicate = true;938          break;939        }940      }941 942      if (!duplicate) creatorId = candidate;943    }944 945    if (!creatorId) {946      await Api.answerCallbackQuery({947        callback_query_id: callbackId,948        text: "خطا در ساخت Creator ID."949      });950      return;951    }952 953    const saveCreatorId = await db.user.set(954      "creator_id",955      creatorId,956      { user_id: targetUserId }957    );958 959    if (!saveSucceeded(saveCreatorId)) {960      await Api.answerCallbackQuery({961        callback_query_id: callbackId,962        text: "خطا در ذخیره Creator ID."963      });964      return;965    }966  }967 968  // دریافت یا ساخت رمز عبور969  let password = await db.user.get(970    "creator_password",971    null,972    { user_id: targetUserId }973  );974 975  if (!password) {976    password = modules.randomstring.generate({977      length: 12,978      charset: "alphanumeric",979      readable: true980    }).toUpperCase();981 982    const savePassword = await db.user.set(983      "creator_password",984      password,985      { user_id: targetUserId }986    );987 988    if (!saveSucceeded(savePassword)) {989      await Api.answerCallbackQuery({990        callback_query_id: callbackId,991        text: "خطا در ذخیره رمز عبور."992      });993      return;994    }995  }996 997  // ثبت تأیید؛ فعال‌سازی امکانات همچنان با مدیر است998  const statusResult = await db.user.set(999    "membership_status",1000    "approved",1001    { user_id: targetUserId }1002  );1003 1004  if (!saveSucceeded(statusResult)) {1005    await Api.answerCallbackQuery({1006      callback_query_id: callbackId,1007      text: "خطا در ذخیره وضعیت عضویت."1008    });1009    return;1010  }1011 1012  await Api.answerCallbackQuery({1013    callback_query_id: callbackId,1014    text: "عضویت تأیید شد."1015  });1016 1017  // به‌روزرسانی پیام درخواست مدیر1018  try {1019    await Api.editMessageText({1020      chat_id: callbackMessage.chat.id,1021      message_id: callbackMessage.message_id,1022      text:1023        "✦ درخواست عضویت تأیید شد.\n\n" +1024        "Creator ID: " + creatorId + "\n" +1025        "وضعیت: approved"1026    });1027  } catch (error) {1028    // خطای ویرایش پیام نباید مانع اطلاع‌رسانی به عضو شود1029  }1030 1031  // اطلاع‌رسانی به عضو1032  try {1033    await Api.sendMessage({1034      chat_id: targetUserId,1035      text:1036        "✦ CREATORS ✦\n" +1037        "━━━━━━━━━━━━━━━━━━\n\n" +1038        "درخواست عضویت شما تأیید شد. ✦\n\n" +1039        "به جمع CREATORS خوش آمدید.\n\n" +1040        "شناسه عضویت شما:\n" +1041        creatorId + "\n\n" +1042        "رمز عبور شما:\n" +1043        password + "\n\n" +1044        "لطفاً این اطلاعات را نزد خود محفوظ نگه دارید.\n\n" +1045        "✦ مرحله بعد:\n" +1046        "برای فعال‌سازی امکانات عضویت، اشتراک خود را پرداخت کنید.\n\n" +1047        "پس از پرداخت و فعال‌سازی توسط مدیر، دسترسی‌های شما برقرار خواهد شد."1048    });1049  } catch (error) {1050    await Api.sendMessage({1051      chat_id: Number(process.env.ADMIN_ID),1052      text:1053        "⚠️ عضویت تأیید شد، اما ارسال پیام به عضو ناموفق بود.\n\n" +1054        "شناسه تلگرام: " + targetUserId1055    });1056  }1057 1058  return;1059}1060 1061 1062// ==================================================1063// رد درخواست عضویت1064// ==================================================1065 1066if (data.startsWith("reject_")) {1067  const targetUserId = getTargetId("reject_");1068 1069  if (!targetUserId) {1070    await Api.answerCallbackQuery({1071      callback_query_id: callbackId,1072      text: "شناسه کاربر نامعتبر است."1073    });1074    return;1075  }1076 1077  const result = await db.user.set(1078    "membership_status",1079    "rejected",1080    { user_id: targetUserId }1081  );1082 1083  if (!saveSucceeded(result)) {1084    await Api.answerCallbackQuery({1085      callback_query_id: callbackId,1086      text: "خطا در ذخیره وضعیت."1087    });1088    return;1089  }1090 1091  await Api.answerCallbackQuery({1092    callback_query_id: callbackId,1093    text: "درخواست رد شد."1094  });1095 1096  try {1097    await Api.editMessageText({1098      chat_id: callbackMessage.chat.id,1099      message_id: callbackMessage.message_id,1100      text:1101        "✦ درخواست عضویت رد شد.\n\n" +1102        "شناسه کاربر: " + targetUserId1103    });1104  } catch (error) {}1105 1106  try {1107    await Api.sendMessage({1108      chat_id: targetUserId,1109      text:1110        "✦ درخواست عضویت شما پس از بررسی تأیید نشد.\n\n" +1111        "در صورت تمایل می‌توانید در آینده دوباره درخواست دهید."1112    });1113  } catch (error) {1114    await Api.sendMessage({1115      chat_id: Number(process.env.ADMIN_ID),1116      text:1117        "⚠️ درخواست رد شد، اما ارسال پیام به کاربر ناموفق بود.\n" +1118        "شناسه کاربر: " + targetUserId1119    });1120  }1121 1122  return;1123}1124 1125 1126// ==================================================1127// فعال‌سازی همه دسترسی‌ها1128// ==================================================1129 1130if (data.startsWith("all_on_")) {1131  const targetId = getTargetId("all_on_");1132 1133  if (!targetId) {1134    await Api.answerCallbackQuery({1135      callback_query_id: callbackId,1136      text: "شناسه کاربر نامعتبر است."1137    });1138    return;1139  }1140 1141  const access = {1142    membership: true,1143    profile: true,1144    challenges: true,1145    vc: true,1146    streak: true,1147    achievements: true,1148    rewards: true,1149    private_content: true,1150    private_group: true1151  };1152 1153  const accessResult = await db.user.set(1154    "access",1155    access,1156    { user_id: targetId }1157  );1158 1159  if (!saveSucceeded(accessResult)) {1160    await Api.answerCallbackQuery({1161      callback_query_id: callbackId,1162      text: "خطا در فعال کردن دسترسی‌ها."1163    });1164    return;1165  }1166 1167  const statusResult = await db.user.set(1168    "membership_status",1169    "active",1170    { user_id: targetId }1171  );1172 1173  if (!saveSucceeded(statusResult)) {1174    await Api.answerCallbackQuery({1175      callback_query_id: callbackId,1176      text: "دسترسی‌ها ذخیره شدند، اما تغییر وضعیت عضویت ناموفق بود."1177    });1178    return;1179  }1180 1181  await Api.answerCallbackQuery({1182    callback_query_id: callbackId,1183    text: "عضویت و همه دسترسی‌ها فعال شدند."1184  });1185 1186  try {1187    await Api.sendMessage({1188      chat_id: targetId,1189      text:1190        "✦ عضویت شما در CREATORS فعال شد.\n\n" +1191        "دسترسی شما به امکانات خصوصی برقرار شد."1192    });1193  } catch (error) {}1194 1195  await updateManagePanel(targetId);1196  return;1197}1198 1199 1200// ==================================================1201// غیرفعال‌سازی همه دسترسی‌ها1202// ==================================================1203 1204if (data.startsWith("all_off_")) {1205  const targetId = getTargetId("all_off_");1206 1207  if (!targetId) {1208    await Api.answerCallbackQuery({1209      callback_query_id: callbackId,1210      text: "شناسه کاربر نامعتبر است."1211    });1212    return;1213  }1214 1215  const access = {1216    membership: false,1217    profile: false,1218    challenges: false,1219    vc: false,1220    streak: false,1221    achievements: false,1222    rewards: false,1223    private_content: false,1224    private_group: false1225  };1226 1227  const accessResult = await db.user.set(1228    "access",1229    access,1230    { user_id: targetId }1231  );1232 1233  if (!saveSucceeded(accessResult)) {1234    await Api.answerCallbackQuery({1235      callback_query_id: callbackId,1236      text: "خطا در ذخیره دسترسی‌ها."1237    });1238    return;1239  }1240 1241  const statusResult = await db.user.set(1242    "membership_status",1243    "expired",1244    { user_id: targetId }1245  );1246 1247  if (!saveSucceeded(statusResult)) {1248    await Api.answerCallbackQuery({1249      callback_query_id: callbackId,1250      text: "دسترسی‌ها غیرفعال شدند، اما تغییر وضعیت ناموفق بود."1251    });1252    return;1253  }1254 1255  await Api.answerCallbackQuery({1256    callback_query_id: callbackId,1257    text: "عضویت و همه دسترسی‌ها غیرفعال شدند."1258  });1259 1260  try {1261    await Api.sendMessage({1262      chat_id: targetId,1263      text:1264        "✦ دسترسی عضویت شما در CREATORS غیرفعال شد.\n\n" +1265        "امکانات خصوصی دیگر در دسترس نیستند.\n\n" +1266        "برای ادامه مسیر، با مدیر مجموعه تماس بگیرید."1267    });1268  } catch (error) {}1269 1270  await updateManagePanel(targetId);1271  return;1272}1273 1274 1275// ==================================================1276// تغییر یک دسترسی مشخص1277// ==================================================1278 1279if (data.startsWith("toggle_")) {1280  const parts = data.split("_");1281  const targetId = Number(parts[1]);1282  const accessName = parts.slice(2).join("_");1283 1284  const allowed = [1285    "membership",1286    "profile",1287    "challenges",1288    "vc",1289    "streak",1290    "achievements",1291    "rewards",1292    "private_content",1293    "private_group"1294  ];1295 1296  if (!Number.isSafeInteger(targetId) || targetId <= 0) {1297    await Api.answerCallbackQuery({1298      callback_query_id: callbackId,1299      text: "شناسه کاربر نامعتبر است."1300    });1301    return;1302  }1303 1304  if (!allowed.includes(accessName)) {1305    await Api.answerCallbackQuery({1306      callback_query_id: callbackId,1307      text: "نوع دسترسی نامعتبر است."1308    });1309    return;1310  }1311 1312  const access = await db.user.get(1313    "access",1314    {},1315    { user_id: targetId }1316  );1317 1318  const currentAccess = Object.assign({}, access || {});1319  const newValue = !Boolean(currentAccess[accessName]);1320 1321  currentAccess[accessName] = newValue;1322 1323  const result = await db.user.set(1324    "access",1325    currentAccess,1326    { user_id: targetId }1327  );1328 1329  if (!saveSucceeded(result)) {1330    await Api.answerCallbackQuery({1331      callback_query_id: callbackId,1332      text: "خطا در ذخیره دسترسی."1333    });1334    return;1335  }1336 1337  await Api.answerCallbackQuery({1338    callback_query_id: callbackId,1339    text: newValue ? "دسترسی فعال شد." : "دسترسی غیرفعال شد."1340  });1341 1342  await updateManagePanel(targetId);1343  return;1344}1345 1346 1347// ==================================================1348// callback ناشناخته1349// ==================================================1350 1351await Api.answerCallbackQuery({1352  callback_query_id: callbackId,1353  text: "دستور ناشناخته است."1354});1355 1356 1357// ==================================================1358// به‌روزرسانی پنل مدیریت1359// ==================================================1360 1361async function updateManagePanel(targetId) {1362  const membership = await db.user.get(1363    "membership_status",1364    "unknown",1365    { user_id: targetId }1366  );1367 1368  const access = await db.user.get(1369    "access",1370    {},1371    { user_id: targetId }1372  );1373 1374  const a = access || {};1375 1376  await Api.editMessageText({1377    chat_id: callbackMessage.chat.id,1378    message_id: callbackMessage.message_id,1379    text:1380      "✦ مدیریت Creator\n\n" +1381      "Telegram ID: " + targetId + "\n" +1382      "وضعیت عضویت: " + membership + "\n\n" +1383      "دسترسی‌ها:",1384    reply_markup: {1385      inline_keyboard: [1386        [1387          {1388            text: "🟢 فعال کردن همه",1389            callback_data: "all_on_" + targetId1390          },1391          {1392            text: "🔴 غیرفعال کردن همه",1393            callback_data: "all_off_" + targetId1394          }1395        ],1396        [1397          {1398            text: (a.membership ? "🟢" : "🔴") + " عضویت اصلی",1399            callback_data: "toggle_" + targetId + "_membership"1400          }1401        ],1402        [1403          {1404            text: (a.profile ? "🟢" : "🔴") + " پروفایل",1405            callback_data: "toggle_" + targetId + "_profile"1406          }1407        ],1408        [1409          {1410            text: (a.challenges ? "🟢" : "🔴") + " چالش‌ها",1411            callback_data: "toggle_" + targetId + "_challenges"1412          }1413        ],1414        [1415          {1416            text: (a.vc ? "🟢" : "🔴") + " VC",1417            callback_data: "toggle_" + targetId + "_vc"1418          }1419        ],1420        [1421          {1422            text: (a.streak ? "🟢" : "🔴") + " Streak",1423            callback_data: "toggle_" + targetId + "_streak"1424          }1425        ],1426        [1427          {1428            text: (a.achievements ? "🟢" : "🔴") + " دستاوردها",1429            callback_data: "toggle_" + targetId + "_achievements"1430          }1431        ],1432        [1433          {1434            text: (a.rewards ? "🟢" : "🔴") + " جوایز",1435            callback_data: "toggle_" + targetId + "_rewards"1436          }1437        ],1438        [1439          {1440            text: (a.private_content ? "🟢" : "🔴") + " محتوای خصوصی",1441            callback_data: "toggle_" + targetId + "_private_content"1442          }1443        ],1444        [1445          {1446            text: (a.private_group ? "🟢" : "🔴") + " گروه خصوصی",1447            callback_data: "toggle_" + targetId + "_private_group"1448          }1449        ]1450      ]1451    }1452  });1453}