Repository: B3H1Z/Hiddify-Telegram-Bot
Branch: main
Commit: f82165920b02
Files: 36
Total size: 488.9 KB
Directory structure:
gitextract_jrhoa15n/
├── .gitignore
├── AdminBot/
│ ├── Json/
│ │ ├── buttons.json
│ │ ├── commands.json
│ │ └── messages.json
│ ├── bot.py
│ ├── content.py
│ ├── markups.py
│ └── templates.py
├── Cronjob/
│ ├── backup.py
│ ├── backupBot.py
│ └── reminder.py
├── Database/
│ └── dbManager.py
├── LICENSE
├── README-FA.md
├── README.md
├── Shared/
│ └── common.py
├── UserBot/
│ ├── Json/
│ │ ├── buttons.json
│ │ ├── commands.json
│ │ └── messages.json
│ ├── bot.py
│ ├── content.py
│ ├── markups.py
│ └── templates.py
├── Utils/
│ ├── api.py
│ ├── serverInfo.py
│ └── utils.py
├── config.py
├── crontab.py
├── hiddifyTelegramBot.py
├── install.sh
├── requirements.txt
├── restart.sh
├── uninstall.sh
├── update.py
├── update.sh
└── version.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
/Database/hidyBot.db
/Logs
/Backup
/UserBot/Receiptions
/.idea
/temp
/Utils/swapWallet.py
/.handler-saves
hiddifypanel.db
config.json
*.pyc
*.pyo!/qodana.yaml
qodana.yaml
check-host.py
.vscode/launch.json
Database/hidyBot1.db
================================================
FILE: AdminBot/Json/buttons.json
================================================
{
"EN": {
"CONFIRM": "✅Confirm",
"CANCEL": "❌Cancel",
"BOT_USERS_MANAGEMENT": "👤Bot Users Management",
"USERS_LIST": "👤Bot Users List",
"SEARCH_USERS_BOT": "🔍Search Bot Users",
"ORDERS_MANAGEMENT": "📗Orders Management",
"ORDERS_LIST": "📗Orders List",
"SEARCH_ORDERS": "🔍Search Orders",
"PAYMENT_MANAGEMENT": "💵Payment Management",
"APPROVED_PAYMENTS_LIST": "✅Approved Payment List",
"NON_APPROVED_PAYMENTS_LIST": "🚫Non Approved Payment List",
"PENDING_PAYMENT_LIST": "⏳Pending Payment List",
"CARD_PAYMENT_LIST": "💳Card Payment List",
"DIGITAL_PAYMENT_LIST": "💸Digital Payment List",
"SEARCH_PAYMENTS": "🔍Search Payment",
"USER_SUB_LIST": "📋Subscriptions List",
"EDIT_WALLET": "💳Edit Wallet",
"PAYMENTS_LIST": "💵Payment List",
"GIFT_LIST": "🎁Gift List",
"REFERRED_LIST": "🎗Referred List",
"USERS_SEARCH": "🔍Search User",
"ADD_USER": "➕Add User",
"SERVER_BACKUP": "📥Panel Backup",
"SERVER_STATUS": "📈Server Status",
"USERS_BOT_MANAGEMENT": "🤖Users Bot Management",
"NEXT_PAGE": "➡️",
"PREV_PAGE": "⬅️",
"CONFIGS_USER": "Configs",
"EDIT_USER": "Edit User",
"DELETE_USER": "Delete User",
"EDIT_NAME": "👤Edit Name",
"EDIT_USAGE": "📊Edit Usage",
"RESET_USAGE": "🔄Reset Usage",
"EDIT_DAYS": "📆Edit Days",
"RESET_DAYS": "🔄Reset Days",
"EDIT_COMMENT": "📝Edit Comment",
"UPDATE_MESSAGE": "🔄Update Message",
"BACK": "🔙Back",
"CONFIGS_DIR": "Configs",
"CONFIGS_SUB_AUTO": "Auto Subscription",
"CONFIGS_SUB": "Subscription Link",
"CONFIGS_SUB_B64": "Subscription Link b64",
"CONFIGS_CLASH": "Clash Subscription",
"CONFIGS_HIDDIFY": "Hiddify Subscription",
"CONFIGS_SING_BOX": "Sing-box",
"CONFIGS_FULL_SING_BOX": "Full Sing-box",
"SEARCH_USER_NAME": "Search by Name",
"SEARCH_USER_TELEGRAM_ID": "Search by Telegram ID",
"SEARCH_USER_UUID": "Search by UUID",
"SEARCH_USER_CONFIG": "Search by Config",
"SEARCH_EXPIRED_USERS": "Expired Users List",
"USERS_BOT_ADD_PLAN": "➕Add Plan",
"USERS_BOT_DEL_PLAN": "➖Delete Plan",
"USERS_BOT_OWNER_INFO": "👤Owner Info",
"USERS_BOT_OWNER_INFO_EDIT": "👤Edit Owner Info",
"USERS_BOT_ORDERS_STATUS": "📈Payment Status",
"USERS_BOT_SUB_STATUS": "📈Subscription Status",
"USERS_BOT_OWNER_INFO_EDIT_CARD_NAME": "Edit Card Holder Name",
"USERS_BOT_OWNER_INFO_EDIT_CARD_NUMBER": "Edit Card Number",
"USERS_BOT_OWNER_INFO_EDIT_USERNAME": "Edit Support Username",
"USERS_BOT_SEND_MESSAGE_TO_USERS": "📩Send Message to Users",
"USERS_BOT_SETTINGS": "⚙️Settings",
"USERS_BOT_SETTINGS_SHOW_HIDI_LINK": "User Page Hyperlink",
"USERS_BOT_SETTINGS_SHOW_THREE_RAND": "Random 3 Digit Price",
"USERS_BOT_SETTINGS_MIN_DEPO": "Minimum Deposit",
"USERS_BOT_SETTINGS_PNL_V8_FEATURES": "Panel V8 Features",
"USERS_BOT_SETTINGS_CHANNEL_ID": "Support Channel",
"USERS_BOT_SETTINGS_CHANNEL_ّFORCE_JOIN": "Force Join",
"USERS_BOT_SETTINGS_VISIBLE_SUBS": "Visible Subscriptions",
"USERS_BOT_SETTINGS_SET_WELCOME_MSG": "Welcome Message",
"USERS_BOT_SETTINGS_SET_FAQ_MSG": "ّFAQ",
"USERS_BOT_SETTINGS_SET_FAQ_MESSAGE": "Set FAQ",
"USERS_BOT_SETTINGS_HIDE_FAQ": "❌Hide FAQ",
"USERS_BOT_SETTINGS_TEST_SUB": "Test Subscription",
"USERS_BOT_SETTINGS_TEST_SUB_DAYS": "Test Subscription Days",
"USERS_BOT_SETTINGS_TEST_SUB_SIZE": "Test Subscription Size",
"USERS_BOT_SETTINGS_NOTIF_REMINDER": "Subscription Reminder",
"USERS_BOT_SETTINGS_NOTIF_REMINDER_USAGE": "Usage Reminder",
"USERS_BOT_SETTINGS_NOTIF_REMINDER_DAYS": "Days Reminder",
"USERS_BOT_SETTINGS_PANEL_AUTO_BACKUP": "Auto Backup",
"USERS_BOT_SETTINGS_BOT_AUTO_BACKUP": "Bot Auto Backup",
"USERS_BOT_SETTINGS_PANEL_MANUAL": "Manual",
"USERS_BOT_SETTINGS_PANEL_MANUAL_ANDROID": "Android Manual",
"USERS_BOT_SETTINGS_PANEL_MANUAL_IOS": "IOS Manual",
"USERS_BOT_SETTINGS_PANEL_MANUAL_WIN": "Windows Manual",
"USERS_BOT_SETTINGS_PANEL_MANUAL_MAC": "Mac Manual",
"USERS_BOT_SETTINGS_PANEL_MANUAL_LIN": "Linux Manual",
"USERS_BOT_SETTINGS_BACKUP_BOT": "Backup Bot",
"USERS_BOT_SETTINGS_RESTORE_BOT": "Restore Bot",
"USERS_BOT_SETTINGS_BUY_SUBSCRIPTION_STATUS": "Buy Subscription",
"USERS_BOT_SETTINGS_RENEWAL_SUBSCRIPTION_STATUS": "Renewal Subscription",
"USERS_BOT_SETTINGS_RENEWAL_METHOD": "Renewal Method",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_DEFAULT": "Default",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED": "Advanced",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_FAIRLY": "Fairly",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_DAYS": "Maximum Days for Renewal",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_USAGE": "Maximum Usage for Renewal",
"USERS_BOT_SETTINGS_RESET_FREE_TEST_LIMIT": "Reset free test limit",
"ABOUT_BOT": "ℹ️",
"TO_QR": "ً🖼QR",
"SUPPORT_GROUP": "Support Group",
"SERVERS_MANAGEMENT":"🖥Servers Management",
"ADD_SERVER": "➕Add Server",
"EDIT_SERVER": "Edit Server",
"DELETE_SERVER": "➖Delete Server",
"SERVER_LIST_OF_USERS": "👤Users List",
"SERVER_LIST_OF_PLANS": "Plans List",
"SERVER_EDIT_TITLE": "Edit title",
"SERVER_EDIT_USER_LIMIT": "Edit User Limit",
"SERVER_EDIT_URL": "Edit URL",
"CHANGE_STATUS_PAYMENT": "Change Payment Status",
"CONFIRM_PAYMENT": "✅Confirm Payment",
"NO": "❌No",
"YES": "✅Yes",
"ANSWER": "Answer",
"SEND_MESSAGE": "Send Message",
"DEBUG":"DEBUG",
"SKIP":"⏩Skip",
"RESET_TEST":"🔄Reset Test",
"BAN_USER":"🚫Ban User"
},
"FA": {
"CONFIRM": "✅تأیید",
"CANCEL": "❌لغو",
"BOT_USERS_MANAGEMENT": "👤مدیریت کاربران ربات",
"USERS_LIST": "👤لیست کاربران ربات",
"SEARCH_USERS_BOT": "🔍جستجوی کاربران ربات",
"ORDERS_MANAGEMENT": "📗مدیریت سفارشات",
"ORDERS_LIST": "📗لیست سفارشات",
"SEARCH_ORDERS": "🔍جستجوی سفارشات",
"PAYMENT_MANAGEMENT": "💵مدیریت تراکنشات",
"APPROVED_PAYMENTS_LIST": "✅لیست تراکنشات تایید شده",
"NON_APPROVED_PAYMENTS_LIST": "🚫لیست تراکنشات رد شده",
"PENDING_PAYMENT_LIST": "⏳لیست تراکنشات در انتظار",
"CARD_PAYMENT_LIST": "💳لیست تراکنشات کارت به کارت",
"DIGITAL_PAYMENT_LIST": "💸لیست تراکنشات دیجیتال",
"SEARCH_PAYMENTS": "🔍جستجوی تراکنش",
"USER_SUB_LIST": "📋لیست سرویسها",
"EDIT_WALLET": "💳ویرایش کیف پول",
"PAYMENTS_LIST": "💵لیست تراکنشات",
"GIFT_LIST": "🎁لیست هدایا",
"REFERRED_LIST": "🎗لیست معرفی شدهها",
"USERS_SEARCH": "🔍جستجوی کاربر",
"ADD_USER": "➕افزودن کاربر",
"SERVER_BACKUP": "📥دریافت بکاپ",
"SERVER_STATUS": "📈وضعیت سرور",
"USERS_BOT_MANAGEMENT": "🤖مدیریت ربات کاربران",
"NEXT_PAGE": "➡️",
"PREV_PAGE": "⬅️",
"CONFIGS_USER": "کانفیگ ها",
"EDIT_USER": "ویرایش کاربر",
"DELETE_USER": "حذف کاربر",
"EDIT_NAME": "👤ویرایش نام",
"EDIT_USAGE": "📊ویرایش حجم",
"RESET_USAGE": "🔄بازنشانی حجم",
"EDIT_DAYS": "📆ویرایش مدت",
"RESET_DAYS": "🔄بازنشانی مدت",
"EDIT_COMMENT": "📝ویرایش یادداشت",
"UPDATE_MESSAGE": "🔄بهروزرسانی پیام",
"BACK": "🔙بازگشت",
"CONFIGS_DIR": "کانفیگ مستقیم",
"CONFIGS_SUB_AUTO": "اشتراک خودکار",
"CONFIGS_SUB": "لینک اشتراک",
"CONFIGS_SUB_B64": "لینک اشتراک b64",
"CONFIGS_CLASH": "اشتراک Clash",
"CONFIGS_HIDDIFY": "اشتراک Hiddify",
"CONFIGS_SING_BOX": "Sing-box",
"CONFIGS_FULL_SING_BOX": "Full Sing-box",
"SEARCH_USER_NAME": "جستجو با نام",
"SEARCH_USER_TELEGRAM_ID": "جستجو با Telegram ID",
"SEARCH_USER_UUID": "جستجو با UUID",
"SEARCH_USER_CONFIG": "جستجو با کانفیگ",
"SEARCH_EXPIRED_USERS": "لیست کاربران منقضی",
"USERS_BOT_ADD_PLAN": "➕افزودن پلن",
"USERS_BOT_DEL_PLAN": "➖حذف پلن",
"USERS_BOT_OWNER_INFO": "👤اطلاعات مالک",
"USERS_BOT_OWNER_INFO_EDIT": "ویرایش اطلاعات مالک",
"USERS_BOT_ORDERS_STATUS": "📊پیگیری تراکنش",
"USERS_BOT_SUB_STATUS": "📊پیگیری اشتراک",
"USERS_BOT_OWNER_INFO_EDIT_USERNAME": "ویرایش نام کاربری پشتیبان",
"USERS_BOT_OWNER_INFO_EDIT_CARD_NUMBER": "ویرایش شماره کارت",
"USERS_BOT_OWNER_INFO_EDIT_CARD_NAME": "ویرایش نام صاحب کارت",
"USERS_BOT_SEND_MESSAGE_TO_USERS": "📩ارسال پیام همگانی",
"USERS_BOT_SETTINGS": "⚙️تنظیمات",
"USERS_BOT_SETTINGS_SHOW_HIDI_LINK": "هایپرلینک هیدیفای",
"USERS_BOT_SETTINGS_SHOW_THREE_RAND": "مشخصه تصادفی قیمت",
"USERS_BOT_SETTINGS_MIN_DEPO": "محدودیت حداقل تراکنش",
"USERS_BOT_SETTINGS_PNL_V8_FEATURES": "اشتراک های نسخه 8",
"USERS_BOT_SETTINGS_CHANNEL_ID": "تنظیم کانال پشتیبانی",
"USERS_BOT_SETTINGS_CHANNEL_ّFORCE_JOIN": "عضویت اجباری",
"USERS_BOT_SETTINGS_VISIBLE_SUBS": "وضعیت نمایش اشتراک ها",
"USERS_BOT_SETTINGS_SET_WELCOME_MSG": "پیام خوش آمدگویی",
"USERS_BOT_SETTINGS_SET_FAQ_MSG": "متن سوالات متداول",
"USERS_BOT_SETTINGS_SET_FAQ_MESSAGE": "تنظیم متن سوالات متداول",
"USERS_BOT_SETTINGS_HIDE_FAQ": "❌حذف سوالات متداول",
"USERS_BOT_SETTINGS_TEST_SUB": "مشخصات اشتراک تستی",
"USERS_BOT_SETTINGS_TEST_SUB_DAYS": "مدت اشتراک تستی",
"USERS_BOT_SETTINGS_TEST_SUB_SIZE": "حجم اشتراک تستی",
"USERS_BOT_SETTINGS_NOTIF_REMINDER": "یادآور وضعیت اشتراک",
"USERS_BOT_SETTINGS_NOTIF_REMINDER_USAGE": "یادآور وضعیت مصرف",
"USERS_BOT_SETTINGS_NOTIF_REMINDER_DAYS": "یادآور وضعیت زمان",
"USERS_BOT_SETTINGS_PANEL_AUTO_BACKUP": "ارسال خودکار بکاپ",
"USERS_BOT_SETTINGS_BOT_AUTO_BACKUP": "بکاپ خودکار ربات",
"USERS_BOT_SETTINGS_PANEL_MANUAL": "متن راهنما",
"USERS_BOT_SETTINGS_PANEL_MANUAL_ANDROID": "راهنمای اندروید",
"USERS_BOT_SETTINGS_PANEL_MANUAL_IOS": "راهنمای IOS",
"USERS_BOT_SETTINGS_PANEL_MANUAL_WIN": "راهنمای ویندوز",
"USERS_BOT_SETTINGS_PANEL_MANUAL_MAC": "راهنمای مک",
"USERS_BOT_SETTINGS_PANEL_MANUAL_LIN": "راهنمای لینوکس",
"USERS_BOT_SETTINGS_BACKUP_BOT": "پشتیبان گیری ربات",
"USERS_BOT_SETTINGS_RESTORE_BOT": "بازیابی ربات",
"USERS_BOT_SETTINGS_BUY_SUBSCRIPTION_STATUS": "خرید اشتراک",
"USERS_BOT_SETTINGS_RENEWAL_SUBSCRIPTION_STATUS": "تمدید اشتراک",
"USERS_BOT_SETTINGS_RENEWAL_METHOD": "شیوه تمدید",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_DEFAULT": "پیشفرض",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED": "پیشرفته",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_FAIRLY": "منصفانه",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_DAYS": "حداکثر زمان مجاز برای تمدید",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_USAGE": "حداکثر مصرف مجاز برای تمدید",
"USERS_BOT_SETTINGS_RESET_FREE_TEST_LIMIT": "بازنشانی تست رایگان",
"ABOUT_BOT": "ℹ️",
"TO_QR": "ً🖼کیوآر",
"SUPPORT_GROUP": "گروه پشتیبانی",
"SERVERS_MANAGEMENT":"🖥 مدیریت سرورها",
"ADD_SERVER": "➕افزودن سرور",
"EDIT_SERVER": "ویرایش سرور",
"DELETE_SERVER": "حذف سرور",
"SERVER_LIST_OF_USERS": "مدیریت کاربران",
"SERVER_LIST_OF_PLANS": "لیست پلنها",
"SERVER_EDIT_TITLE": "ویرایش عنوان",
"SERVER_EDIT_USER_LIMIT": "ویرایش محدودیت کاربر",
"SERVER_EDIT_URL": "ویرایش لینک",
"CHANGE_STATUS_PAYMENT": "تغییر وضعیت تراکنش",
"CONFIRM_PAYMENT": "✅تایید تراکنش",
"NO": "❌خیر",
"YES": "✅بله",
"ANSWER": "📤پاسخ",
"SEND_MESSAGE": "📤ارسال پیام",
"DEBUG":"DEBUG",
"SKIP":"⏩رد کردن",
"RESET_TEST":"🔄بازنشانی اشتراک تستی",
"BAN_USER":"🚫مسدود کردن کاربر"
}
}
================================================
FILE: AdminBot/Json/commands.json
================================================
{
"EN": {
"START": "start",
"DEBUG": "debug"
},
"FA": {
"START": "شروع",
"DEBUG": "اشکال زدایی"
}
}
================================================
FILE: AdminBot/Json/messages.json
================================================
{
"EN": {
"WELCOME": "Welcome to Hiddify Management Bot",
"ERROR_INVALID_NUMBER": "❌Only numbers are allowed!",
"ERROR_USER_NOT_FOUND": "❌User not found",
"ERROR_INVALID_COMMAND": "❌Invalid command",
"ERROR_UNKNOWN": "❌Unknown error",
"ERROR_CONFIG_NOT_FOUND": "❌Config not found",
"ERROR_PLAN_NOT_FOUND": "❌Plan not found",
"ERROR_SUB_NOT_FOUND": "❌Subscription not found",
"ERROR_CHANNEL_ID_NOT_SET": "❌Channel ID not set, please set it first.",
"SUCCESS_USER_DELETED": "✅User deleted",
"SUCCESS_USER_EDITED": "✅User edited",
"SUCCESS_USER_ADDED": "✅User added",
"SUCCESS_USER_USAGE_EDITED": "✅Usage limit edited to:",
"SUCCESS_USER_DAYS_EDITED": "✅Days edited to:",
"SUCCESS_USER_NAME_EDITED": "✅Name edited to:",
"SUCCESS_USER_COMMENT_EDITED": "✅Comment edited to:",
"SUCCESS_ADD_USER": "✅User added",
"SUCCESS_SEARCH_USER": "✅User found",
"SUCCESS_SEARCH_SUB": "✅Subscription found",
"SUCCESS_SEND_MSG_USERS": "✅Message sent to users",
"SUCCESS_REMOVED_SERVER": "✅Server removed",
"SUCCESS_RESET_FREE_TEST": "✅Free trial limit successfully reset",
"WAIT": "Please wait...",
"CANCELED": "❌Canceled",
"CANCEL_ADD_USER": "❌Add User Canceled",
"ADD_USER_NAME": "Please enter the name of the user: ",
"ADD_USER_COMMENT": "Please enter the comment of the user: ",
"ADD_USER_USAGE_LIMIT": "Please enter the usage limit of the user (GB): ",
"ADD_USER_DAYS": "Please enter the days of package: ",
"ENTER_NEW_USAGE_LIMIT": "Please enter new usage limit (GB): ",
"ENTER_NEW_DAYS": "Please enter new limit: ",
"ENTER_NEW_NAME": "Please enter new name: ",
"ENTER_NEW_COMMENT": "Please enter new comment: ",
"RESET_USAGE": "✅Usage limit reset",
"RESET_DAYS": "✅Days reset",
"ADD_USER_CONFIRM": "Please confirm the information:",
"ERROR_NOT_ADMIN": "❌You are not admin!",
"NEW_USER_INFO": "[New User Info]",
"EDITED_USER_INFO": "[User Info Updated]",
"EXPIRED_USERS_LIST": "[EXPIRED USERS LIST]",
"GB": "GB",
"DAY_EXPIRE": "Days",
"INFO_USAGE": "📊Usage:",
"OF": "of",
"INFO_REMAINING_DAYS": "📆Remaining Days:",
"INFO_LAST_CONNECTION": "📶Last Connection:",
"INFO_COMMENT": "📝Comment:",
"INFO_USER_NAME": "⬖ Name:",
"INFO_USER_USERNAME": "⬖ Username:",
"INFO_USER_NUM_ID": "⬖ Telegram ID:",
"HEADER_USERS_LIST": "⬖ Users List",
"HEADER_USERS_LIST_MSG": "ℹ️You can see the list of users and their information here.",
"NUM_USERS": "🟢Number of users: ",
"NUM_USERS_ONLINE": "🔵Online users: ",
"NUM_GET_FREE_USERS": "⬖ Number of received free test: ",
"NUM_ORDERED_USERS": "⬖ Number of users placed order: ",
"TOTAL_BALANCE_USERS": "⬖ Total balance of users' wallets: ",
"SEARCH_USER": "Please select the search method",
"SEARCH_USER_NAME": "Please enter the name of the user: ",
"SEARCH_USER_TELEGRAM_ID": "Please enter the Telegram ID of the user: ",
"SEARCH_USER_UUID": "Please enter the UUID of the user: ",
"SEARCH_USER_CONFIG": "Please enter one of the config of the user: ",
"SEARCH_RESULT": "[Search Result]",
"MONTH": "Months",
"WEEK": "Weeks",
"DAY": "Days",
"HOUR": "Hours",
"MINUTE": "Minutes",
"ONLINE": "Online",
"AGO": "ago",
"NEVER": "Never",
"TOMAN": "T",
"CURRENT_VALUE": "Current Value",
"ERROR_CLIENT_TOKEN": "❌Client bot is not set!",
"USERS_BOT_ADD_PLAN": "Please complete the following information to add a plan",
"USERS_BOT_ADD_PLAN_DAYS": "Please enter the days of Plan: ",
"USERS_BOT_ADD_PLAN_USAGE": "Please enter the usage limit(GB) of the Plan: ",
"USERS_BOT_ADD_PLAN_PRICE": "Please enter the price(TOMAN) of the Plan: ",
"USERS_BOT_ADD_PLAN_DESC": "Please enter the description of the Plan: ",
"USERS_BOT_ADD_PLAN_CONFIRM": "Please confirm the information:",
"USERS_BOT_ADD_PLAN_SUCCESS": "✅Plan added",
"USERS_BOT_OWNER_INFO_NOT_FOUND": "Owner info not found!\nPlease set it first.",
"USERS_BOT_OWNER_INFO_ADD_USERNAME": "Please enter the username of the support bot: ",
"USERS_BOT_OWNER_INFO_ADD_CARD_NUMBER": "Please enter the card number: ",
"USERS_BOT_OWNER_INFO_ADD_CARD_NAME": "Please enter the name of the card owner: ",
"USERS_BOT_SEND_MSG_USERS": "Please enter the message you want to send to users:",
"USERS_BOT_PLANS_LIST": "📋Plans List",
"USERS_BOT_SELECT_PLAN_TO_DELETE": "Please select the plan you want to delete:",
"USERS_BOT_PLAN_DELETED": "✅Plan deleted",
"SUCCESS_UPDATE_DATA": "✅Data updated",
"USERS_BOT_SETTINGS": "⚙️Users Bot Settings",
"USERS_BOT_SETTINGS_HYPERLINK": "Set Hyperlink visibility when user request subscription info",
"USERS_BOT_ORDER_NUMBER_REQUEST": "Please enter the payment number:",
"USERS_BOT_SUB_ID_REQUEST": "Please enter the subscription ID:",
"USERS_BOT_SETTING_MIN_DEPO": "Please enter the minimum deposit:",
"USERS_BOT_SETTING_CHANNEL_ID": "Please enter the channel ID:",
"USERS_BOT_SETTING_FORCE_JOIN_HELP": "⭕Please add the bot to your channel and make it admin to work properly.",
"USERS_BOT_SETTING_WELCOME_MSG": "Please enter the welcome message:",
"USERS_BOT_SETTING_FAQ_MSG": "Please enter the faq text to show in the user panel:",
"USERS_BOT_SETTINGS_TEST_SUB_DAYS": "Please enter the days of test subscription:",
"USERS_BOT_SETTINGS_TEST_SUB_USAGE": "Please enter the usage limit(GB) of test subscription:",
"USERS_BOT_SETTINGS_NOTIF_REMINDER_DAYS": "Set the number of days before the end of the subscription to send a reminder message:",
"USERS_BOT_SETTINGS_NOTIF_REMINDER_USAGE": "Set the remaining GB to send a reminder message:",
"USERS_BOT_SETTINGS_PANEL_MANUAL": "Please enter the manual text to show in the user panel:",
"USERS_BOT_SETTINGS_BACKUP_BOT": "Backup Bot File",
"USERS_BOT_SETTINGS_RESTORE_BOT": "This feature is under test, so be careful when using it and ask your questions from the support group.\nRestore Bot Backup File",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_DAYS":"Set the number of days before the end of the subscription to allow the user to renew the subscription:",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_USAGE":"Set the remaining GB to allow the user to renew the subscription:",
"USERS_BOT_SETTINGS_RESET_FREE_TEST_LIMIT_QUESTION": "Are you sure you want to reset your free trial?\n⚠️By confirming this, all users are able to take a free test again",
"ERROR_INVALID_USERNAME": "❌Invalid username\nUsername must start with @",
"ERROR_INVALID_CARD_NUMBER": "❌Invalid card number",
"PAYMENT_CONFIRMED": "✅Payment confirmed",
"PAYMENT_NOT_CONFIRMED": "❌Payment not confirmed",
"ERROR_PAYMENT_ALREADY_CONFIRMED": "❌Payment already confirmed",
"ERROR_PAYMENT_ALREADY_REJECTED": "❌Payment already rejected",
"PAYMENT_CONFIRMED_ADMIN": "✅Payment confirmed",
"PAYMENT_NOT_CONFIRMED_ADMIN": "❌Payment not confirmed",
"ERROR_PAYMENT_NOT_FOUND": "❌Payment not found",
"ERROR_ORDER_NOT_FOUND": "❌Order not found",
"ERROR_GIFT_NOT_FOUND": "❌Gift not found",
"ORDER_ID": "Payment number:",
"SUB_ID": "Subscription ID:",
"USER_TIME_EXPIRED": "⚠️EXPIRED",
"USER_LAST_DAY": "Last Day",
"PAYMENT_ASK_CHANGE_STATUS": "Do you want to change the status of the payment?",
"PAYMENT_ACCEPT_STATUS_CONFIRMED": "🟢Confirmed",
"PAYMENT_ACCEPT_STATUS_NOT_CONFIRMED": "🔴Not Confirmed",
"PAYMENT_ACCEPT_STATUS_WAITING": "🟡Waiting",
"PAYMENT_ACCEPT_STATUS": "Status:",
"CREATED_AT": "Created:",
"WALLET_PAYMENT_CONFIRMED": "✅Payment confirmed\nYour wallet balance has increased.",
"FEATUR_UNAVAILABLE": "❌This feature is not available at the moment.",
"REQUEST_JOIN_HIDY": "Please join the support group to get the latest information.",
"WELCOME_TO_ADMIN": "Hiddify Management Bot has been successfully launched.\nTo start working, send the /start command.",
"SUCCESS_RESTORE_BOT": "✅Bot restored successfully",
"ADD_SERVER": "Please complete the following information to add a server",
"ADD_SERVER_TITLE": "Please enter the title of Server: ",
"ADD_SERVER_USER_LIMIT": "Please enter the user limit of the Server: ",
"ADD_SERVER_URL": "Please enter the url of the Server: ",
"ERROR_ADD_SERVER_URL": "Please enter the valid url of the Server: ",
"ERROR_SAME_SERVER_URL": "This link is already registered for another server, please submit another link:",
"ADD_SERVER_SUCCESS": "✅Server added",
"INFO_SERVER": "Server:",
"INFO_SERVER_USER_NUMBER": "Number of Users:",
"INFO_SERVER_USER_PLAN": "Number of Plan:",
"DELETE_SERVER_QUESTION": "Are you sure you want to delete the server?\n⚠️After deleting subscriptions related to this server, it is not visible to users.",
"ERROR_SERVER_NOT_FOUND": "❌Server not found",
"INFO_PLAN_ID": "Plan ID:",
"INFO_PLAN_USAGE": "Usage limit(GB):",
"INFO_PLAN_DAYS": "Time limitation:",
"INFO_PLAN_PRICE": "Price",
"INFO_PLAN_DESC": "Description:",
"INFO_PLAN_NUM_ORDER": "Purchases",
"INFO_PLAN_TOTAL_SALE": "Total sales",
"SUCCESS_SERVER_TITLE_EDITED":"✅Title edited to:",
"SUCCESS_SERVER_USER_LIMIT_EDITED" : "✅User limit edited to:",
"SUCCESS_SERVER_URL_EDITED": "✅URL edited to:",
"SERVER": "⬖ Server:",
"HEADER_ORDERS_LIST": "⬖ Orders List",
"NUM_ORDERS": "⬖ Number of Orders: ",
"TOTAL_ORDERS_VALUME": "⬖ Total volume ordered(GB): ",
"TOTAL_ORDERS_SALES": "⬖ Total value of orders: ",
"LAST_30DAYS_NUM_ORDERS": "⬖ Number of Last 30 Days Orders: ",
"LAST_30DAYS_ORDERS_VALUME": "⬖ Volume ordered in Last 30 Days(GB): ",
"LAST_30DAYS_ORDERS_SALES": "⬖ Value of orders in Last 30 Days: ",
"THIS_MONTH_NUM_ORDERS": "⬖ Number of This Month Orders: ",
"THIS_MONTH_ORDERS_VALUME": "⬖ Volume ordered in This Month(GB): ",
"THIS_MONTH_ORDERS_SALES": "⬖ Value of orders in This Month: ",
"HEADER_PAYMENT_LIST": "⬖ Payment List",
"NUM_PAYMENTS": "⬖ Number of Payments: ",
"TOTAL_PAYMENTS_AMOUNT": "⬖ Total amount payment: ",
"LAST_30DAYS_NUM_PAYMENTS": "⬖ Number of Last 30 Days Payments: ",
"LAST_30DAYS_PAYMENTS_AMOUNT": "⬖ Amount of Payments in Last 30 Days: ",
"THIS_MONTH_NUM_PAYMENTS": "⬖ Number of This Month Payments: ",
"THIS_MONTH_PAYMENTS_AMOUNT": "⬖ Amount of Payments in This Month: ",
"GET_FREE_TEST_STATUS": "⬖ Free Test Status: ",
"WALLET_BALANCE": "⬖ Wallet Balance: ",
"NUM_ORDER_SUB": "⬖ Number of ordered subscriptions: ",
"NUM_NON_ORDER_SUB": "⬖ Number of connected subscriptions: ",
"NUM_APPROVED_PAYMENTS": "⬖ Number of Approved Payments: ",
"BOT_ORDER_ID": "⬖ Order Number: ",
"ORDERED_VALUME": "⬖ Ordered Volume: ",
"ORDERED_DAYS": "⬖ Ordered Days: ",
"ORDERED_PRICE": "⬖ Ordered Price: ",
"SUB_NAME": "⬖ Subscription title: ",
"BOT_ORDER_DATE": "⬖ Order Date: ",
"ORDER_NUMBER_REQUEST": "Please enter the order number:",
"PAYMENTS_ID": "⬖ Payment number: ",
"BOT_PAYMENT_DATE": "⬖ Payment Date: ",
"PAIED_AMOUNT": "⬖ Paid amount: ",
"STATUS": "⬖ Status: ",
"PAYMENTS_METHOD": "⬖ Payment Method: ",
"PAYMENT_NUMBER_REQUEST": "Please enter the payment number:",
"CHANGE_STATUS_PAYMENT_CONFIRM_REQUEST": "⚠️Are you sure about the changing payment status?",
"WALLET_CHANGED_TO_PAYMENT_CONFIRMED": "✅Payment changed to confirmed by admin\nYour wallet balance has increased.",
"PAYMENT_CHANGED_TO_NOT_CONFIRMED": "❌Payment changed to rejected by admin And the payment amount is deducted from your wallet balance\nPlease contact support if a mistake has been made.",
"PAYMENT_CHANGED_TO_CONFIRMED_ADMIN": "✅Payment changed to confirmed",
"PAYMENT_CHANGED_TO_NOT_CONFIRMED_ADMIN": "❌Payment changed to rejected",
"SUCCESS_SEARCH_ORDER": "✅Order found",
"SUCCESS_SEARCH_PAYMENT": "✅Payment found",
"NOT_SET ": "Not set",
"EDIT_WALLET_BALANCE": "Please enter the new balance:",
"SEND_MESSAGE_TO_USER": "Please enter message you want to send to the user:",
"MESSAGE_SENDED": "Message Sended",
"ADMIN": "َAdmin:",
"MESSAGE_FROM_ADMIN": "Message from admin",
"MESSAGE_TEXT": "Message:",
"ERROR_USER_HAVE_TEST_SUB": "❌User already have a test subscription",
"SUCCESS_RESET_TEST_SUB": "✅Test subscription reset",
"WALLET_BALANCE_CHANGED_BY_ADMIN_P1": "💰Wallet balance changed to",
"WALLET_BALANCE_CHANGED_BY_ADMIN_P2": "by admin",
"SUCCESS_BAN_USER": "✅User banned",
"SUCCESS_UNBAN_USER": "✅User unbanned"
},
"FA": {
"WELCOME": "به ربات مدیریت هیدی بات خوش آمدید.",
"ERROR_INVALID_NUMBER": "❌تنها اعداد مجاز هستند!",
"ERROR_USER_NOT_FOUND": "❌کاربر یافت نشد",
"ERROR_INVALID_COMMAND": "❌فرمان نامعتبر",
"ERROR_UNKNOWN": "❌خطای ناشناخته",
"ERROR_CONFIG_NOT_FOUND": "❌کانفیگ یافت نشد",
"ERROR_PLAN_NOT_FOUND": "❌پلن یافت نشد",
"ERROR_SUB_NOT_FOUND": "❌اشتراکی با این شناسه یافت نشد",
"ERROR_CHANNEL_ID_NOT_SET": "❌آیدی کانال پشتیبانی تنظیم نشده است، لطفا ابتدا آن را تنظیم کنید.",
"SUCCESS_USER_DELETED": "✅کاربر حذف شد",
"SUCCESS_USER_EDITED": "✅کاربر ویرایش شد",
"SUCCESS_USER_ADDED": "✅کاربر اضافه شد",
"SUCCESS_USER_USAGE_EDITED": "✅محدودیت استفاده کاربر ویرایش شد به:",
"SUCCESS_USER_DAYS_EDITED": "✅روزها ویرایش شد به:",
"SUCCESS_USER_NAME_EDITED": "✅نام ویرایش شد به:",
"SUCCESS_USER_COMMENT_EDITED": "✅یادداشت ویرایش شد به:",
"SUCCESS_ADD_USER": "✅کاربر اضافه شد",
"SUCCESS_SEARCH_USER": "✅کاربر یافت شد",
"SUCCESS_SEARCH_SUB": "✅اشتراک یافت شد",
"SUCCESS_SEND_MSG_USERS": "✅پیام به کاربران ارسال شد",
"SUCCESS_REMOVED_SERVER": "✅سرور حذف شد",
"SUCCESS_RESET_FREE_TEST": "✅محدودیت تست رایگان با موفقیت بازنشانی شد",
"WAIT": "لطفاً منتظر بمانید...",
"CANCELED": "❌لغو شد",
"CANCEL_ADD_USER": "❌افزودن کاربر لغو شد",
"ADD_USER_NAME": "لطفاً نام کاربر را وارد کنید: ",
"ADD_USER_COMMENT": "لطفاً نظر کاربر را وارد کنید: ",
"ADD_USER_USAGE_LIMIT": "لطفاً محدودیت استفاده کاربر (GB) را وارد کنید: ",
"ADD_USER_DAYS": "لطفاً تعداد روز بستهی کاربر را وارد کنید: ",
"ENTER_NEW_USAGE_LIMIT": "لطفاً محدودیت استفاده جدید (GB) را وارد کنید: ",
"ENTER_NEW_DAYS": "لطفاً محدودیت جدید را وارد کنید: ",
"ENTER_NEW_NAME": "لطفاً نام جدید را وارد کنید: ",
"ENTER_NEW_COMMENT": "لطفاً یادداشت جدید را وارد کنید: ",
"RESET_USAGE": "✅محدودیت استفاده بازنشانی شد",
"RESET_DAYS": "✅روزها بازنشانی شد",
"ADD_USER_CONFIRM": "لطفاً اطلاعات را تأیید کنید:",
"ERROR_NOT_ADMIN": "❌شما ادمین نیستید!",
"NEW_USER_INFO": "[اطلاعات کاربر جدید]",
"EDITED_USER_INFO": "[اطلاعات کاربر بهروزرسانی شد]",
"EXPIRED_USERS_LIST": "[لیست کاربران منقضی شده]",
"GB": "گیگابایت",
"DAY_EXPIRE": "روز دیگر",
"INFO_USAGE": "📊مصرف:",
"OF": "از",
"INFO_REMAINING_DAYS": "📆انقضا:",
"INFO_LAST_CONNECTION": "📶آخرین اتصال:",
"INFO_COMMENT": "📝یادداشت:",
"INFO_USER_NAME": "⬖ کاربر:",
"INFO_USER_USERNAME": "⬖ نام کاربری:",
"INFO_USER_NUM_ID": "⬖ شناسه کاربر:",
"HEADER_USERS_LIST": "⬖ لیست کاربران",
"HEADER_USERS_LIST_MSG": "ش️ما میتوانید لیست کاربران و اطلاعات آنها را اینجا مشاهده کنید",
"NUM_USERS": "⬖ تعداد کاربران: ",
"NUM_USERS_ONLINE": "🔵کاربران آنلاین: ",
"NUM_GET_FREE_USERS": "⬖ تعداد کاربران تست رایگان: ",
"NUM_ORDERED_USERS": "⬖ تعداد کاربران سفارشات: ",
"TOTAL_BALANCE_USERS": "⬖ مجموع موجودی کیف پول کاربران: ",
"SEARCH_USER": "لطفاً روش جستجو را انتخاب کنید",
"SEARCH_USER_NAME": "لطفاً نام کاربر را وارد کنید: ",
"SEARCH_USER_TELEGRAM_ID": "لطفا Telegram ID کاربر را وارد کنید: ",
"SEARCH_USER_UUID": "لطفاً UUID کاربر را وارد کنید: ",
"SEARCH_USER_CONFIG": "لطفاً یکی از کانفیگ های کاربر را وارد کنید: ",
"SEARCH_RESULT": "[نتیجه جستجو]",
"MONTH": "ماه",
"WEEK": "هفته",
"DAY": "روز",
"HOUR": "ساعت",
"MINUTE": "دقیقه",
"ONLINE": "آنلاین",
"AGO": "پیش",
"NEVER": "هرگز",
"TOMAN": "تومان",
"CURRENT_VALUE": "مقدار فعلی",
"ERROR_CLIENT_TOKEN": "❌ربات کاربران تنظیم نشده",
"USERS_BOT_ADD_PLAN": "⬇️اطلاعات لازم را برای افزودن پلن وارد کنید",
"USERS_BOT_ADD_PLAN_DAYS": "لطفا زمان(تعداد روزهای) پلن را وارد کنید:",
"USERS_BOT_ADD_PLAN_USAGE": "لطفا محدودیت استفاده(گیگابایت) پلن را وارد کنید:",
"USERS_BOT_ADD_PLAN_PRICE": "لطفا قیمت(تومان) پلن را وارد کنید:",
"USERS_BOT_ADD_PLAN_DESC": "لطفا توضیحات پلن را وارد کنید:",
"USERS_BOT_ADD_PLAN_CONFIRM": "لطفا اطلاعات زیر را تایید کنید",
"USERS_BOT_ADD_PLAN_SUCCESS": "✅پلن با موفقیت افزوده شد",
"USERS_BOT_OWNER_INFO_NOT_FOUND": "❌اطلاعات مالک یافت نشد \n لطفا ابتدا آن را تنظیم کنید.",
"USERS_BOT_OWNER_INFO_ADD_USERNAME": "لطفا نام کاربری تلگرام پشتیبان را وارد کنید\nلطفا همراه با @ وارد کنید\nمثال: @example",
"USERS_BOT_OWNER_INFO_ADD_CARD_NUMBER": "لطفا شماره 16 رقمی کارت بانکی جهت واریز را وارد کنید",
"USERS_BOT_OWNER_INFO_ADD_CARD_NAME": "لطفا نام صاحب حساب بانکی جهت واریز را وارد کنید",
"USERS_BOT_SEND_MSG_USERS": "لطفا پیام خود را برای ارسال به کاربران وارد کنید:",
"USERS_BOT_PLANS_LIST": "📋لیست پلن های موجود",
"USERS_BOT_SELECT_PLAN_TO_DELETE": "لطفا پلن مورد نظر را برای حذف انتخاب کنید",
"USERS_BOT_PLAN_DELETED": "✅پلن با موفقیت حذف شد",
"USERS_BOT_SETTINGS": "⚙️تنظیمات ربات کاربران",
"USERS_BOT_SETTINGS_HYPERLINK": "تنظیم نمایش Hyperlink صفحه هیدیفای روی نام کاربر هنگام دریافت اطلاعات اشتراک",
"USERS_BOT_ORDER_NUMBER_REQUEST": "لطفا [شناسه تراکنش] را وارد کنید:",
"USERS_BOT_SUB_ID_REQUEST": "لطفا شناسه اشتراک را وارد کنید:",
"USERS_BOT_SETTING_MIN_DEPO": "لطفا حداقل مبلغ واریزی را تعیین کنید:",
"USERS_BOT_SETTING_CHANNEL_ID": "لطفا آیدی کانال را وارد کنید:",
"USERS_BOT_SETTING_FORCE_JOIN_HELP": "⭕لطفا برای اجرای این قابلیت، حتما [ربات کاربران] را به کانال خود اضافه و آن را ادمین کنید!",
"USERS_BOT_SETTING_WELCOME_MSG": "لطفا پیام خوش آمدگویی را تنظیم کنید:",
"USERS_BOT_SETTING_FAQ_MSG": "لطفا متن سوالات متداول مورد نظر را برای نمایش در پنل کاربران وارد کنید:",
"USERS_BOT_SETTINGS_TEST_SUB_DAYS": "لطفا تعداد روزهای اشتراک تست را تنظیم کنید:",
"USERS_BOT_SETTINGS_TEST_SUB_USAGE": "لطفا حجم(گیگابایت) اشتراک تست را تنظیم کنید:",
"USERS_BOT_SETTINGS_NOTIF_REMINDER_DAYS": "تعیین کنید که چند روز قبل از اتمام اشتراک پیام یادآوری تمدید اشتراک ارسال شود:",
"USERS_BOT_SETTINGS_NOTIF_REMINDER_USAGE": "تعیین کنید که چند گیگ مانده به اتمام اشتراک پیام یادآوری تمدید اشتراک ارسال شود:",
"USERS_BOT_SETTINGS_PANEL_MANUAL": "لطفا متن راهنمای مورد نظر را برای نمایش در پنل کاربران وارد کنید:",
"USERS_BOT_SETTINGS_BACKUP_BOT": "فایل پشتیبان ربات",
"USERS_BOT_SETTINGS_RESTORE_BOT": "📥 لطفا فایل پشتیبان خود را ارسال کنید: \n توجه داشته باشید که این قابلیت حساس میباشد و در صورت وجود هرگونه سوال یا شبهه، ابتدا با گروه پشتیبانی در ارتباط باشید.",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_DAYS":"تعیین کنید که چند روز مانده به پایان اشتراک، کاربر مجاز به تمدید اشتراک باشد:",
"USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_USAGE":"تعیین کنید که چند گیگ مانده به پایان اشتراک، کاربر مجاز به تمدید اشتراک باشد:",
"USERS_BOT_SETTINGS_RESET_FREE_TEST_LIMIT_QUESTION": "آیا از بازنشانی تست رایگان کاربران اطمینان دارید؟\n⚠️با تایید این مورد تمامی کاربران قادر به گرفتن تست رایگان مجدد میباشند",
"SUCCESS_UPDATE_DATA": "✅اطلاعات با موفقیت به روز شد",
"ERROR_INVALID_USERNAME": "❌آیدی نامعتبر است\n آیدی باید با @ شروع شود",
"ERROR_INVALID_CARD_NUMBER": "❌شماره کارت نامعتبر است\nشماره کارت باید 16 رقمی باشد",
"PAYMENT_CONFIRMED": "تراکنش شما تایید شد\n از طریق دکمه [📊وضعیت اشتراک] میتوانید به اطلاعات اشتراک خود دسترسی داشته باشید.",
"PAYMENT_NOT_CONFIRMED": "تراکنش شما تایید نشد!\nلطفا اگر اشتباهی صورت گرفته با پشتیبانی در تماس باشید.",
"ERROR_PAYMENT_ALREADY_CONFIRMED": "تراکنش قبلا تایید شده است",
"ERROR_PAYMENT_ALREADY_REJECTED": "تراکنش قبلا رد شده است",
"PAYMENT_CONFIRMED_ADMIN": "تراکنش با موفقیت تایید شد",
"PAYMENT_NOT_CONFIRMED_ADMIN": "تراکنش تایید نشد",
"ERROR_ORDER_NOT_FOUND": "❌سفارش یافت نشد",
"ERROR_PAYMENT_NOT_FOUND": "تراکنش یافت نشد",
"ERROR_GIFT_NOT_FOUND": "❌هدیه یافت نشد",
"ORDER_ID": "شناسه تراکنش:",
"SUB_ID": "شناسه اشتراک",
"USER_TIME_EXPIRED": "⚠️منقضی",
"USER_LAST_DAY": "آخرین روز",
"PAYMENT_ASK_CHANGE_STATUS": "آیا میخواهید وضعیت تراکنش را تغییر دهید؟",
"PAYMENT_ACCEPT_STATUS_CONFIRMED": "🟢تایید شده",
"PAYMENT_ACCEPT_STATUS_NOT_CONFIRMED": "🔴رد شده",
"PAYMENT_ACCEPT_STATUS_WAITING": "🟡در انتظار تایید",
"PAYMENT_ACCEPT_STATUS": "وضعیت:",
"CREATED_AT": "تاریخ ایجاد:",
"WALLET_PAYMENT_CONFIRMED": "تراکنش شما تایید شد\n از طریق دکمه [💰کیف پول] میتوانید به موجودی کیف پول خود دسترسی داشته باشید.",
"FEATUR_UNAVAILABLE": "❌این قابلیت در حال حاضر در دسترس نیست.",
"REQUEST_JOIN_HIDY": "📍جهت دریافت آخرین اطلاعات، در گروه پشتیبانی عضو شوید.",
"WELCOME_TO_ADMIN": "ربات مدیریت هیدی بات با موفقیت راهاندازی شد.\nبرای شروع کار، دستور /start را ارسال کنید.",
"SUCCESS_RESTORE_BOT": "✅ربات با موفقیت بازیابی شد",
"ADD_SERVER": "لطفا اطلاعات زیر را برای افزودن سرور وارد کنید",
"ADD_SERVER_TITLE": "لطفا عنوانی را برای سرور وارد کنید:",
"ADD_SERVER_USER_LIMIT": "لطفا محدودیت تعداد کاربر سرور را وارد کنید:",
"ADD_SERVER_URL": "لطفا لینک سرور را وارد کنید:",
"ERROR_ADD_SERVER_URL": "لطفا لینک معتبر ارسال کنید: ",
"ERROR_SAME_SERVER_URL": "این لینک قبلا برای سرور دیگری ثبت شده است، لطفا لینک دیگری ارسال کنید:",
"ADD_SERVER_SUCCESS": "✅سرور با موفقیت افزوده شد",
"INFO_SERVER": "سرور:",
"INFO_SERVER_USER_NUMBER": "تعداد کاربر:",
"INFO_SERVER_USER_PLAN": "تعداد پلن:",
"DELETE_SERVER_QUESTION": "آیا از حذف سرور مطمئن هستید؟\n⚠️بعد از حذف، اشتراکهای مربوط به این سرور برای کاربران قابل مشاهده نمیباشد و غیر قابل بازگردانی میباشد.",
"ERROR_SERVER_NOT_FOUND": "❌سرور یافت نشد",
"INFO_PLAN_ID": "آی دی:",
"INFO_PLAN_USAGE": "محدودیت مصرف(GB):",
"INFO_PLAN_DAYS": "محدودیت زمان(روز):",
"INFO_PLAN_PRICE": "قیمت:",
"INFO_PLAN_DESC": "توضیحات:",
"INFO_PLAN_NUM_ORDER": "تعداد سفارش:",
"INFO_PLAN_TOTAL_SALE": "مجموع فروش:",
"SUCCESS_SERVER_TITLE_EDITED":"✅عنوان سرور ویرایش شد به:",
"SUCCESS_SERVER_USER_LIMIT_EDITED" : "✅محدودیت کاربر ویرایش شد به:",
"SUCCESS_SERVER_URL_EDITED": "✅لینک سرور ویرایش شد به:",
"SERVER": "⬖ سرور: ",
"HEADER_ORDERS_LIST": "⬖ لیست سفارشات",
"NUM_ORDERS": "⬖ تعداد سفارشات: ",
"TOTAL_ORDERS_VALUME": "⬖ مجموع حجم سفارشات(GB): ",
"TOTAL_ORDERS_SALES": "⬖ مجموع ارزش سفارشات: ",
"LAST_30DAYS_NUM_ORDERS": "⬖ تعداد سفارشات 30 روز گذشته: ",
"LAST_30DAYS_ORDERS_VALUME": "⬖ حجم سفارشات 30 روز گذشته(GB): ",
"LAST_30DAYS_ORDERS_SALES": "⬖ ارزش سفارشات 30 روز گذشته: ",
"THIS_MONTH_NUM_ORDERS": "⬖ تعداد سفارشات این ماه: ",
"THIS_MONTH_ORDERS_VALUME": "⬖ حجم سفارشات این ماه(GB): ",
"THIS_MONTH_ORDERS_SALES": "⬖ ارزش سفارشات این ماه: ",
"HEADER_PAYMENT_LIST": "⬖ لیست تراکنشات",
"NUM_PAYMENTS": "⬖ تعداد تراکنشات: ",
"TOTAL_PAYMENTS_AMOUNT": "⬖ مبلغ تراکنشات: ",
"LAST_30DAYS_NUM_PAYMENTS": "⬖ تراکنشات 30 روز گذشته: ",
"LAST_30DAYS_PAYMENTS_AMOUNT": "⬖ مبلغ تراکنشات 30 روز گذشته: ",
"THIS_MONTH_NUM_PAYMENTS": "⬖ تراکنشات این ماه: ",
"THIS_MONTH_PAYMENTS_AMOUNT": "⬖ مبلغ تراکنشات این ماه: ",
"GET_FREE_TEST_STATUS": "⬖ وضعیت دریافت تست رایگان: ",
"WALLET_BALANCE": "⬖ موجودی کیف پول: ",
"NUM_ORDER_SUB": "⬖ تعداد اشتراکهای خریداری شده: ",
"NUM_NON_ORDER_SUB": "⬖ تعداد اشتراکهای متصل شده: ",
"NUM_APPROVED_PAYMENTS": "⬖ تعداد تراکنشات تایید شده: ",
"BOT_ORDER_ID": "⬖ شناسه سفارش: ",
"ORDERED_VALUME": "⬖ حجم سفارش(GB): ",
"ORDERED_DAYS": "⬖ تعداد روز سفارش: ",
"ORDERED_PRICE": "⬖ مبلغ سفارش: ",
"SUB_NAME": "⬖ عنوان اشتراک: ",
"BOT_ORDER_DATE": "⬖ تاریخ سفارش: ",
"ORDER_NUMBER_REQUEST": "لطفا شناسه سفارش را وارد کنید:",
"PAYMENTS_ID": "⬖ شناسه تراکنش: ",
"BOT_PAYMENT_DATE": "⬖ تاریخ تراکنش:",
"PAIED_AMOUNT": "⬖ مبلغ تراکنش: ",
"STATUS": "⬖ وضعیت: ",
"PAYMENTS_METHOD": "⬖ روش تراکنش: ",
"PAYMENT_NUMBER_REQUEST": "لطفا شناسه تراکنش را وارد کنید:",
"CHANGE_STATUS_PAYMENT_CONFIRM_REQUEST": "⚠️آیا از تغییر وضعیت تراکنش، اطمینان دارید؟",
"WALLET_CHANGED_TO_PAYMENT_CONFIRMED": "✅وضیعت تراکنش شما توسط مدیر به تایید شده تغییر یافت\nاز طریق دکمه [💰کیف پول] میتوانید به موجودی کیف پول خود دسترسی داشته باشید.",
"PAYMENT_CHANGED_TO_NOT_CONFIRMED": "❌وضعیت تراکنش شما توسط مدیر به رد شده تغییر یافت و مبلغ تراکنش از موجود کیف پول شما کسر شد!\nلطفا اگر اشتباهی صورت گرفته با پشتیبانی در تماس باشید.",
"PAYMENT_CHANGED_TO_CONFIRMED_ADMIN": "✅وضعیت تراکنش به تایید شده تغییر یافت",
"PAYMENT_CHANGED_TO_NOT_CONFIRMED_ADMIN": "❌وضعیت تراکنش به رد شده تغییر یافت",
"SUCCESS_SEARCH_ORDER": "✅سفارش یافت شد",
"SUCCESS_SEARCH_PAYMENT": "تراکنش یافت شد",
"NOT_SET": "تنظیم نشده",
"EDIT_WALLET_BALANCE": "لطفا مبلغی که میخواهید موجودی کیف پول به آن تغییر کند را به تومان وارد کنید:",
"SEND_MESSAGE_TO_USER": "لطفا متن پیامی که می خواهید برای کاربر ارسال شود را وارد کنید:",
"MESSAGE_SENDED": "پیام ارسال شد",
"ADMIN": "ادمین:",
"MESSAGE_FROM_ADMIN": "📬پیام جدیدی از سمت ادمین دریافت شد",
"MESSAGE_TEXT": "📄متن پیام:",
"ERROR_USER_HAVE_TEST_SUB": "❌کاربر اکنون نیز اشتراک تست رایگان دارد",
"SUCCESS_RESET_TEST_SUB": "✅اشتراک تست رایگان این کاربر با موفقیت بازنشانی شد",
"WALLET_BALANCE_CHANGED_BY_ADMIN_P1": "💰موجودی کیف پول شما توسط مدیر به",
"WALLET_BALANCE_CHANGED_BY_ADMIN_P2": "تومان تغییر یافت",
"SUCCESS_BAN_USER": "✅کاربر مسدود شد",
"SUCCESS_UNBAN_USER": "✅کاربر مسدود شده، آزاد شد"
}
}
================================================
FILE: AdminBot/bot.py
================================================
# Description: Main Bot File
import datetime
import html
import logging
import operator
import time
import telebot
import os
from telebot.types import Message, CallbackQuery
from config import TELEGRAM_TOKEN, ADMINS_ID, PANEL_ADMIN_ID, CLIENT_TOKEN, BOT_BACKUP_LOC
from AdminBot.content import BOT_COMMANDS, MESSAGES, KEY_MARKUP
from AdminBot import markups
from AdminBot import templates
from Utils import utils
from Shared.common import user_bot
from Database.dbManager import USERS_DB
from Utils import api
from config import panel_url_validator, API_PATH
# Initialize Bot
bot = telebot.TeleBot(TELEGRAM_TOKEN, parse_mode="HTML")
bot.remove_webhook()
URL = 'url'
selected_server = None
search_mode = "Single"
server_mode = "Single"
searched_name = ""
list_mode = ""
item_mode= ""
selected_telegram_id = "0"
if CLIENT_TOKEN:
user_bot = user_bot()
# ----------------------------------- Helper Functions -----------------------------------
# Check if message is digit
def is_it_digit(message: Message, allow_float=False, response=MESSAGES['ERROR_INVALID_NUMBER'],
markup=markups.main_menu_keyboard_markup()):
if not message.text:
bot.send_message(message.chat.id, response, reply_markup=markup)
return False
try:
value = float(message.text) if allow_float else int(message.text)
return True
except ValueError:
bot.send_message(message.chat.id, response, reply_markup=markup)
return False
# Check if message is cancel
def is_it_cancel(message: Message, response=MESSAGES['CANCELED']):
if message.text == KEY_MARKUP['CANCEL']:
bot.send_message(message.chat.id, response, reply_markup=markups.main_menu_keyboard_markup())
return True
return False
def message_to_html(message: Message):
text = message.text
entities = message.entities
html_content = ""
offset = 0
for entity in entities:
html_content += html.escape(text[offset:entity.offset])
if entity.type == 'bold':
html_content += f'{html.escape(text[entity.offset:entity.offset + entity.length])}'
elif entity.type == 'italic':
html_content += f'{html.escape(text[entity.offset:entity.offset + entity.length])}'
elif entity.type == 'code':
html_content += f'{html.escape(text[entity.offset:entity.offset + entity.length])}'
elif entity.type == 'pre':
html_content += f'
{html.escape(text[entity.offset:entity.offset + entity.length])}'
elif entity.type == 'text_link':
html_content += f'{html.escape(text[entity.offset:entity.offset + entity.length])}'
offset = entity.offset + entity.length
html_content += html.escape(text[offset:])
return html_content
# ----------------------------------- Add User Area -----------------------------------
# Add user Data dict
add_user_data = {}
# Add User - Name
def add_user_name(message: Message, server_id):
if is_it_cancel(message):
return
add_user_data['name'] = message.text
bot.send_message(message.chat.id, MESSAGES['ADD_USER_USAGE_LIMIT'], reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(message, add_user_limit, server_id)
# Add User - Usage Limit
def add_user_limit(message: Message, server_id):
if is_it_cancel(message):
return
if not is_it_digit(message, f"{MESSAGES['ERROR_INVALID_NUMBER']}\n{MESSAGES['ADD_USER_USAGE_LIMIT']}",
markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, add_user_limit, server_id)
return
add_user_data['limit'] = message.text
bot.send_message(message.chat.id, MESSAGES['ADD_USER_DAYS'], reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(message, add_user_usage_days, server_id)
# Add User - Usage Days
def add_user_usage_days(message: Message, server_id):
if is_it_cancel(message, MESSAGES['CANCEL_ADD_USER']):
return
if not is_it_digit(message, f"{MESSAGES['ERROR_INVALID_NUMBER']}\n{MESSAGES['ADD_USER_DAYS']}",
markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, add_user_usage_days, server_id)
return
add_user_data['usage_days'] = message.text
bot.send_message(message.chat.id,
f"{MESSAGES['ADD_USER_CONFIRM']}\n\n{MESSAGES['INFO_USER_NAME']} {add_user_data['name']}\n"
f"{MESSAGES['INFO_USAGE']} {add_user_data['limit']} {MESSAGES['GB']}\n{MESSAGES['INFO_REMAINING_DAYS']} {add_user_data['usage_days']} {MESSAGES['DAY']}",
reply_markup=markups.confirm_add_user_markup())
bot.register_next_step_handler(message, confirm_add_user, server_id)
# Add User - Confirm to add user
def confirm_add_user(message: Message, server_id):
if message.text == KEY_MARKUP['CANCEL']:
bot.send_message(message.chat.id, MESSAGES['CANCEL_ADD_USER'], reply_markup=markups.main_menu_keyboard_markup())
return
if message.text == KEY_MARKUP['CONFIRM']:
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'])
# res = ADMIN_DB.add_default_user(name=add_user_data['name'], package_days=int(add_user_data['usage_days']),
# usage_limit_GB=int(add_user_data['limit']))
server = USERS_DB.find_server(id=int(server_id))
if not server:
bot.send_message(message.chat.id, MESSAGES['ERROR_SERVER_NOT_FOUND'])
return
server = server[0]
URL = server['url'] + API_PATH
res = api.insert(URL, name=add_user_data['name'], package_days=int(add_user_data['usage_days']),
usage_limit_GB=int(add_user_data['limit']))
if res:
bot.send_message(message.chat.id, MESSAGES['SUCCESS_ADD_USER'],
reply_markup=markups.main_menu_keyboard_markup())
usr = utils.user_info(URL, res)
if not usr:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
msg = templates.user_info_template(usr, server, MESSAGES['NEW_USER_INFO'])
bot.delete_message(message.chat.id, msg_wait.message_id)
bot.send_message(message.chat.id, msg, reply_markup=markups.user_info_markup(usr['uuid']))
else:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
else:
bot.send_message(message.chat.id, MESSAGES['CANCEL_ADD_USER'], reply_markup=markups.main_menu_keyboard_markup())
# ----------------------------------- Edit User Area -----------------------------------
# Edit User - Name
def edit_user_name(message: Message, uuid):
if is_it_cancel(message):
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
# status = ADMIN_DB.edit_user(uuid, name=message.text)
status = api.update(URL, uuid, name=message.text)
bot.delete_message(message.chat.id, msg_wait.message_id)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, f"{MESSAGES['SUCCESS_USER_NAME_EDITED']} {message.text} ",
reply_markup=markups.main_menu_keyboard_markup())
# Edit User - Usage
def edit_user_usage(message: Message, uuid):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, edit_user_usage, uuid)
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
# status = ADMIN_DB.edit_user(uuid, usage_limit_GB=int(message.text))
status = api.update(URL, uuid, usage_limit_GB=int(message.text))
bot.delete_message(message.chat.id, msg_wait.message_id)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, f"{MESSAGES['SUCCESS_USER_USAGE_EDITED']} {message.text} {MESSAGES['GB']}",
reply_markup=markups.main_menu_keyboard_markup())
# Edit User - Days
def edit_user_days(message: Message, uuid):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, edit_user_days, uuid)
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
# status = ADMIN_DB.edit_user(uuid, package_days=int(message.text))
status = api.update(URL, uuid, package_days=int(message.text))
bot.delete_message(message.chat.id, msg_wait.message_id)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id,
f"{MESSAGES['SUCCESS_USER_DAYS_EDITED']} {message.text} {MESSAGES['DAY_EXPIRE']} ",
reply_markup=markups.main_menu_keyboard_markup())
# Edit User - Comment
def edit_user_comment(message: Message, uuid):
if is_it_cancel(message):
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
# status = ADMIN_DB.edit_user(uuid, comment=message.text)
status = api.update(URL, uuid, comment=message.text)
bot.delete_message(message.chat.id, msg_wait.message_id)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, f"{MESSAGES['SUCCESS_USER_COMMENT_EDITED']} {message.text} ",
reply_markup=markups.main_menu_keyboard_markup())
# ----------------------------------- Search User Area -----------------------------------
# Search User - Name
def search_user_name(message: Message, server_id):
global searched_name
if is_it_cancel(message):
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
searched_name = message.text
users = utils.search_user_by_name(URL, searched_name)
bot.delete_message(message.chat.id, msg_wait.message_id)
if not users:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_USER'], reply_markup=markups.main_menu_keyboard_markup())
bot.send_message(message.chat.id, templates.users_list_template(users, MESSAGES['SEARCH_RESULT']),
reply_markup=markups.users_list_markup(server_id, users))
# Search User - UUID
def search_user_uuid(message: Message, server_id):
if is_it_cancel(message):
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
user = utils.search_user_by_uuid(URL, message.text)
bot.delete_message(message.chat.id, msg_wait.message_id)
if not user:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
server = USERS_DB.find_server(id=int(server_id))
if not server:
bot.send_message(message.chat.id, MESSAGES['ERROR_SERVER_NOT_FOUND'])
return
server = server[0]
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_USER'], reply_markup=markups.main_menu_keyboard_markup())
bot.send_message(message.chat.id, templates.user_info_template(user, server, MESSAGES['SEARCH_RESULT']),
reply_markup=markups.user_info_markup(user['uuid']))
# Search User - Config
def search_user_config(message: Message, server_id):
if is_it_cancel(message):
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
user = utils.search_user_by_config(URL, message.text)
bot.delete_message(message.chat.id, msg_wait.message_id)
if not user:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
server = USERS_DB.find_server(id=int(server_id))
if not server:
bot.send_message(message.chat.id, MESSAGES['ERROR_SERVER_NOT_FOUND'])
return
server = server[0]
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_USER'], reply_markup=markups.main_menu_keyboard_markup())
bot.send_message(message.chat.id, templates.user_info_template(user, server, MESSAGES['SEARCH_RESULT']),
reply_markup=markups.user_info_markup(user['uuid']))
# All Servers Search User - Name
def all_server_search_user_name(message: Message):
global searched_name
if is_it_cancel(message):
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
users = []
searched_name = message.text
servers = USERS_DB.select_servers()
if servers:
for server in servers:
URL = server['url'] + API_PATH
searched_users = utils.search_user_by_name(URL, searched_name)
if searched_users:
users.extend(searched_users)
bot.delete_message(message.chat.id, msg_wait.message_id)
if not users:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_USER'], reply_markup=markups.main_menu_keyboard_markup())
bot.send_message(message.chat.id, templates.users_list_template(users, MESSAGES['SEARCH_RESULT']),
reply_markup=markups.users_list_markup("None", users))
# All Servers Search User - UUID
def all_server_search_user_uuid(message: Message):
selected_server = None
if is_it_cancel(message):
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
servers = USERS_DB.select_servers()
if servers:
for server in servers:
URL = server['url'] + API_PATH
user = utils.search_user_by_uuid(URL, message.text)
if user:
selected_server = server
break
bot.delete_message(message.chat.id, msg_wait.message_id)
if not user:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_USER'], reply_markup=markups.main_menu_keyboard_markup())
bot.send_message(message.chat.id, templates.user_info_template(user, selected_server, MESSAGES['SEARCH_RESULT']),
reply_markup=markups.user_info_markup(user['uuid']))
# All Servers Search User - Config
def all_server_search_user_config(message: Message):
selected_server = None
if is_it_cancel(message):
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
servers = USERS_DB.select_servers()
if servers:
for server in servers:
URL = server['url'] + API_PATH
user = utils.search_user_by_config(URL, message.text)
if user:
selected_server = server
break
bot.delete_message(message.chat.id, msg_wait.message_id)
if not user:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_USER'], reply_markup=markups.main_menu_keyboard_markup())
bot.send_message(message.chat.id, templates.user_info_template(user, selected_server, MESSAGES['SEARCH_RESULT']),
reply_markup=markups.user_info_markup(user['uuid']))
# ----------------------------------- Users Bot Search Area -----------------------------------
# User Bot Search - Name
def search_bot_user_name(message: Message):
global searched_name
if is_it_cancel(message):
return
searched_name = message.text
users = USERS_DB.find_user(full_name=searched_name)
if not users:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
users.sort(key = operator.itemgetter('created_at'), reverse=True)
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_USER'], reply_markup=markups.main_menu_keyboard_markup())
wallets_list = USERS_DB.select_wallet()
orders_list = USERS_DB.select_orders()
msg = templates.bot_users_list_template(users, wallets_list, orders_list)
bot.send_message(message.chat.id, msg, reply_markup=markups.bot_users_list_markup(users))
# User Bot Search - Name
def search_bot_user_telegram_id(message: Message):
global selected_telegram_id
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, search_bot_user_telegram_id)
return
searched_id = message.text
users = USERS_DB.find_user(telegram_id=int(searched_id))
if not users:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
user = users[0]
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_USER'], reply_markup=markups.main_menu_keyboard_markup())
selected_telegram_id = user['telegram_id']
orders = USERS_DB.find_order(telegram_id=user['telegram_id'])
paymets = USERS_DB.find_payment(telegram_id=user['telegram_id'])
wallet = None
wallets = USERS_DB.find_wallet(telegram_id=user['telegram_id'])
if wallets:
wallet = wallets[0]
non_order_subs = utils.non_order_user_info(user['telegram_id'])
order_subs = utils.order_user_info(user['telegram_id'])
plans_list = USERS_DB.select_plans()
msg = templates.bot_users_info_template(user, orders, paymets, wallet, non_order_subs, order_subs, plans_list)
bot.send_message(message.chat.id, msg, reply_markup=markups.bot_user_info_markup(user['telegram_id']))
# User Bot Search - Order
def search_bot_user_order(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, search_bot_user_order)
return
orders = USERS_DB.find_order(id=int(message.text))
if not orders:
bot.send_message(message.chat.id, MESSAGES['ERROR_ORDER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
order = orders[0]
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_ORDER'], reply_markup=markups.main_menu_keyboard_markup())
plans = USERS_DB.find_plan(id=order['plan_id'])
if not plans:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
plan = plans[0]
#subs =
users = USERS_DB.find_user(telegram_id=order['telegram_id'])
if not users:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
user = users[0]
servers = USERS_DB.find_server(id=plan['server_id'])
if not servers:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
server = servers[0]
msg = templates.bot_orders_info_template(order, plan, user, server)
bot.send_message(message.chat.id, msg)
# User Bot Search - Payment
def search_bot_user_payment(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, search_bot_user_payment)
return
payments = USERS_DB.find_payment(id=int(message.text))
if not payments:
bot.send_message(message.chat.id, MESSAGES['ERROR_ORDER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_PAYMENT'], reply_markup=markups.main_menu_keyboard_markup())
payment = payments[0]
user_data = USERS_DB.find_user(telegram_id=payment['telegram_id'])
if not user_data:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
user_data = user_data[0]
msg = templates.bot_payment_info_template(payment,user_data)
photo_path = os.path.join(os.getcwd(), 'UserBot', 'Receiptions', payment['payment_image'])
bot.send_photo(message.chat.id, photo=open(photo_path, 'rb'),
caption=msg, reply_markup=markups.change_status_payment_by_admin(payment['id']))
# ----------------------------------- Users Bot Management Area -----------------------------------
#add_plan_data = {}
# Add Plan - Size
# def users_bot_add_plan_usage(message: Message):
# if is_it_cancel(message):
# return
# if not is_it_digit(message):
# return
# add_plan_data['usage'] = int(message.text)
# bot.send_message(message.chat.id, MESSAGES['USERS_BOT_ADD_PLAN_DAYS'],
# reply_markup=markups.while_edit_user_markup())
# bot.register_next_step_handler(message, users_bot_add_plan_days)
# # Add Plan - Days
# def users_bot_add_plan_days(message: Message):
# if is_it_cancel(message):
# return
# if not is_it_digit(message):
# return
# add_plan_data['days'] = int(message.text)
# bot.send_message(message.chat.id, MESSAGES['USERS_BOT_ADD_PLAN_PRICE'],
# reply_markup=markups.while_edit_user_markup())
# bot.register_next_step_handler(message, users_bot_add_plan_price)
# # Add Plan - Price
# def users_bot_add_plan_price(message: Message):
# if is_it_cancel(message):
# return
# if not is_it_digit(message):
# return
# add_plan_data['price'] = utils.toman_to_rial(message.text)
# msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
# status = utils.users_bot_add_plan(add_plan_data['usage'], add_plan_data['days'], add_plan_data['price'])
# bot.delete_message(message.chat.id, msg_wait.message_id)
# if not status:
# bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
# return
# bot.send_message(message.chat.id, MESSAGES['USERS_BOT_ADD_PLAN_SUCCESS'],
# reply_markup=markups.main_menu_keyboard_markup())
# ----------------------------------- Server Management Area -----------------------------------
add_server_data = {}
# Add Server - Title
def add_server_title(message: Message):
if is_it_cancel(message):
return
add_server_data['title'] = message.text
bot.send_message(message.chat.id, MESSAGES['ADD_SERVER_URL'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(message, add_server_url)
# Add Server - url
def add_server_url(message: Message):
if is_it_cancel(message):
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
url = panel_url_validator(message.text)
bot.delete_message(message.chat.id, msg_wait.message_id)
if not url:
bot.reply_to(message, MESSAGES['ERROR_ADD_SERVER_URL'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(message, add_server_url)
return
servers = USERS_DB.select_servers()
if servers:
for server in servers:
if server['url'] == url:
bot.reply_to(message, MESSAGES['ERROR_SAME_SERVER_URL'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(message, add_server_url)
return
add_server_data['url'] = url
bot.send_message(message.chat.id, MESSAGES['ADD_SERVER_USER_LIMIT'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(message, add_server_user_limit)
# Add Server - User Limit
def add_server_user_limit(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, add_server_user_limit)
return
add_server_data['user_limit'] = int(message.text)
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
status = utils.add_server(url=add_server_data['url'], user_limit=add_server_data['user_limit'], title=add_server_data['title'])
bot.delete_message(message.chat.id, msg_wait.message_id)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['ADD_SERVER_SUCCESS'],
reply_markup=markups.main_menu_keyboard_markup())
servers = USERS_DB.select_servers()
bot.send_message(message.chat.id, KEY_MARKUP['SERVERS_MANAGEMENT'],
reply_markup=markups.servers_management_markup(servers))
# Edit Server - Server Title
def edit_server_title(message: Message, server_id):
if is_it_cancel(message):
return
status = USERS_DB.edit_server(int(server_id), title=message.text)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'])
server = USERS_DB.find_server(id=int(server_id))
if not server:
bot.send_message(message.chat.id, MESSAGES['ERROR_SERVER_NOT_FOUND'])
return
server = server[0]
bot.send_message(message.chat.id, f"{MESSAGES['SUCCESS_SERVER_TITLE_EDITED']}{server['title']}",
reply_markup=markups.main_menu_keyboard_markup())
plans = USERS_DB.select_plans()
msg = templates.server_info_template(server,plans)
bot.send_message(message.chat.id, msg,
reply_markup=markups.server_edit_markup(server_id))
# Edit Server - Server User Limit
def edit_server_user_limit(message: Message, server_id):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, edit_server_user_limit, server_id)
return
status = USERS_DB.edit_server(int(server_id), user_limit=int(message.text))
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'])
server = USERS_DB.find_server(id=int(server_id))
if not server:
bot.send_message(message.chat.id, MESSAGES['ERROR_SERVER_NOT_FOUND'])
return
server = server[0]
bot.send_message(message.chat.id, f"{MESSAGES['SUCCESS_SERVER_USER_LIMIT_EDITED']}{server['user_limit']}",
reply_markup=markups.main_menu_keyboard_markup())
plans = USERS_DB.select_plans()
msg = templates.server_info_template(server,plans)
bot.send_message(message.chat.id, msg,
reply_markup=markups.server_edit_markup(server_id))
# Edit Server - Server Url
def edit_server_url(message: Message, server_id):
if is_it_cancel(message):
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
url = panel_url_validator(message.text)
bot.delete_message(message.chat.id, msg_wait.message_id)
if not url:
bot.send_message(message.chat.id, MESSAGES['ERROR_ADD_SERVER_URL'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(message, edit_server_url, server_id)
return
servers = USERS_DB.select_servers()
if servers:
for server in servers:
if server['url'] == url:
bot.reply_to(message, MESSAGES['ERROR_SAME_SERVER_URL'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(message, edit_server_url, server_id)
return
status = USERS_DB.edit_server(int(server_id), url=url)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
server = USERS_DB.find_server(id=int(server_id))
if not server:
bot.send_message(message.chat.id, MESSAGES['ERROR_SERVER_NOT_FOUND'])
return
server = server[0]
bot.send_message(message.chat.id, f"{MESSAGES['SUCCESS_SERVER_URL_EDITED']}\n{server['url']}",
reply_markup=markups.main_menu_keyboard_markup())
plans = USERS_DB.select_plans()
msg = templates.server_info_template(server,plans)
bot.send_message(message.chat.id, msg,
reply_markup=markups.server_edit_markup(server_id))
# ----------------------------------- Users Bot Management Area -----------------------------------
add_plan_data = {}
# Add Plan - Size
def users_bot_add_plan_usage(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_add_plan_usage)
return
add_plan_data['usage'] = int(message.text)
bot.send_message(message.chat.id, MESSAGES['USERS_BOT_ADD_PLAN_DAYS'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(message, users_bot_add_plan_days)
# Add Plan - Days
def users_bot_add_plan_days(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_add_plan_days)
return
add_plan_data['days'] = int(message.text)
bot.send_message(message.chat.id, MESSAGES['USERS_BOT_ADD_PLAN_PRICE'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(message, users_bot_add_plan_price)
# Add Plan - Price
def users_bot_add_plan_price(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_add_plan_price)
return
add_plan_data['price'] = utils.toman_to_rial(message.text)
bot.send_message(message.chat.id, MESSAGES['USERS_BOT_ADD_PLAN_DESC'],
reply_markup=markups.while_edit_skip_user_markup())
bot.register_next_step_handler(message, users_bot_add_plan_description)
def users_bot_add_plan_description(message: Message):
if is_it_cancel(message):
return
if message.text == KEY_MARKUP['SKIP']:
add_plan_data['description'] = None
else:
add_plan_data['description'] = message.text
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
status = utils.users_bot_add_plan(add_plan_data['usage'], add_plan_data['days'],
add_plan_data['price'], add_plan_data['server_id'], add_plan_data['description'])
bot.delete_message(message.chat.id, msg_wait.message_id)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['USERS_BOT_ADD_PLAN_SUCCESS'],
reply_markup=markups.main_menu_keyboard_markup())
plans_list = []
plans = USERS_DB.select_plans()
if plans:
for plan in plans:
if plan['status']:
if plan['server_id'] == int(add_plan_data['server_id']):
plans_list.append(plan)
plans_markup = markups.plans_list_markup(plans_list,add_plan_data['server_id'])
bot.send_message(message.chat.id, {MESSAGES['USERS_BOT_PLANS_LIST']},
reply_markup=plans_markup)
# Users Bot - Edit Owner Info - Username
def users_bot_edit_owner_info_username(message: Message):
if is_it_cancel(message):
return
if not message.text.startswith('@'):
bot.send_message(message.chat.id, MESSAGES['ERROR_INVALID_USERNAME'],
reply_markup=markups.main_menu_keyboard_markup())
return
status = USERS_DB.edit_str_config("support_username", value=message.text)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
# Users Bot - Edit Owner Info - Card Number
def users_bot_edit_owner_info_card_number(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_edit_owner_info_card_number)
return
if len(message.text) != 16:
bot.send_message(message.chat.id, MESSAGES['ERROR_INVALID_CARD_NUMBER'],
reply_markup=markups.main_menu_keyboard_markup())
return
status = USERS_DB.edit_str_config("card_number", value=message.text)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
# Users Bot - Edit Owner Info - Cardholder Name
def users_bot_edit_owner_info_card_name(message: Message):
if is_it_cancel(message):
return
status = USERS_DB.edit_str_config("card_holder", value=message.text)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
# Users Bot - Send Message - All Users
def users_bot_send_msg_users(message: Message):
if is_it_cancel(message):
return
if not CLIENT_TOKEN:
bot.send_message(message.chat.id, MESSAGES['ERROR_CLIENT_TOKEN'],
reply_markup=markups.main_menu_keyboard_markup())
return
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=markups.while_edit_user_markup())
users_number_id = USERS_DB.select_users()
bot.delete_message(message.chat.id, msg_wait.message_id)
if not users_number_id:
bot.send_message(message.chat.id, MESSAGES['ERROR_NO_USERS'], reply_markup=markups.main_menu_keyboard_markup())
return
for user in users_number_id:
time.sleep(0.05)
try:
user_bot.send_message(user['telegram_id'], message.text)
except Exception as e:
logging.warning(f"Error in send message to user {user['telegram_id']}: {e}")
continue
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEND_MSG_USERS'],
reply_markup=markups.main_menu_keyboard_markup())
# Users Bot - Settings - Update Message
def users_bot_settings_update_message(message: Message, markup,title=MESSAGES['USERS_BOT_SETTINGS']):
settings = utils.all_configs_settings()
bot.edit_message_text(chat_id=message.chat.id, message_id=message.message_id,
text=title,
reply_markup=markup)
# # Users Bot - Order Status
# def users_bot_order_status(message: Message):
# from UserBot.templates import payment_received_template
# if is_it_cancel(message):
# return
# if not is_it_digit(message):
# return
# payment = USERS_DB.find_payment(id=int(message.text))
# if not payment:
# bot.send_message(message.chat.id, MESSAGES['ERROR_ORDER_NOT_FOUND'],
# reply_markup=markups.main_menu_keyboard_markup())
# return
# # plan = USERS_DB.find_plan(id=payment[0]['plan_id'])
# # if not payment:
# # bot.send_message(message.chat.id, MESSAGES['ERROR_ORDER_NOT_FOUND'], reply_markup=markups.main_menu_keyboard_markup())
# # return
# payment = payment[0]
# user_data = USERS_DB.find_user(telegram_id=payment['telegram_id'])
# if not user_data:
# bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
# reply_markup=markups.main_menu_keyboard_markup())
# return
# user_data = user_data[0]
# is_it_accepted = None
# if payment['approved'] == 0:
# is_it_accepted = MESSAGES['PAYMENT_ACCEPT_STATUS_NOT_CONFIRMED']
# elif payment['approved'] == 1:
# is_it_accepted = MESSAGES['PAYMENT_ACCEPT_STATUS_CONFIRMED']
# else:
# is_it_accepted = MESSAGES['PAYMENT_ACCEPT_STATUS_WAITING']
# photo_path = path_recp = os.path.join(os.getcwd(), 'UserBot', 'Receiptions', payment['payment_image'])
# bot.send_photo(message.chat.id, photo=open(photo_path, 'rb'),
# caption=payment_received_template(payment,user_data,
# footer=f"{MESSAGES['PAYMENT_ACCEPT_STATUS']} {is_it_accepted}\n{MESSAGES['CREATED_AT']} {payment['created_at']}"),
# reply_markup=markups.main_menu_keyboard_markup())
def users_bot_sub_status(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_sub_status)
return
bot_user = None
if len(message.text) == 7:
user = USERS_DB.find_order_subscription(id=int(message.text))
if user:
orders = USERS_DB.find_order(id=user[0]['order_id'])
if orders:
bot_users = USERS_DB.find_user(telegram_id=orders[0]['telegram_id'])
if bot_users:
bot_user = bot_users[0]
elif len(message.text) == 8:
user = USERS_DB.find_non_order_subscription(id=int(message.text))
if user:
bot_users = USERS_DB.find_user(telegram_id=user[0]['telegram_id'])
if bot_users:
bot_user = bot_users[0]
else:
bot.send_message(message.chat.id, MESSAGES['ERROR_SUB_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
if not user:
bot.send_message(message.chat.id, MESSAGES['ERROR_SUB_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
if not bot_user:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
user_uuid = user[0]['uuid']
selected_server = None
servers = USERS_DB.select_servers()
usr = None
if servers:
for server in servers:
URL = server['url'] + API_PATH
usr = utils.user_info(URL, user_uuid)
if usr:
selected_server = server
break
else:
continue
if not usr:
bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'],
reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_SEARCH_SUB'],
reply_markup=markups.main_menu_keyboard_markup())
msg = templates.user_info_template(usr, selected_server)
bot.send_message(message.chat.id, msg,
reply_markup=markups.sub_search_info_markup(usr['uuid'], bot_user))
def users_bot_settings_min_depo(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_settings_min_depo)
return
new_min_depo = utils.toman_to_rial(message.text)
new_min_depo = int(new_min_depo)
status = USERS_DB.edit_int_config("min_deposit_amount", value=new_min_depo)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_channel_id(message: Message):
if is_it_cancel(message):
return
if not message.text.startswith('@'):
bot.send_message(message.chat.id, MESSAGES['ERROR_INVALID_USERNAME'],
reply_markup=markups.main_menu_keyboard_markup())
return
status = USERS_DB.edit_str_config("channel_id", value=message.text)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_welcome_msg(message: Message):
if is_it_cancel(message):
return
status = USERS_DB.edit_str_config("msg_user_start", value=message.html_text)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_set_faq_msg(message: Message, msg):
if is_it_cancel(message):
return
status = USERS_DB.edit_str_config("msg_faq", value=message.html_text)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
try:
bot.edit_message_reply_markup(message.chat.id, msg.message_id,
reply_markup=markups.users_bot_management_settings_faq_markup())
except:
pass
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_test_sub_size(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, allow_float=True, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_settings_test_sub_size)
return
# if float convert float else convert int
if '.' in message.text:
new_test_sub_size = float(message.text)
else:
new_test_sub_size = int(message.text)
status = USERS_DB.edit_int_config("test_sub_size_gb", value=new_test_sub_size)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_test_sub_days(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_settings_test_sub_days)
return
new_test_sub_days = int(message.text)
status = USERS_DB.edit_int_config("test_sub_days", value=new_test_sub_days)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_notif_reminder_usage(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, allow_float=True, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_settings_notif_reminder_usage)
return
if '.' in message.text:
new_reminder_usage = float(message.text)
else:
new_reminder_usage = int(message.text)
status = USERS_DB.edit_int_config("reminder_notification_usage", value=new_reminder_usage)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_notif_reminder_days(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_settings_notif_reminder_days)
return
new_test_sub_days = int(message.text)
status = USERS_DB.edit_int_config("reminder_notification_days", value=new_test_sub_days)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_panel_manual(message: Message, db_key):
if is_it_cancel(message):
return
status = USERS_DB.edit_str_config(db_key, value=message.html_text)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_restore_bot(message: Message):
if is_it_cancel(message):
return
# save file
file_name = message.document.file_name
file_info = bot.get_file(message.document.file_id)
downloaded_file = bot.download_file(file_info.file_path)
file_save_path = os.path.join(BOT_BACKUP_LOC,"Restore")
if not os.path.exists(file_save_path):
os.makedirs(file_save_path)
# save in Backup/bot/restore
with open(os.path.join(file_save_path,file_name), 'wb') as new_file:
new_file.write(downloaded_file)
restore_status = utils.restore_json_bot(os.path.join(file_save_path,file_name))
if not restore_status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['SUCCESS_RESTORE_BOT'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_renewal_method_advanced_days(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_settings_renewal_method_advanced_days)
return
new_test_sub_days = int(message.text)
status = USERS_DB.edit_int_config("advanced_renewal_days", value=new_test_sub_days)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def users_bot_settings_renewal_method_advanced_usage(message: Message):
if is_it_cancel(message):
return
if not is_it_digit(message, allow_float=True, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, users_bot_settings_renewal_method_advanced_usage)
return
if '.' in message.text:
new_renewal_usage = float(message.text)
else:
new_renewal_usage = int(message.text)
status = USERS_DB.edit_int_config("advanced_renewal_usage", value=new_renewal_usage)
if not status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
def edit_wallet_balance(message: Message,telegram_id):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=markups.while_edit_user_markup()):
bot.register_next_step_handler(message, edit_wallet_balance)
return
new_balance = utils.toman_to_rial(message.text)
wallet_status = USERS_DB.find_wallet(telegram_id=telegram_id)
if not wallet_status:
status = USERS_DB.add_wallet(telegram_id=telegram_id)
if not status:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
status = USERS_DB.edit_wallet(telegram_id=telegram_id, balance=new_balance)
if not status:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'])
bot.send_message(message.chat.id, MESSAGES['SUCCESS_UPDATE_DATA'], reply_markup=markups.main_menu_keyboard_markup())
user_bot.send_message(telegram_id, f"{MESSAGES['WALLET_BALANCE_CHANGED_BY_ADMIN_P1']} {message.text} {MESSAGES['WALLET_BALANCE_CHANGED_BY_ADMIN_P2']}")
def send_message_to_user(message: Message, payment_id):
if is_it_cancel(message):
return
payment_info = USERS_DB.find_payment(id=int(payment_id))
if not payment_info:
bot.send_message(message.chat.id,
f"{MESSAGES['ERROR_PAYMENT_NOT_FOUND']}\n{MESSAGES['ORDER_ID']} {payment_id}")
return
payment_info = payment_info[0]
user_bot.send_message(int(payment_info['telegram_id']),
f"{MESSAGES['ADMIN']}\n{message.text}\n{MESSAGES['ORDER_ID']} {payment_id}",
reply_markup=markups.send_message_to_user_markup(message.chat.id))
bot.send_message(message.chat.id, MESSAGES['MESSAGE_SENDED'],
reply_markup=markups.main_menu_keyboard_markup())
def users_bot_send_message_to_user(message: Message, telegram_id):
if is_it_cancel(message):
return
user_bot.send_message(int(telegram_id),
f"{MESSAGES['MESSAGE_FROM_ADMIN']}\n{MESSAGES['MESSAGE_TEXT']} {message.text}", reply_markup=markups.send_message_to_user_markup(message.chat.id))
bot.send_message(message.chat.id, MESSAGES['MESSAGE_SENDED'],
reply_markup=markups.main_menu_keyboard_markup())
# ----------------------------------- Callbacks -----------------------------------
# Callback Handler for Inline Buttons
@bot.callback_query_handler(func=lambda call: True)
def callback_query(call: CallbackQuery):
logging.info(f"Callback Query: {call.data}")
bot.answer_callback_query(call.id, MESSAGES['WAIT'])
# Check if user is not admin
if call.from_user.id not in ADMINS_ID:
bot.answer_callback_query(call.id, MESSAGES['ERROR_NOT_ADMIN'])
return
bot.clear_step_handler(call.message)
# Split Callback Data to Key(Command) and UUID
data = call.data.split(':')
key = data[0]
value = data[1]
global URL
#Single , Single_name , Single_expired , All_server_name , All_server_expired
global search_mode
# All , Single
global server_mode
global searched_name
global selected_server
#User_Orders, User_Payments, User_Gifts, Orders, Approved_Payments
#Non_Approved_Payments, Pending_Payments, Card_Payments, Digital_Payments
#Bot_User, Bot_Users_Search_Name, User_Refferals
global list_mode
#Order, Payment, Gift
global item_mode
global selected_telegram_id
# ----------------------------------- Users List Area Callbacks -----------------------------------
# Single User Info Callback
if key == "info":
if server_mode == "Single":
usr = utils.user_info(URL, value)
else:
servers = USERS_DB.select_servers()
if servers:
for server in servers:
URL = server['url'] + API_PATH
usr = utils.user_info(URL, value)
if usr:
selected_server = server
break
if not usr:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
msg = templates.user_info_template(usr, selected_server)
bot.send_message(call.message.chat.id, msg,
reply_markup=markups.user_info_markup(usr['uuid']))
# Next Page Callback
elif key == "next":
# users_list = utils.dict_process(utils.users_to_dict(ADMIN_DB.select_users()))
users_list = []
server_id = selected_server['id']
if search_mode == "Single":
users_list = api.select(URL)
server_id = selected_server['id']
elif search_mode == "Single_name":
users_list = utils.search_user_by_name(URL, searched_name)
server_id = selected_server['id']
elif search_mode == "Single_expired":
users_list = api.select(URL)
users_list = utils.expired_users_list(users_list)
server_id = selected_server['id']
elif search_mode == "All_server_name":
servers = USERS_DB.select_servers()
if servers:
for server in servers:
server_url = server['url'] + API_PATH
searched_users = utils.search_user_by_name(server_url, searched_name)
users_list.extend(searched_users)
server_id = "None"
elif search_mode == "All_server_expired":
servers = USERS_DB.select_servers()
if servers:
for server in servers:
server_url = server['url'] + API_PATH
users = api.select(server_url)
users = utils.expired_users_list(users)
users_list.extend(users)
server_id = "None"
if not users_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.users_list_markup(server_id, users_list, int(value)))
# ----------------------------------- Single User Info Area Callbacks -----------------------------------
# Delete User Callback
elif key == "user_delete":
# status = ADMIN_DB.delete_user(uuid=value)
bot.send_message(call.message.chat.id, MESSAGES['FEATUR_UNAVAILABLE'],
reply_markup=markups.main_menu_keyboard_markup())
return
# if not status:
# bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
# reply_markup=markups.main_menu_keyboard_markup())
# return
# bot.delete_message(call.message.chat.id, call.message.message_id)
# bot.send_message(call.message.chat.id, MESSAGES['SUCCESS_USER_DELETED'],
# reply_markup=markups.main_menu_keyboard_markup())
# Edit User Main Button Callback
elif key == "user_edit":
if server_mode == "All":
servers = USERS_DB.select_servers()
if servers:
for server in servers:
users_list = api.find(server['url'] + API_PATH, value)
if users_list:
URL = server['url'] + API_PATH
selected_server = server
break
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.edit_user_markup(value))
# Configs User Callback
elif key == "user_config":
if server_mode == "All":
servers = USERS_DB.select_servers()
if servers:
for server in servers:
users_list = api.find(server['url'] + API_PATH, value)
if users_list:
URL = server['url'] + API_PATH
selected_server = server
break
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.sub_url_user_list_markup(value))
# ----------------------------------- Edit User Area Callbacks -----------------------------------
# Edit User - Update Message Callback
elif key == "user_edit_update":
usr = utils.user_info(URL, value)
if not usr:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
msg = templates.user_info_template(usr, selected_server, MESSAGES['EDITED_USER_INFO'])
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.edit_user_markup(value))
# Edit User - Edit Usage Callback
elif key == "user_edit_usage":
bot.send_message(call.message.chat.id, MESSAGES['ENTER_NEW_USAGE_LIMIT'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, edit_user_usage, value)
# Edit User - Reset Usage Callback
elif key == "user_edit_reset_usage":
status = api.update(URL, uuid=value, current_usage_GB=0)
if not status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(call.message.chat.id, MESSAGES['RESET_USAGE'],
reply_markup=markups.main_menu_keyboard_markup())
# Edit User - Edit Days Callback
elif key == "user_edit_days":
bot.send_message(call.message.chat.id, MESSAGES['ENTER_NEW_DAYS'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, edit_user_days, value)
# Edit User - Reset Days Callback
elif key == "user_edit_reset_days":
# status = ADMIN_DB.reset_package_days(uuid=value)
last_reset_time = datetime.datetime.now().strftime("%Y-%m-%d")
status = api.update(URL, uuid=value, start_date=last_reset_time)
# api.insert()
if not status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(call.message.chat.id, MESSAGES['RESET_DAYS'], reply_markup=markups.main_menu_keyboard_markup())
# Edit User - Edit Comment Callback
elif key == "user_edit_comment":
bot.send_message(call.message.chat.id, MESSAGES['ENTER_NEW_COMMENT'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, edit_user_comment, value)
# Edit User - Edit Name Callback
elif key == "user_edit_name":
bot.send_message(call.message.chat.id, MESSAGES['ENTER_NEW_NAME'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, edit_user_name, value)
# ----------------------------------- Configs User Info Area Callbacks -----------------------------------
# User Configs - DIR Configs Callback
elif key == "conf_dir":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
configs = utils.sub_parse(sub['sub_link'])
if not configs:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.sub_user_list_markup(value,configs))
# User Configs - VLESS Configs Callback
elif key == "conf_dir_vless":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
configs = utils.sub_parse(sub['sub_link'])
if not configs:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
if not configs['vless']:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
msgs = templates.configs_template(configs['vless'])
for message in msgs:
if message:
bot.send_message(call.message.chat.id, f"{message}",
reply_markup=markups.main_menu_keyboard_markup())
# User Configs - VMess Configs Callback
elif key == "conf_dir_vmess":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
configs = utils.sub_parse(sub['sub_link'])
if not configs:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
if not configs['vmess']:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
msgs = templates.configs_template(configs['vmess'])
for message in msgs:
if message:
bot.send_message(call.message.chat.id, f"{message}",
reply_markup=markups.main_menu_keyboard_markup())
# User Configs - Trojan Configs Callback
elif key == "conf_dir_trojan":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
configs = utils.sub_parse(sub['sub_link'])
if not configs:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
if not configs['trojan']:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
msgs = templates.configs_template(configs['trojan'])
for message in msgs:
if message:
bot.send_message(call.message.chat.id, f"{message}",
reply_markup=markups.main_menu_keyboard_markup())
# User Configs - Main Menu
elif key == 'configs_list':
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.sub_url_user_list_markup(value))
# User Configs - Subscription Configs Callback
elif key == "conf_sub_url":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['sub_link'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_SUB']}\n{sub['sub_link']}",
reply_markup=markups.main_menu_keyboard_markup()
)
# User Configs - Base64 Subscription Configs Callback
elif key == "conf_sub_url_b64":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['sub_link_b64'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_SUB_B64']}\n{sub['sub_link_b64']}",
reply_markup=markups.main_menu_keyboard_markup()
)
# User Configs - Subscription Configs For Clash Callback
elif key == "conf_clash":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['clash_configs'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_CLASH']}\n{sub['clash_configs']}",
reply_markup=markups.main_menu_keyboard_markup()
)
# User Configs - Subscription Configs For Hiddify Callback
elif key == "conf_hiddify":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['hiddify_configs'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_HIDDIFY']}\n{sub['hiddify_configs']}",
reply_markup=markups.main_menu_keyboard_markup()
)
elif key == "conf_sub_auto":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['sub_link_auto'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_SUB_AUTO']}\n{sub['sub_link_auto']}",
reply_markup=markups.main_menu_keyboard_markup()
)
elif key == "conf_sub_sing_box":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['sing_box'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_SING_BOX']}\n{sub['sing_box']}",
reply_markup=markups.main_menu_keyboard_markup()
)
elif key == "conf_sub_full_sing_box":
sub = utils.sub_links(value, URL)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['sing_box_full'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_FULL_SING_BOX']}\n{sub['sing_box_full']}",
reply_markup=markups.main_menu_keyboard_markup()
)
else:
bot.answer_callback_query(call.id, MESSAGES['ERROR_INVALID_COMMAND'])
# ----------------------------------- Search User Area Callbacks -----------------------------------
# Search User - Name Callback
if key == "search_name":
bot.send_message(call.message.chat.id, MESSAGES['SEARCH_USER_NAME'],
reply_markup=markups.while_edit_user_markup())
if value == "None":
search_mode = "All_server_name"
bot.register_next_step_handler(call.message, all_server_search_user_name)
else:
search_mode = "Single_name"
bot.register_next_step_handler(call.message, search_user_name, value)
# Search User - UUID Callback
elif key == "search_uuid":
bot.send_message(call.message.chat.id, MESSAGES['SEARCH_USER_UUID'],
reply_markup=markups.while_edit_user_markup())
if value == "None":
bot.register_next_step_handler(call.message, all_server_search_user_uuid)
else:
bot.register_next_step_handler(call.message, search_user_uuid, value)
# Search User - Config Callback
elif key == "search_config":
bot.send_message(call.message.chat.id, MESSAGES['SEARCH_USER_CONFIG'],
reply_markup=markups.while_edit_user_markup())
if value == "None":
bot.register_next_step_handler(call.message, all_server_search_user_config)
else:
bot.register_next_step_handler(call.message, search_user_config, value)
# Search User - Expired Callback
elif key == "search_expired":
users_list = []
if value == "None":
search_mode = "All_server_expired"
servers = USERS_DB.select_servers()
if servers:
for server in servers:
server_url = server['url'] + API_PATH
users = api.select(server_url)
users = utils.expired_users_list(users)
users_list.extend(users)
else:
search_mode = "Single_expired"
users_list = api.select(URL)
users_list = utils.expired_users_list(users_list)
if not users_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
msg = templates.users_list_template(users_list, MESSAGES['EXPIRED_USERS_LIST'])
bot.send_message(call.message.chat.id, msg, reply_markup=markups.users_list_markup(value, users_list))
# ----------------------------------- Server Management Callbacks -----------------------------------
elif key == "server_selected":
server_mode = "Single"
server = USERS_DB.find_server(id=int(value))
if not server:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_SERVER_NOT_FOUND'])
return
server = server[0]
URL = server['url'] + API_PATH
selected_server = server
plans = USERS_DB.select_plans()
msg = templates.server_info_template(server,plans)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.server_selected_markup(value))
# Server Management - Add Server Callback
elif key == "add_server":
bot.send_message(call.message.chat.id, MESSAGES['ADD_SERVER'],
reply_markup=markups.while_edit_user_markup())
bot.send_message(call.message.chat.id, MESSAGES['ADD_SERVER_TITLE'])
bot.register_next_step_handler(call.message, add_server_title)
# Server Management - Delete Server Callback
elif key == "delete_server":
bot.edit_message_text(MESSAGES['DELETE_SERVER_QUESTION'], call.message.chat.id, call.message.message_id,
reply_markup=markups.server_delete_markup(value))
# Server Management - Edit Server Callback
elif key == "edit_server":
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.server_edit_markup(value))
# Server Management - Edit Title Server Callback
elif key == "server_edit_title":
bot.send_message(call.message.chat.id, MESSAGES['ADD_SERVER_TITLE'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, edit_server_title, value)
# Server Management - Edit User Limit Server Callback
elif key == "server_edit_user_limit":
bot.send_message(call.message.chat.id, MESSAGES['ADD_SERVER_USER_LIMIT'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, edit_server_user_limit, value)
# Server Management - Edit Url Server Callback
elif key == "server_edit_url":
bot.send_message(call.message.chat.id, MESSAGES['ADD_SERVER_URL'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, edit_server_url, value)
# Server Management - Confirm Delete Server Callback
elif key == "confirm_delete_server":
server_id = int(value)
#status = USERS_DB.edit_server(value, status=0)
status = USERS_DB.delete_server(id=server_id)
if not status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
USERS_DB.delete_plan(server_id=server_id)
USERS_DB.delete_order_subscription(server_id=server_id)
USERS_DB.delete_non_order_subscription(server_id=server_id)
servers = USERS_DB.select_servers()
bot.edit_message_text(KEY_MARKUP['SERVERS_MANAGEMENT'], call.message.chat.id, call.message.message_id,
reply_markup=markups.servers_management_markup(servers))
bot.send_message(call.message.chat.id, MESSAGES['SUCCESS_REMOVED_SERVER'], reply_markup=markups.main_menu_keyboard_markup())
# Server Management - List of Plans for Server Callback
elif key == "server_list_of_plans":
plans_list = []
plans = USERS_DB.select_plans()
if plans:
for plan in plans:
if plan['status']:
if plan['server_id'] == int(value):
plans_list.append(plan)
plans_markup = markups.plans_list_markup(plans_list,value)
bot.edit_message_text({MESSAGES['USERS_BOT_PLANS_LIST']}, call.message.chat.id, call.message.message_id,
reply_markup=plans_markup)
elif key == "server_list_of_users":
users_list = api.select(URL)
search_mode = "Single"
if not users_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
msg = templates.users_list_template(users_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.users_list_markup(value, users_list))
elif key == "server_add_user":
global add_user_data
bot.send_message(call.message.chat.id, MESSAGES['ADD_USER_NAME'], reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, add_user_name, value)
elif key == "server_search_user":
bot.edit_message_text(MESSAGES['SEARCH_USER'],call.message.chat.id, call.message.message_id,
reply_markup=markups.search_user_markup(server_id=value))
# ----------------------------------- Users Bot Management Callbacks -----------------------------------
elif key == "users_bot_management_menu":
bot.edit_message_text(KEY_MARKUP['USERS_BOT_MANAGEMENT'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_management_markup())
elif key == "bot_users_list_management":
bot.edit_message_text(KEY_MARKUP['BOT_USERS_MANAGEMENT'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_users_management_markup())
elif key == "bot_users_list":
list_mode = "Bot_Users"
users_list = USERS_DB.select_users()
wallets_list = USERS_DB.select_wallet()
orders_list = USERS_DB.select_orders()
if not users_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
users_list.sort(key = operator.itemgetter('created_at'), reverse=True)
msg = templates.bot_users_list_template(users_list, wallets_list, orders_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_users_list_markup(users_list))
users_list.sort(key = operator.itemgetter('created_at'), reverse=True)
elif key == "search_users_bot":
bot.edit_message_text(MESSAGES['SEARCH_USER'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_users_search_method_markup())
elif key == "bot_users_search_name":
list_mode = "Bot_Users"
bot.send_message(call.message.chat.id, MESSAGES['SEARCH_USER_NAME'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, search_bot_user_name)
elif key == "bot_users_search_telegram_id":
bot.send_message(call.message.chat.id, MESSAGES['SEARCH_USER_TELEGRAM_ID'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, search_bot_user_telegram_id)
elif key == "bot_user_info":
selected_telegram_id = value
users = USERS_DB.find_user(telegram_id=int(value))
if not users:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
user = users[0]
orders = USERS_DB.find_order(telegram_id=user['telegram_id'])
paymets = USERS_DB.find_payment(telegram_id=user['telegram_id'])
wallet = None
wallets = USERS_DB.find_wallet(telegram_id=user['telegram_id'])
if wallets:
wallet = wallets[0]
non_order_subs = utils.non_order_user_info(user['telegram_id'])
order_subs = utils.order_user_info(user['telegram_id'])
plans_list = USERS_DB.select_plans()
msg = templates.bot_users_info_template(user, orders, paymets, wallet, non_order_subs, order_subs, plans_list)
bot.send_message(call.message.chat.id, msg, reply_markup=markups.bot_user_info_markup(value))
elif key == "bot_user_next":
if list_mode == "Bot_Users":
users_list = USERS_DB.select_users()
elif list_mode == "Bot_Users_Search_Name":
users_list = USERS_DB.find_user(full_name=searched_name)
elif list_mode == "User_Refferals":
users_list = USERS_DB.find_user(telegram_id=int(selected_telegram_id))
if not users_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
users_list.sort(key = operator.itemgetter('created_at'), reverse=True)
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_users_list_markup(users_list, int(value)))
elif key == "bot_user_item_info":
if item_mode == "Order":
orders = USERS_DB.find_order(id=int(value))
if not orders:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
order = orders[0]
plans = USERS_DB.find_plan(id=order['plan_id'])
if not plans:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
plan = plans[0]
#subs =
users = USERS_DB.find_user(telegram_id=order['telegram_id'])
if not users:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
user = users[0]
servers = USERS_DB.find_server(id=plan['server_id'])
if not servers:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
server = servers[0]
msg = templates.bot_orders_info_template(order, plan, user, server)
bot.send_message(call.message.chat.id, msg)
elif item_mode == "Payment":
payments = USERS_DB.find_payment(id=int(value))
if not payments:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
payment = payments[0]
user_data = USERS_DB.find_user(telegram_id=payment['telegram_id'])
if not user_data:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
user_data = user_data[0]
msg = templates.bot_payment_info_template(payment,user_data)
photo_path = os.path.join(os.getcwd(), 'UserBot', 'Receiptions', payment['payment_image'])
if payment['approved'] == None:
bot.send_photo(call.message.chat.id, photo=open(photo_path, 'rb'),
caption=msg, reply_markup=markups.confirm_payment_by_admin(payment['id']))
else:
bot.send_photo(call.message.chat.id, photo=open(photo_path, 'rb'),
caption=msg, reply_markup=markups.change_status_payment_by_admin(payment['id']))
elif item_mode == "Gift":
gift = USERS_DB.find_user_plans(id=int(value))
elif key == "bot_user_item_next":
if list_mode == "User_Orders":
item_list = USERS_DB.find_order(telegram_id=int(selected_telegram_id))
elif list_mode == "User_Payments":
item_list = USERS_DB.find_payment(telegram_id=int(selected_telegram_id))
elif list_mode == "User_Gifts":
item_list = USERS_DB.find_user_plans(telegram_id=int(selected_telegram_id))
elif list_mode == "Orders":
item_list = USERS_DB.select_orders()
if list_mode == "Approved_Payments":
payments_list = USERS_DB.select_payments()
item_list = [payment for payment in payments_list if payment['approved'] == 1]
elif list_mode == "Non_Approved_Payments":
payments_list = USERS_DB.select_payments()
item_list = [payment for payment in payments_list if payment['approved'] == 0]
elif list_mode == "Pending_Payments":
payments_list = USERS_DB.select_payments()
item_list = [payment for payment in payments_list if payment['approved'] == None]
elif list_mode == "Card_Payments":
payments_list = USERS_DB.select_payments()
item_list = [payment for payment in payments_list if payment['payment_method'] == "Card"]
elif list_mode == "Digital_Payments":
payments_list = USERS_DB.select_payments()
item_list = [payment for payment in payments_list if payment['payment_method'] == "Digital"]
if not item_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
if not list_mode == "User_Gifts":
item_list.sort(key = operator.itemgetter('created_at'), reverse=True)
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_user_item_list_markup(item_list, int(value)))
elif key == "bot_users_sub_user_list":
server_mode = "All"
subs = utils.non_order_user_info(int(value))
order_subs = utils.order_user_info(int(value))
if order_subs:
subs.extend(order_subs)
if not subs:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_SUB_NOT_FOUND'])
return
msg = templates.users_list_template(subs)
bot.send_message(call.message.chat.id, msg, reply_markup=markups.users_list_markup("None", subs))
elif key == "users_bot_orders_user_list":
list_mode = "User_Orders"
item_mode = "Order"
orders_list = USERS_DB.find_order(telegram_id=int(value))
plans_list = USERS_DB.select_plans()
if not orders_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_ORDER_NOT_FOUND'])
return
orders_list.sort(key = operator.itemgetter('created_at'), reverse=True)
msg = templates.bot_orders_list_template(orders_list, plans_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_user_item_list_markup(orders_list))
elif key == "users_bot_payments_user_list":
list_mode = "User_Payments"
item_mode = "Payment"
paymets = USERS_DB.find_payment(telegram_id=int(value))
if not paymets:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
paymets.sort(key = operator.itemgetter('created_at'), reverse=True)
msg = templates.bot_payments_list_template(paymets)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_user_item_list_markup(paymets))
elif key == "users_bot_wallet_edit_balance":
bot.send_message(call.message.chat.id, MESSAGES['EDIT_WALLET_BALANCE'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, edit_wallet_balance, value)
elif key == "users_bot_reset_test":
users = USERS_DB.find_user(telegram_id=int(value))
if not users:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
user = users[0]
if user['test_subscription'] == 0:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_HAVE_TEST_SUB'])
return
status = USERS_DB.edit_user(telegram_id=int(value), test_subscription=0)
if not status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
bot.send_message(call.message.chat.id, MESSAGES['SUCCESS_RESET_TEST_SUB'])
elif key == "users_bot_ban_user":
users = USERS_DB.find_user(telegram_id=int(value))
if not users:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
user = users[0]
if user['banned'] == 0:
status = USERS_DB.edit_user(telegram_id=int(value), banned=1)
if not status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
bot.send_message(call.message.chat.id, MESSAGES['SUCCESS_BAN_USER'])
return
if user['banned'] == 1:
status = USERS_DB.edit_user(telegram_id=int(value), banned=0)
if not status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
bot.send_message(call.message.chat.id, MESSAGES['SUCCESS_UNBAN_USER'])
return
elif key == "users_bot_gifts_user_list":
list_mode = "User_Gifts"
item_mode = "Gift"
gift = USERS_DB.find_user_plans(telegram_id=int(value))
if not gift:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_GIFT_NOT_FOUND'])
return
# msg = templates.bot_gift_list_template(paymets)
# bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
# reply_markup=markups.bot_user_item_list_markup(gift))
elif key == "users_bot_referred_user_list":
list_mode = "User_Refferals"
users = USERS_DB.find_user(telegram_id=int(value))
if not users:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
user = users[0]
#referred_user =
elif key == "users_bot_orders_list_management":
bot.edit_message_text(KEY_MARKUP['ORDERS_MANAGEMENT'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_orders_management_markup())
elif key == "users_bot_orders_list":
list_mode = "Orders"
item_mode = "Order"
orders_list = USERS_DB.select_orders()
plans_list = USERS_DB.select_plans()
if not orders_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_ORDER_NOT_FOUND'])
return
orders_list.sort(key = operator.itemgetter('created_at'), reverse=True)
msg = templates.bot_orders_list_template(orders_list, plans_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_user_item_list_markup(orders_list))
elif key == "search_orders":
bot.send_message(call.message.chat.id, MESSAGES['ORDER_NUMBER_REQUEST'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, search_bot_user_order)
elif key == "users_bot_payments_list_management":
bot.edit_message_text(KEY_MARKUP['PAYMENT_MANAGEMENT'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_payments_management_markup())
elif key == "search_payments":
bot.send_message(call.message.chat.id, MESSAGES['PAYMENT_NUMBER_REQUEST'],
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, search_bot_user_payment)
elif key == "bot_users_approved_payments_list":
list_mode = "Approved_Payments"
item_mode = "Payment"
payments_list = USERS_DB.select_payments()
if not payments_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
approved_payments_list = [payment for payment in payments_list if payment['approved'] == 1]
if not approved_payments_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
approved_payments_list.sort(key = operator.itemgetter('created_at'), reverse=True)
msg = templates.bot_payments_list_template(approved_payments_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_user_item_list_markup(approved_payments_list))
elif key == "users_bot_non_approved_payments_list":
list_mode = "Non_Approved_Payments"
item_mode = "Payment"
payments_list = USERS_DB.select_payments()
if not payments_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
non_approved_payments_list = [payment for payment in payments_list if payment['approved'] == 0]
if not non_approved_payments_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
non_approved_payments_list.sort(key = operator.itemgetter('created_at'), reverse=True)
msg = templates.bot_payments_list_template(non_approved_payments_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_user_item_list_markup(non_approved_payments_list))
elif key == "users_bot_pending_payments_list":
list_mode = "Pending_Payments"
item_mode = "Payment"
payments_list = USERS_DB.select_payments()
if not payments_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
pending_payments_list = [payment for payment in payments_list if payment['approved'] == None]
if not pending_payments_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
pending_payments_list.sort(key = operator.itemgetter('created_at'), reverse=True)
msg = templates.bot_payments_list_template(pending_payments_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_user_item_list_markup(pending_payments_list))
elif key == "users_bot_card_payments_list":
list_mode = "Card_Payments"
item_mode = "Payment"
payments_list = USERS_DB.select_payments()
if not payments_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
card_payments_list = [payment for payment in payments_list if payment['payment_method'] == "Card"]
if not card_payments_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
card_payments_list.sort(key = operator.itemgetter('created_at'), reverse=True)
msg = templates.bot_payments_list_template(card_payments_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_user_item_list_markup(card_payments_list))
elif key == "users_bot_digital_payments_list":
list_mode = "Digital_Payments"
item_mode = "Payment"
payments_list = USERS_DB.select_payments()
if not payments_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
digital_payments_list = [payment for payment in payments_list if payment['payment_method'] == "Digital"]
if not digital_payments_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
digital_payments_list.sort(key = operator.itemgetter('created_at'), reverse=True)
msg = templates.bot_payments_list_template(digital_payments_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_user_item_list_markup(digital_payments_list))
# Plan Management - Add Plan Callback
elif key == "users_bot_add_plan":
bot.send_message(call.message.chat.id, MESSAGES['USERS_BOT_ADD_PLAN'],
reply_markup=markups.while_edit_user_markup())
bot.send_message(call.message.chat.id, MESSAGES['USERS_BOT_ADD_PLAN_USAGE'])
add_plan_data['server_id'] = int(value)
bot.register_next_step_handler(call.message, users_bot_add_plan_usage)
# Plan Management - Info Plan Callback
elif key == "info_plan_selected":
plans= USERS_DB.find_plan(id=value)
if not plans:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
orders = USERS_DB.find_order(plan_id=value)
plan = plans[0]
msg = templates.plan_info_template(plan, orders)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.plan_info_selected_markup(plan['server_id']))
# Plan Management - Edit Plan Callback
elif key == "users_bot_del_plan":
status = USERS_DB.edit_plan(value, status=0)
if status:
plans= USERS_DB.find_plan(id=value)
if not plans:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
del_plan = plans[0]
server_id = del_plan['server_id']
plans_list = []
plans = USERS_DB.select_plans()
if plans:
for plan in plans:
if plan['status']:
if plan['server_id'] == server_id:
plans_list.append(plan)
plans_markup = markups.plans_list_markup(plans_list, server_id,delete_mode = True)
bot.edit_message_text({MESSAGES['USERS_BOT_SELECT_PLAN_TO_DELETE']}, call.message.chat.id, call.message.message_id,
reply_markup=plans_markup)
else:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
# Plan Management - List Plans Callback
elif key == "users_bot_list_plans":
plans_list = []
plans = USERS_DB.select_plans()
if plans:
for plan in plans:
if plan['status']:
if plan['server_id'] == int(value):
plans_list.append(plan)
plans_markup = markups.plans_list_markup(plans_list,value,delete_mode = True)
bot.edit_message_text({MESSAGES['USERS_BOT_SELECT_PLAN_TO_DELETE']}, call.message.chat.id, call.message.message_id,
reply_markup=plans_markup)
# Owner Info - Edit Owner Info Callback
elif key == "users_bot_owner_info":
owner_info = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
templates.owner_info_template(owner_info['support_username'], owner_info['card_number'],
owner_info['card_holder']),
reply_markup=markups.users_bot_edit_owner_info_markup())
# Owner Info - Edit Owner Username Callback
elif key == "users_bot_owner_info_edit_username":
bot.send_message(call.message.chat.id, f"{MESSAGES['USERS_BOT_OWNER_INFO_ADD_USERNAME']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_edit_owner_info_username)
# Owner Info - Edit Owner Card Number Callback
elif key == "users_bot_owner_info_edit_card_number":
bot.send_message(call.message.chat.id, f"{MESSAGES['USERS_BOT_OWNER_INFO_ADD_CARD_NUMBER']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_edit_owner_info_card_number)
# Owner Info - Edit Owner Cardholder Callback
elif key == "users_bot_owner_info_edit_card_name":
bot.send_message(call.message.chat.id, f"{MESSAGES['USERS_BOT_OWNER_INFO_ADD_CARD_NAME']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_edit_owner_info_card_name)
# Send Message - Send Message To All Users Callback
elif key == "users_bot_send_msg_users":
bot.send_message(call.message.chat.id, f"{MESSAGES['USERS_BOT_SEND_MSG_USERS']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_send_msg_users)
# User Bot Settings - Main Settings Callback
elif key == "users_bot_settings":
settings = USERS_DB.select_bool_config()
if not settings:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
bot.edit_message_text(MESSAGES['USERS_BOT_SETTINGS'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_management_settings_markup(settings))
# User Bot Settings - Set Hyperlink Status Callback
elif key == "users_bot_settings_hyperlink":
if value == "1":
edit_config = USERS_DB.edit_bool_config("visible_hiddify_hyperlink", value=False)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif value == "0":
edit_config = USERS_DB.edit_bool_config("visible_hiddify_hyperlink", value=True)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message, markups.users_bot_management_settings_markup(settings))
# User Bot Settings - Set three random letters for define price
elif key == "users_bot_settings_three_rand_price":
if value == "1":
edit_config = USERS_DB.edit_bool_config("three_random_num_price", value=False)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif value == "0":
edit_config = USERS_DB.edit_bool_config("three_random_num_price", value=True)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message, markups.users_bot_management_settings_markup(settings))
elif key == "users_bot_settings_panel_auto_backup":
if value == "1":
edit_config = USERS_DB.edit_bool_config("panel_auto_backup", value=False)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif value == "0":
edit_config = USERS_DB.edit_bool_config("panel_auto_backup", value=True)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message, markups.users_bot_management_settings_markup(settings))
elif key == "users_bot_settings_bot_auto_backup":
if value == "1":
edit_config = USERS_DB.edit_bool_config("bot_auto_backup", value=False)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif value == "0":
edit_config = USERS_DB.edit_bool_config("bot_auto_backup", value=True)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message, markups.users_bot_management_settings_markup(settings))
elif key == "users_bot_settings_min_depo":
settings = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {utils.rial_to_toman(settings['min_deposit_amount'])}\n{MESSAGES['USERS_BOT_SETTING_MIN_DEPO']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_min_depo)
# elif key == "users_bot_settings_panel_v8":
# if value == "1":
# edit_config = USERS_DB.edit_bool_config("hiddify_v8_feature", value=False)
# if not edit_config:
# bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
# return
# elif value == "0":
# edit_config = USERS_DB.edit_bool_config("hiddify_v8_feature", value=True)
# if not edit_config:
# bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
# return
# users_bot_settings_update_message(call.message)
elif key == "users_bot_settings_channel_id":
settings = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {settings['channel_id']}\n{MESSAGES['USERS_BOT_SETTING_CHANNEL_ID']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_channel_id)
elif key == "users_bot_settings_force_join":
settings = utils.all_configs_settings()
if not settings['channel_id']:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CHANNEL_ID_NOT_SET'])
return
if value == "1":
edit_config = USERS_DB.edit_bool_config("force_join_channel", value=False)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif value == "0":
edit_config = USERS_DB.edit_bool_config("force_join_channel", value=True)
bot.send_message(call.message.chat.id, MESSAGES['USERS_BOT_SETTING_FORCE_JOIN_HELP'])
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message, markups.users_bot_management_settings_markup(settings))
elif key == "users_bot_settings_visible_sub_menu":
settings = utils.all_configs_settings()
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_management_settings_visible_sub_markup(settings))
elif key == "users_bot_settings_visible_sub":
settings = utils.all_configs_settings()
row_key = value
current_status = settings[row_key]
if current_status == 1:
edit_config = USERS_DB.edit_bool_config(row_key, value=False)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif current_status == 0:
edit_config = USERS_DB.edit_bool_config(row_key, value=True)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message,
markups.users_bot_management_settings_visible_sub_markup(settings))
elif key == "users_bot_settings_set_welcome_msg":
settings = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {settings['msg_user_start']}\n{MESSAGES['USERS_BOT_SETTING_WELCOME_MSG']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_welcome_msg)
elif key == "users_bot_settings_faq_management":
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_management_settings_faq_markup())
elif key == "users_bot_settings_set_faq_msg":
settings = utils.all_configs_settings()
faq_text = settings['msg_faq']
msg = call.message
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {faq_text}\n{MESSAGES['USERS_BOT_SETTING_FAQ_MSG']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_set_faq_msg, msg)
elif key == "users_bot_settings_hide_faq":
settings = utils.all_configs_settings()
status = USERS_DB.edit_str_config("msg_faq", value=None)
if not status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_management_settings_faq_markup())
elif key == "users_bot_settings_test_sub_menu":
settings = utils.all_configs_settings()
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_management_settings_test_sub_markup(settings))
elif key == "users_bot_settings_test_sub":
settings = utils.all_configs_settings()
row_key = value
current_status = settings['test_subscription']
if current_status == 1:
edit_config = USERS_DB.edit_bool_config(row_key, value=False)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif current_status == 0:
edit_config = USERS_DB.edit_bool_config(row_key, value=True)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message, markups.users_bot_management_settings_test_sub_markup(settings))
elif key == "users_bot_settings_test_sub_size":
settings = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {settings['test_sub_size_gb']} {MESSAGES['GB']}\n{MESSAGES['USERS_BOT_SETTINGS_TEST_SUB_USAGE']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_test_sub_size)
elif key == "users_bot_settings_test_sub_days":
settings = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {settings['test_sub_days']} {MESSAGES['DAY']}\n{MESSAGES['USERS_BOT_SETTINGS_TEST_SUB_DAYS']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_test_sub_days)
# User Bot Settings - Reminder Notification Callback
elif key == "users_bot_settings_notif_reminder_menu":
settings = utils.all_configs_settings()
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_management_settings_notif_reminder_markup(
settings))
elif key == "users_bot_settings_notif_reminder":
settings = utils.all_configs_settings()
row_key = value
current_status = settings['reminder_notification']
if current_status == 1:
edit_config = USERS_DB.edit_bool_config(row_key, value=False)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif current_status == 0:
edit_config = USERS_DB.edit_bool_config(row_key, value=True)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message,
markups.users_bot_management_settings_notif_reminder_markup(settings))
elif key == "users_bot_settings_notif_reminder_usage":
settings = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {settings['reminder_notification_usage']} {MESSAGES['GB']}\n{MESSAGES['USERS_BOT_SETTINGS_NOTIF_REMINDER_USAGE']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_notif_reminder_usage)
elif key == "users_bot_settings_notif_reminder_days":
settings = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {settings['reminder_notification_days']} {MESSAGES['DAY']}\n{MESSAGES['USERS_BOT_SETTINGS_NOTIF_REMINDER_DAYS']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_notif_reminder_days)
elif key == "users_bot_settings_panel_manual_menu":
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_management_settings_panel_manual_markup())
elif key == "users_bot_settings_panel_manual":
settings = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {settings[value]}\n{MESSAGES['USERS_BOT_SETTINGS_PANEL_MANUAL']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_panel_manual, value)
elif key == "users_bot_settings_backup_bot":
backup_file = utils.backup_json_bot()
if not backup_file:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
bot.send_document(call.message.chat.id, open(backup_file, 'rb'),caption=MESSAGES['USERS_BOT_SETTINGS_BACKUP_BOT'])
elif key == "users_bot_settings_restore_bot":
bot.send_message(call.message.chat.id, MESSAGES['USERS_BOT_SETTINGS_RESTORE_BOT'], reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_restore_bot)
elif key == "users_bot_settings_buy_sub_status":
if value == "1":
edit_config = USERS_DB.edit_bool_config("buy_subscription_status", value=False)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif value == "0":
edit_config = USERS_DB.edit_bool_config("buy_subscription_status", value=True)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message, markups.users_bot_management_settings_markup(settings))
elif key == "users_bot_settings_renewal_sub_status":
if value == "1":
edit_config = USERS_DB.edit_bool_config("renewal_subscription_status", value=False)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif value == "0":
edit_config = USERS_DB.edit_bool_config("renewal_subscription_status", value=True)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message, markups.users_bot_management_settings_markup(settings))
elif key == "users_bot_settings_renewal_method_menu":
settings = utils.all_configs_settings()
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_management_settings_renewal_method_markup(settings))
elif key == "users_bot_settings_renewal_method":
if value == "1":
edit_config = USERS_DB.edit_int_config("renewal_method", value=1)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif value == "2":
edit_config = USERS_DB.edit_int_config("renewal_method", value=2)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
elif value == "3":
edit_config = USERS_DB.edit_int_config("renewal_method", value=3)
if not edit_config:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
settings = utils.all_configs_settings()
users_bot_settings_update_message(call.message, markups.users_bot_management_settings_renewal_method_markup(settings))
elif key == "users_bot_settings_renewal_method_advanced_days":
settings = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {settings['advanced_renewal_days']} {MESSAGES['DAY']}\n{MESSAGES['USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_DAYS']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_renewal_method_advanced_days)
elif key == "users_bot_settings_renewal_method_advanced_usage":
settings = utils.all_configs_settings()
bot.send_message(call.message.chat.id,
f"{MESSAGES['CURRENT_VALUE']}: {settings['advanced_renewal_usage']} {MESSAGES['GB']}\n{MESSAGES['USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_USAGE']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_settings_renewal_method_advanced_usage)
# User Bot Settings - Order Status Callback
# elif key == "users_bot_orders_status":
# bot.send_message(call.message.chat.id, f"{MESSAGES['USERS_BOT_ORDER_NUMBER_REQUEST']}")
# bot.register_next_step_handler(call.message, users_bot_order_status)
elif key == "users_bot_sub_status":
bot.send_message(call.message.chat.id, f"{MESSAGES['USERS_BOT_SUB_ID_REQUEST']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_sub_status)
elif key == "users_bot_settings_reset_free_test_limit_question":
bot.edit_message_text(MESSAGES['USERS_BOT_SETTINGS_RESET_FREE_TEST_LIMIT_QUESTION'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_management_settings_reset_free_test_markup())
elif key == "users_bot_management_settings_reset_free_test_confirm":
users_list = USERS_DB.select_users()
free_test_bot_users = [user for user in users_list if user['test_subscription']]
if free_test_bot_users:
for user in free_test_bot_users:
status = USERS_DB.edit_user(telegram_id=user['telegram_id'],test_subscription=False)
if not status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'], reply_markup=markups.main_menu_keyboard_markup())
return
bot.send_message(call.message.chat.id, MESSAGES['SUCCESS_RESET_FREE_TEST'], reply_markup=markups.main_menu_keyboard_markup())
else:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'], reply_markup=markups.main_menu_keyboard_markup())
# ----------------------------------- Payment Callbacks -----------------------------------
# Payment - Confirm Payment Callback
elif key == "confirm_payment_by_admin":
if not CLIENT_TOKEN:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CLIENT_TOKEN'])
return
payment_id = value
payment_info = USERS_DB.find_payment(id=payment_id)
if not payment_info:
bot.send_message(call.message.chat.id,
f"{MESSAGES['ERROR_PAYMENT_NOT_FOUND']}\n{MESSAGES['ORDER_ID']} {payment_id}")
return
payment_info = payment_info[0]
if payment_info['approved'] == 1:
bot.send_message(call.message.chat.id,
f"{MESSAGES['ERROR_PAYMENT_ALREADY_CONFIRMED']}\n{MESSAGES['ORDER_ID']} {payment_id}")
return
wallet = USERS_DB.find_wallet(telegram_id=payment_info['telegram_id'])
if not wallet:
create_wallet_status = USERS_DB.add_wallet(payment_info['telegram_id'])
if not create_wallet_status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
wallet = USERS_DB.find_wallet(telegram_id=payment_info['telegram_id'])
wallet = wallet[0]
payment_status = USERS_DB.edit_payment(payment_id, approved=True)
if payment_status:
new_balance = int(wallet['balance']) + int(payment_info['payment_amount'])
wallet_status = USERS_DB.edit_wallet(wallet['telegram_id'], balance=new_balance)
if not wallet_status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
bot.delete_message(call.message.chat.id, call.message.message_id)
user_bot.send_message(int(payment_info['telegram_id']),
f"{MESSAGES['WALLET_PAYMENT_CONFIRMED']}\n{MESSAGES['ORDER_ID']} {payment_id}")
bot.send_message(call.message.chat.id,
f"{MESSAGES['PAYMENT_CONFIRMED_ADMIN']}\n{MESSAGES['ORDER_ID']} {payment_id}")
# Payment - Reject Payment Callback
elif key == 'cancel_payment_by_admin':
if not CLIENT_TOKEN:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CLIENT_TOKEN'])
return
payment_id = value
payment_info = USERS_DB.find_payment(id=payment_id)
if not payment_info:
bot.send_message(call.message.chat.id,
f"{MESSAGES['ERROR_PAYMENT_NOT_FOUND']}\n{MESSAGES['ORDER_ID']} {payment_id}")
return
payment_info = payment_info[0]
if payment_info['approved'] == 0:
bot.send_message(call.message.chat.id,
f"{MESSAGES['ERROR_PAYMENT_ALREADY_REJECTED']}\n{MESSAGES['ORDER_ID']} {payment_id}")
return
payment_status = USERS_DB.edit_payment(payment_id, approved=False)
if payment_status:
user_bot.send_message(int(payment_info['telegram_id']),
f"{MESSAGES['PAYMENT_NOT_CONFIRMED']}\n{MESSAGES['ORDER_ID']} {payment_id}")
bot.send_message(call.message.chat.id,
f"{MESSAGES['PAYMENT_NOT_CONFIRMED_ADMIN']}\n{MESSAGES['ORDER_ID']}: {payment_id}")
bot.delete_message(call.message.chat.id, call.message.message_id)
else:
bot.send_message(call.message.chat.id, f"{MESSAGES['ERROR_UNKNOWN']}\n{MESSAGES['ORDER_ID']}: {payment_id}")
# Payment - Change status Payment Callback
elif key == "change_status_payment_by_admin":
payments = USERS_DB.find_payment(id=int(value))
if not payments:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
payment = payments[0]
user_data = USERS_DB.find_user(telegram_id=payment['telegram_id'])
if not user_data:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
user_data = user_data[0]
msg = templates.bot_payment_info_template(payment,user_data, footer=MESSAGES['CHANGE_STATUS_PAYMENT_CONFIRM_REQUEST'])
bot.edit_message_caption(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.confirm_change_status_payment_by_admin(value))
# Payment - Confirm change status Payment Callback
elif key == "confirm_change_status_payment_by_admin":
if not CLIENT_TOKEN:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CLIENT_TOKEN'])
return
payment_id = int(value)
payments = USERS_DB.find_payment(id=payment_id)
if not payments:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
payment = payments[0]
if payment['approved']:
payment_status = USERS_DB.edit_payment(payment_id, approved=False)
if payment_status:
wallet = USERS_DB.find_wallet(telegram_id=payment['telegram_id'])
if not wallet:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
wallet = wallet[0]
new_balance = int(wallet['balance']) - int(payment['payment_amount'])
wallet_status = USERS_DB.edit_wallet(wallet['telegram_id'], balance=new_balance)
if not wallet_status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
payments = USERS_DB.find_payment(id=payment_id)
if not payments:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
payment = payments[0]
user_data = USERS_DB.find_user(telegram_id=payment['telegram_id'])
if not user_data:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
user_data = user_data[0]
msg = templates.bot_payment_info_template(payment,user_data)
bot.edit_message_caption(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.change_status_payment_by_admin(value))
user_bot.send_message(int(payment['telegram_id']),
f"{MESSAGES['PAYMENT_CHANGED_TO_NOT_CONFIRMED']}\n{MESSAGES['ORDER_ID']} {payment_id}")
bot.send_message(call.message.chat.id,
f"{MESSAGES['PAYMENT_CHANGED_TO_NOT_CONFIRMED_ADMIN']}\n{MESSAGES['ORDER_ID']} {payment_id}")
elif payment['approved'] == False:
payment_status = USERS_DB.edit_payment(payment_id, approved=True)
if payment_status:
wallet = USERS_DB.find_wallet(telegram_id=payment['telegram_id'])
if not wallet:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
wallet = wallet[0]
new_balance = int(wallet['balance']) + int(payment['payment_amount'])
wallet_status = USERS_DB.edit_wallet(wallet['telegram_id'], balance=new_balance)
if not wallet_status:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
payments = USERS_DB.find_payment(id=payment_id)
if not payments:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
payment = payments[0]
user_data = USERS_DB.find_user(telegram_id=payment['telegram_id'])
if not user_data:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
user_data = user_data[0]
msg = templates.bot_payment_info_template(payment,user_data)
bot.edit_message_caption(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.change_status_payment_by_admin(value))
user_bot.send_message(int(payment['telegram_id']),
f"{MESSAGES['WALLET_CHANGED_TO_PAYMENT_CONFIRMED']}\n{MESSAGES['ORDER_ID']} {payment_id}")
bot.send_message(call.message.chat.id,
f"{MESSAGES['PAYMENT_CHANGED_TO_CONFIRMED_ADMIN']}\n{MESSAGES['ORDER_ID']} {payment_id}")
elif key == "cancel_change_status_payment_by_admin":
payments = USERS_DB.find_payment(id=int(value))
if not payments:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_PAYMENT_NOT_FOUND'])
return
payment = payments[0]
user_data = USERS_DB.find_user(telegram_id=payment['telegram_id'])
if not user_data:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
user_data = user_data[0]
msg = templates.bot_payment_info_template(payment,user_data)
bot.edit_message_caption(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.change_status_payment_by_admin(value))
# Payment - Send Message Callback
elif key == "send_message_by_admin":
if not CLIENT_TOKEN:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CLIENT_TOKEN'])
return
bot.send_message(call.message.chat.id, f"{MESSAGES['SEND_MESSAGE_TO_USER']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, send_message_to_user, value)
elif key == "users_bot_send_message_by_admin":
if not CLIENT_TOKEN:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CLIENT_TOKEN'])
return
bot.send_message(call.message.chat.id, f"{MESSAGES['SEND_MESSAGE_TO_USER']}",
reply_markup=markups.while_edit_user_markup())
bot.register_next_step_handler(call.message, users_bot_send_message_to_user, value)
# Back to User Panel Callback
elif key == "back_to_user_panel":
usr = utils.user_info(URL, value)
if not usr:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
msg = templates.user_info_template(usr, selected_server)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.user_info_markup(usr['uuid']))
elif key == "back_to_sub_url_user_list":
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=markups.sub_url_user_list_markup(value))
elif key == "back_to_server_management":
servers = USERS_DB.select_servers()
bot.edit_message_text(KEY_MARKUP['SERVERS_MANAGEMENT'], call.message.chat.id, call.message.message_id,
reply_markup=markups.servers_management_markup(servers))
elif key == "back_to_server_list_of_plans":
plans_list = []
plans = USERS_DB.select_plans()
if plans:
for plan in plans:
if plan['status']:
if plan['server_id'] == int(value):
plans_list.append(plan)
plans_markup = markups.plans_list_markup(plans_list,value)
bot.edit_message_text({MESSAGES['USERS_BOT_PLANS_LIST']}, call.message.chat.id, call.message.message_id,
reply_markup=plans_markup)
elif key == "back_to_server_selected":
if search_mode == "Single":
server = USERS_DB.find_server(id=int(value))
if not server:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_SERVER_NOT_FOUND'])
return
server = server[0]
plans = USERS_DB.select_plans()
msg = templates.server_info_template(server,plans)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.server_selected_markup(value))
else:
bot.edit_message_text(MESSAGES['SEARCH_USER'],call.message.chat.id, call.message.message_id,
reply_markup=markups.search_user_markup(server_id=value))
search_mode = "Single"
elif key == "back_to_server_user_list":
users_list = api.select(URL)
if not users_list:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
return
msg = templates.users_list_template(users_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.users_list_markup(value, users_list))
elif key == "back_to_users_bot_users_management":
bot.edit_message_text(KEY_MARKUP['BOT_USERS_MANAGEMENT'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_users_management_markup())
elif key == "back_to_bot_users_or_reffral_management":
if list_mode == "Bot_Users_Search_Name" or "Bot_User":
bot.edit_message_text(KEY_MARKUP['BOT_USERS_MANAGEMENT'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_users_management_markup())
elif list_mode == "User_Refferals":
users = USERS_DB.find_user(telegram_id=int(selected_telegram_id))
if not users:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
user = users[0]
orders = USERS_DB.find_order(telegram_id=user['telegram_id'])
paymets = USERS_DB.find_payment(telegram_id=user['telegram_id'])
wallet = None
wallets = USERS_DB.find_wallet(telegram_id=user['telegram_id'])
if wallets:
wallet = wallets[0]
non_order_subs = utils.non_order_user_info(user['telegram_id'])
order_subs = utils.order_user_info(user['telegram_id'])
plans_list = USERS_DB.select_plans()
msg = templates.bot_users_info_template(user, orders, paymets, wallet, non_order_subs, order_subs, plans_list)
bot.send_message(call.message.chat.id, msg, reply_markup=markups.bot_user_info_markup(value))
elif key == "back_management_item_list":
approved_payments = list_mode == "Approved_Payments"
non_approved_payments = list_mode == "Non_Approved_Payments"
pending_payments = list_mode == "Pending_Payments"
card_payments = list_mode == "Card_Payments"
digital_payments = list_mode == "Digital_Payments"
if list_mode == "Orders":
bot.edit_message_text(KEY_MARKUP['ORDERS_MANAGEMENT'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_orders_management_markup())
elif approved_payments or non_approved_payments or pending_payments or card_payments or digital_payments:
bot.edit_message_text(KEY_MARKUP['PAYMENT_MANAGEMENT'], call.message.chat.id, call.message.message_id,
reply_markup=markups.users_bot_payments_management_markup())
elif list_mode == "User_Payments" or list_mode == "User_Gifts" or list_mode == "User_Orders":
users = USERS_DB.find_user(telegram_id=int(selected_telegram_id))
if not users:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'],
reply_markup=markups.main_menu_keyboard_markup())
return
user = users[0]
orders = USERS_DB.find_order(telegram_id=user['telegram_id'])
paymets = USERS_DB.find_payment(telegram_id=user['telegram_id'])
wallet = None
wallets = USERS_DB.find_wallet(telegram_id=user['telegram_id'])
if wallets:
wallet = wallets[0]
non_order_subs = utils.non_order_user_info(user['telegram_id'])
order_subs = utils.order_user_info(user['telegram_id'])
plans_list = USERS_DB.select_plans()
msg = templates.bot_users_info_template(user, orders, paymets, wallet, non_order_subs, order_subs, plans_list)
bot.edit_message_text(msg, call.message.chat.id, call.message.message_id,
reply_markup=markups.bot_user_info_markup(selected_telegram_id))
elif key == "server_status":
from Utils.serverInfo import get_server_status
msg_wait = bot.send_message(call.message.chat.id, MESSAGES['WAIT'])
server = USERS_DB.find_server(id=int(value))
if not server:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_SERVER_NOT_FOUND'])
return
server = server[0]
server_status_data = get_server_status(server)
if not server_status_data:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
bot.delete_message(call.message.chat.id, msg_wait.message_id)
bot.send_message(call.message.chat.id, server_status_data, reply_markup=markups.main_menu_keyboard_markup())
elif key == "del_msg":
bot.delete_message(call.message.chat.id, call.message.message_id)
# Check Admin Permission
@bot.message_handler(func=lambda message: message.chat.id not in ADMINS_ID)
def not_admin(message: Message):
bot.reply_to(message, MESSAGES['ERROR_NOT_ADMIN'])
# Send Welcome Message Handler
@bot.message_handler(commands=['help', 'start', 'restart'])
def send_welcome(message: Message):
bot.reply_to(message, MESSAGES['WELCOME'], reply_markup=markups.main_menu_keyboard_markup())
bot.send_message(message.chat.id, MESSAGES['REQUEST_JOIN_HIDY'], reply_markup=markups.start_bot_markup())
# Send users list Message Handler
# @bot.message_handler(func=lambda message: message.text == KEY_MARKUP['USERS_LIST'])
# def all_users_list(message: Message):
# # users_list = utils.dict_process(utils.users_to_dict(ADMIN_DB.select_users()))
# users_list = api.select(URL)
# if not users_list:
# bot.send_message(message.chat.id, MESSAGES['ERROR_USER_NOT_FOUND'])
# return
# msg = templates.users_list_template(users_list)
# bot.send_message(message.chat.id, msg, reply_markup=markups.users_list_markup(users_list))
# Add User Message Handler
# @bot.message_handler(func=lambda message: message.text == KEY_MARKUP['ADD_USER'])
# def add_user(message: Message):
# global add_user_data
# bot.send_message(message.chat.id, MESSAGES['ADD_USER_NAME'], reply_markup=markups.while_add_user_markup())
# bot.register_next_step_handler(message, add_user_name)
# Panel Backup Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['SERVER_BACKUP'])
def server_backup(message: Message):
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'])
zip_file_name = utils.full_backup()
if not zip_file_name:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'])
logging.error("Backup failed")
return
if message.chat.id in ADMINS_ID:
bot.send_document(message.chat.id, open(zip_file_name, 'rb'), caption="🤖Backup",disable_notification=True)
else:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'])
bot.delete_message(message.chat.id, msg_wait.message_id)
# Server Status Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['SERVER_STATUS'])
def server_status(message: Message):
servers = USERS_DB.select_servers()
bot.send_message(message.chat.id, KEY_MARKUP['SERVER_STATUS'],
reply_markup=markups.server_status_markup(servers))
# Search User Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['USERS_SEARCH'])
def search_user(message: Message):
global server_mode
server_mode = "All"
bot.send_message(message.chat.id, MESSAGES['SEARCH_USER'],
reply_markup=markups.search_user_markup())
# Users Bot Management Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['USERS_BOT_MANAGEMENT'])
def users_bot_management(message: Message):
if not CLIENT_TOKEN:
bot.send_message(message.chat.id, MESSAGES['ERROR_CLIENT_TOKEN'])
return
bot.send_message(message.chat.id, KEY_MARKUP['USERS_BOT_MANAGEMENT'],
reply_markup=markups.users_bot_management_markup())
# Server Management Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['SERVERS_MANAGEMENT'])
def servers_management(message: Message):
servers = USERS_DB.select_servers()
bot.send_message(message.chat.id, KEY_MARKUP['SERVERS_MANAGEMENT'],
reply_markup=markups.servers_management_markup(servers))
# About Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['ABOUT_BOT'])
def about_bot(message: Message):
bot.send_message(message.chat.id, templates.about_template())
# Debug Handler
@bot.message_handler(commands=['debug'])
def debug(message: Message):
debug_zip = utils.debug_data()
if not debug_zip:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
bot.send_document(message.chat.id, open(debug_zip, 'rb'), caption="👹Debug")
# ----------------------------------- Main -----------------------------------
# Start Bot
def start():
# Bot Start Commands
try:
bot.set_my_commands([
telebot.types.BotCommand("/start", BOT_COMMANDS['START']),
telebot.types.BotCommand("/debug", BOT_COMMANDS['DEBUG']),
])
except telebot.apihelper.ApiTelegramException as e:
if e.result.status_code == 401:
logging.error("Invalid Telegram Bot Token!")
exit(1)
# Welcome to Admin
for admin in ADMINS_ID:
try:
bot.send_message(admin, MESSAGES['WELCOME_TO_ADMIN'])
except Exception as e:
logging.warning(f"Error in send message to admin {admin}: {e}")
bot.enable_save_next_step_handlers()
bot.load_next_step_handlers()
bot.infinity_polling()
================================================
FILE: AdminBot/content.py
================================================
import os
import json
from config import LANG
FOLDER = "Json"
MSG_FILE = "messages.json"
BTN_FILE = "buttons.json"
CMD_FILE = "commands.json"
with open(os.path.join(os.path.dirname(__file__),FOLDER, MSG_FILE), encoding='utf-8') as f:
MESSAGES = json.load(f)
MESSAGES = MESSAGES[LANG]
with open(os.path.join(os.path.dirname(__file__),FOLDER, BTN_FILE), encoding='utf-8') as f:
KEY_MARKUP = json.load(f)
KEY_MARKUP = KEY_MARKUP[LANG]
with open(os.path.join(os.path.dirname(__file__),FOLDER, CMD_FILE), encoding='utf-8') as f:
BOT_COMMANDS = json.load(f)
BOT_COMMANDS = BOT_COMMANDS[LANG]
================================================
FILE: AdminBot/markups.py
================================================
# Description: This file contains all the reply and inline keyboard markups used in the bot.
from telebot.types import ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton
from AdminBot.content import KEY_MARKUP
from AdminBot.content import MESSAGES
from config import CLIENT_TOKEN, HIDY_BOT_ID
from Utils.utils import all_configs_settings, rial_to_toman
# Main Menu Reply Keyboard Markup
def main_menu_keyboard_markup():
markup = ReplyKeyboardMarkup(row_width=3, resize_keyboard=True)
#markup.add(KeyboardButton(KEY_MARKUP['USERS_LIST']))
#markup.add(KeyboardButton(KEY_MARKUP['USERS_SEARCH']), KeyboardButton(KEY_MARKUP['ADD_USER']))
markup.add(KeyboardButton(KEY_MARKUP['SERVERS_MANAGEMENT']))
markup.add(KeyboardButton(KEY_MARKUP['USERS_SEARCH']))
if CLIENT_TOKEN:
markup.add(KeyboardButton(KEY_MARKUP['USERS_BOT_MANAGEMENT']))
markup.add()
markup.add(KeyboardButton(KEY_MARKUP['SERVER_STATUS']), KeyboardButton(KEY_MARKUP['ABOUT_BOT']),
KeyboardButton(KEY_MARKUP['SERVER_BACKUP']))
return markup
#----------------------------------Hiddify User ---------------------------------
# Users List Inline Keyboard Markup
def users_list_markup(server_id, users, page=1):
markup = InlineKeyboardMarkup(row_width=3)
USER_PER_PAGE = 20
start = (page - 1) * USER_PER_PAGE
end = start + USER_PER_PAGE
keys = []
for user in users[start:end]:
status_tag = ""
if user['last_connection'] == "Online" or user['last_connection'] == "آنلاین":
status_tag = "🔵"
else:
status_tag = "🟡"
if user['remaining_day'] == 0:
status_tag = "🔴"
if user['usage']['remaining_usage_GB'] <= 0:
status_tag = "🔴️"
keys.append(InlineKeyboardButton(f"{status_tag}|{user['name']}", callback_data=f"info:{user['uuid']}"))
markup.add(*keys)
if page < len(users) / USER_PER_PAGE:
markup.add(InlineKeyboardButton(KEY_MARKUP['NEXT_PAGE'], callback_data=f"next:{page + 1}"), row_width=2)
if page > 1:
markup.add(InlineKeyboardButton(KEY_MARKUP['PREV_PAGE'], callback_data=f"next:{page - 1}"), row_width=1)
if server_id != "None":
markup.add(InlineKeyboardButton(KEY_MARKUP['ADD_USER'], callback_data=f"server_add_user:{server_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_SEARCH'], callback_data=f"server_search_user:{server_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_server_selected:{server_id}"))
return markup
# Single User Inline Keyboard Markup
def user_info_markup(uuid):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_USER'], callback_data=f"user_config:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['EDIT_USER'], callback_data=f"user_edit:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['DELETE_USER'], callback_data=f"user_delete:{uuid}"))
return markup
# Single User Edit Inline Keyboard Markup
def edit_user_markup(uuid):
markup = InlineKeyboardMarkup()
markup.row_width = 2
markup.add(InlineKeyboardButton(KEY_MARKUP['EDIT_NAME'], callback_data=f"user_edit_name:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['EDIT_USAGE'], callback_data=f"user_edit_usage:{uuid}"),
InlineKeyboardButton(KEY_MARKUP['RESET_USAGE'], callback_data=f"user_edit_reset_usage:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['EDIT_DAYS'], callback_data=f"user_edit_days:{uuid}"),
InlineKeyboardButton(KEY_MARKUP['RESET_DAYS'], callback_data=f"user_edit_reset_days:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['EDIT_COMMENT'], callback_data=f"user_edit_comment:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['UPDATE_MESSAGE'], callback_data=f"user_edit_update:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_user_panel:{uuid}"))
return markup
# # Add User Reply Keyboard Markup
# def while_add_user_markup():
# markup = ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
# markup.add(KeyboardButton(KEY_MARKUP['CANCEL']))
# return markup
# Edit User Reply Keyboard Markup
def while_edit_user_markup():
markup = ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
markup.add(KeyboardButton(KEY_MARKUP['CANCEL']))
return markup
def while_edit_skip_user_markup():
markup = ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
markup.add(KeyboardButton(KEY_MARKUP['SKIP']))
markup.add(KeyboardButton(KEY_MARKUP['CANCEL']))
return markup
# Confirm Add User Reply Keyboard Markup
def confirm_add_user_markup():
markup = ReplyKeyboardMarkup(row_width=1, resize_keyboard=True)
markup.add(KeyboardButton(KEY_MARKUP['CONFIRM']))
markup.add(KeyboardButton(KEY_MARKUP['CANCEL']))
return markup
# Subscription URL Inline Keyboard Markup
def sub_url_user_list_markup(uuid):
markup = InlineKeyboardMarkup()
markup.row_width = 2
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_DIR'], callback_data=f"conf_dir:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_SUB_AUTO'], callback_data=f"conf_sub_auto:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_SUB'], callback_data=f"conf_sub_url:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_SUB_B64'], callback_data=f"conf_sub_url_b64:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_CLASH'], callback_data=f"conf_clash:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_HIDDIFY'], callback_data=f"conf_hiddify:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_SING_BOX'], callback_data=f"conf_sub_sing_box:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_FULL_SING_BOX'],
callback_data=f"conf_sub_full_sing_box:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_user_panel:{uuid}"))
return markup
# Subscription Configs Inline Keyboard Markup
def sub_user_list_markup(uuid,configs):
markup = InlineKeyboardMarkup()
markup.row_width = 1
if configs['vless']:
markup.add(InlineKeyboardButton('Vless', callback_data=f"conf_dir_vless:{uuid}"))
if configs['vmess']:
markup.add(InlineKeyboardButton('Vmess', callback_data=f"conf_dir_vmess:{uuid}"))
if configs['trojan']:
markup.add(InlineKeyboardButton('Trojan', callback_data=f"conf_dir_trojan:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_sub_url_user_list:{uuid}"))
return markup
# Search User Inline Keyboard Markup
def search_user_markup(server_id=None):
callback_data = server_id if server_id else "None"
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['SEARCH_USER_NAME'], callback_data=f"search_name:{callback_data}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SEARCH_USER_UUID'], callback_data=f"search_uuid:{callback_data}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SEARCH_USER_CONFIG'], callback_data=f"search_config:{callback_data}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SEARCH_EXPIRED_USERS'], callback_data=f"search_expired:{callback_data}"))
if server_id:
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_server_user_list:{server_id}"))
return markup
#----------------------------------End Hiddify User ---------------------------------
#----------------------------------Bot User Management ------------------------------
# Users Bot Management - Inline Keyboard Markup
def users_bot_management_markup(value=None):
markup = InlineKeyboardMarkup()
markup.row_width = 3
# markup.add(
# InlineKeyboardButton(KEY_MARKUP['USERS_BOT_ORDERS_STATUS'], callback_data=f"users_bot_orders_status:None"),
# markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_ADD_PLAN'], callback_data=f"users_bot_add_plan:None"),
# InlineKeyboardButton(KEY_MARKUP['USERS_BOT_DEL_PLAN'], callback_data=f"users_bot_list_plans:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BOT_USERS_MANAGEMENT'],
callback_data=f"bot_users_list_management:None"))
# markup.add(InlineKeyboardButton(KEY_MARKUP['ORDERS_MANAGEMENT'],
# callback_data=f"users_bot_orders_list_management:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['PAYMENT_MANAGEMENT'],
callback_data=f"users_bot_payments_list_management:None"),
InlineKeyboardButton(KEY_MARKUP['ORDERS_MANAGEMENT'],
callback_data=f"users_bot_orders_list_management:None"),)
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SUB_STATUS'], callback_data=f"users_bot_sub_status:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SEND_MESSAGE_TO_USERS'],
callback_data=f"users_bot_send_msg_users:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_OWNER_INFO'], callback_data=f"users_bot_owner_info:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS'], callback_data=f"users_bot_settings:None"))
return markup
# Users Bot Users List Management - Inline Keyboard Markup
def users_bot_users_management_markup(value=None):
markup = InlineKeyboardMarkup()
markup.row_width = 2
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_LIST'], callback_data=f"bot_users_list:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SEARCH_USERS_BOT'], callback_data=f"search_users_bot:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_management_menu:None"))
return markup
# Users Bot Search Method - Inline Keyboard Markup
def users_bot_users_search_method_markup(value=None):
markup = InlineKeyboardMarkup()
markup.row_width = 2
markup.add(InlineKeyboardButton(KEY_MARKUP['SEARCH_USER_NAME'], callback_data=f"bot_users_search_name:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SEARCH_USER_TELEGRAM_ID'], callback_data=f"bot_users_search_telegram_id:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_users_bot_users_management:None"))
return markup
# Users List Inline Keyboard Markup
def bot_users_list_markup(users, page=1):
markup = InlineKeyboardMarkup(row_width=3)
USER_PER_PAGE = 20
start = (page - 1) * USER_PER_PAGE
end = start + USER_PER_PAGE
keys = []
for user in users[start:end]:
name = user['full_name'] if user['full_name'] else user['telegram_id']
keys.append(InlineKeyboardButton(f"{name}", callback_data=f"bot_user_info:{user['telegram_id']}"))
markup.add(*keys)
if page < len(users) / USER_PER_PAGE:
markup.add(InlineKeyboardButton(KEY_MARKUP['NEXT_PAGE'], callback_data=f"bot_user_next:{page + 1}"), row_width=2)
if page > 1:
markup.add(InlineKeyboardButton(KEY_MARKUP['PREV_PAGE'], callback_data=f"bot_user_next:{page - 1}"), row_width=1)
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_bot_users_or_reffral_management:None"))
return markup
# User Item List Inline Keyboard Markup
def bot_user_item_list_markup(items, page=1):
markup = InlineKeyboardMarkup(row_width=3)
USER_PER_PAGE = 20
start = (page - 1) * USER_PER_PAGE
end = start + USER_PER_PAGE
keys = []
for item in items[start:end]:
keys.append(InlineKeyboardButton(f"{item['id']}", callback_data=f"bot_user_item_info:{item['id']}"))
markup.add(*keys)
if page < len(items) / USER_PER_PAGE:
markup.add(InlineKeyboardButton(KEY_MARKUP['NEXT_PAGE'], callback_data=f"bot_user_item_next:{page + 1}"), row_width=2)
if page > 1:
markup.add(InlineKeyboardButton(KEY_MARKUP['PREV_PAGE'], callback_data=f"bot_user_item_next:{page - 1}"), row_width=1)
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_management_item_list:None"))
return markup
# Users Bot Users info Management - Inline Keyboard Markup
def bot_user_info_markup(telegram_id):
markup = InlineKeyboardMarkup()
markup.row_width = 2
markup.add(InlineKeyboardButton(KEY_MARKUP['USER_SUB_LIST'], callback_data=f"bot_users_sub_user_list:{telegram_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['ORDERS_LIST'], callback_data=f"users_bot_orders_user_list:{telegram_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['PAYMENTS_LIST'], callback_data=f"users_bot_payments_user_list:{telegram_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['EDIT_WALLET'], callback_data=f"users_bot_wallet_edit_balance:{telegram_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['RESET_TEST'], callback_data=f"users_bot_reset_test:{telegram_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BAN_USER'], callback_data=f"users_bot_ban_user:{telegram_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SEND_MESSAGE'], callback_data=f"users_bot_send_message_by_admin:{telegram_id}"))
# markup.add(InlineKeyboardButton(KEY_MARKUP['GIFT_LIST'], callback_data=f"users_bot_gifts_user_list:{telegram_id}"),
# InlineKeyboardButton(KEY_MARKUP['REFERRED_LIST'], callback_data=f"users_bot_referred_user_list:{telegram_id}"))
#markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_management_menu:None"))
return markup
# Users Bot Users List Management - Inline Keyboard Markup
def users_bot_orders_management_markup(value=None):
markup = InlineKeyboardMarkup()
markup.row_width = 2
markup.add(InlineKeyboardButton(KEY_MARKUP['ORDERS_LIST'], callback_data=f"users_bot_orders_list:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SEARCH_ORDERS'], callback_data=f"search_orders:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_management_menu:None"))
return markup
def confirm_payment_by_admin(payment_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton(KEY_MARKUP['CONFIRM_PAYMENT'], callback_data=f"confirm_payment_by_admin:{payment_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['NO'], callback_data=f"cancel_payment_by_admin:{payment_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SEND_MESSAGE'], callback_data=f"send_message_by_admin:{payment_id}"))
return markup
def send_message_to_user_markup(admin_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['ANSWER'], callback_data=f"answer_to_admin:{admin_id}"))
return markup
def change_status_payment_by_admin(payment_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton(KEY_MARKUP['CHANGE_STATUS_PAYMENT'], callback_data=f"change_status_payment_by_admin:{payment_id}"))
return markup
def confirm_change_status_payment_by_admin(payment_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton(KEY_MARKUP['YES'], callback_data=f"confirm_change_status_payment_by_admin:{payment_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['NO'], callback_data=f"cancel_change_status_payment_by_admin:{payment_id}"))
return markup
# Users Bot Payments List Management - Inline Keyboard Markup
def users_bot_payments_management_markup(value=None):
markup = InlineKeyboardMarkup()
markup.row_width = 2
markup.add(InlineKeyboardButton(KEY_MARKUP['APPROVED_PAYMENTS_LIST'],
callback_data=f"bot_users_approved_payments_list:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['NON_APPROVED_PAYMENTS_LIST'],
callback_data=f"users_bot_non_approved_payments_list:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['PENDING_PAYMENT_LIST'],
callback_data=f"users_bot_pending_payments_list:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['CARD_PAYMENT_LIST'],
callback_data=f"users_bot_card_payments_list:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['DIGITAL_PAYMENT_LIST'],
callback_data=f"users_bot_digital_payments_list:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SEARCH_PAYMENTS'], callback_data=f"search_payments:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_management_menu:None"))
return markup
#----------------------------------Bot User Settings Management ------------------------------
# Users Bot Management - Settings - Inline Keyboard Markup
def users_bot_management_settings_markup(settings):
markup = InlineKeyboardMarkup()
markup.row_width = 2
status_hyperlink = "✅" if settings['visible_hiddify_hyperlink'] else "❌"
status_three_rand = "✅" if settings['three_random_num_price'] else "❌"
status_panel_auto_backup = "✅" if settings['panel_auto_backup'] else "❌"
status_bot_auto_backup = "✅" if settings['bot_auto_backup'] else "❌"
status_force_join = "✅" if settings['force_join_channel'] else "❌"
status_buy_sub = "✅" if settings['buy_subscription_status'] else "❌"
status_renewal_sub = "✅" if settings['renewal_subscription_status'] else "❌"
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_SHOW_HIDI_LINK']} | {status_hyperlink}",
callback_data=f"users_bot_settings_hyperlink:{settings['visible_hiddify_hyperlink']}"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_SHOW_THREE_RAND']} | {status_three_rand}",
callback_data=f"users_bot_settings_three_rand_price:{settings['three_random_num_price']}"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_BUY_SUBSCRIPTION_STATUS']} | {status_buy_sub}",
callback_data=f"users_bot_settings_buy_sub_status:{settings['buy_subscription_status']}"),
InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_RENEWAL_SUBSCRIPTION_STATUS']} | {status_renewal_sub}",
callback_data= f"users_bot_settings_renewal_sub_status:{settings['renewal_subscription_status']}"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_CHANNEL_ّFORCE_JOIN']} | {status_force_join}",
callback_data=f"users_bot_settings_force_join:{settings['force_join_channel']}"),
InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_CHANNEL_ID'],
callback_data=f"users_bot_settings_channel_id:None"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_PANEL_AUTO_BACKUP']} | {status_panel_auto_backup}",
callback_data=f"users_bot_settings_panel_auto_backup:{settings['panel_auto_backup']}"),)
# InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_BOT_AUTO_BACKUP']} | {status_bot_auto_backup}",
# callback_data=f"users_bot_settings_bot_auto_backup:{settings['bot_auto_backup']}")
# )
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_SET_WELCOME_MSG'],
callback_data=f"users_bot_settings_set_welcome_msg:None"),
InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_PANEL_MANUAL'],
callback_data="users_bot_settings_panel_manual_menu:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_SET_FAQ_MSG'],
callback_data=f"users_bot_settings_faq_management:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_VISIBLE_SUBS'],
callback_data=f"users_bot_settings_visible_sub_menu:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_TEST_SUB'],
callback_data=f"users_bot_settings_test_sub_menu:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_NOTIF_REMINDER'],
callback_data=f"users_bot_settings_notif_reminder_menu:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_MIN_DEPO'],
callback_data=f"users_bot_settings_min_depo:{settings['min_deposit_amount']}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_RENEWAL_METHOD'],
callback_data=f"users_bot_settings_renewal_method_menu:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_RESET_FREE_TEST_LIMIT'],
callback_data=f"users_bot_settings_reset_free_test_limit_question:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_BACKUP_BOT'],
callback_data=f"users_bot_settings_backup_bot:None"),
InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_RESTORE_BOT'],
callback_data=f"users_bot_settings_restore_bot:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_management_menu:None"))
return markup
# Users Bot Management - Settings - Renewal Method - Inline Keyboard Markup
def users_bot_management_settings_renewal_method_markup(settings):
markup = InlineKeyboardMarkup()
markup.row_width = 3
default, advanced, fairly = "❌", "❌", "❌"
if settings['renewal_method'] == 1:
default = "✅"
elif settings['renewal_method'] == 2:
advanced = "✅"
elif settings['renewal_method'] == 3:
fairly = "✅"
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_RENEWAL_METHOD_DEFAULT']} | {default}",
callback_data=f"users_bot_settings_renewal_method:1"),
InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED']} | {advanced}",
callback_data=f"users_bot_settings_renewal_method:2"),
InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_RENEWAL_METHOD_FAIRLY']} | {fairly}",
callback_data=f"users_bot_settings_renewal_method:3"),
)
if settings['renewal_method'] == 2:
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_DAYS'],
callback_data=f"users_bot_settings_renewal_method_advanced_days:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_RENEWAL_METHOD_ADVANCED_USAGE'],
callback_data=f"users_bot_settings_renewal_method_advanced_usage:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_settings:None"))
return markup
# Users Bot Management - Settings - Free Test - Inline Keyboard Markup
def users_bot_management_settings_test_sub_markup(settings):
markup = InlineKeyboardMarkup()
markup.row_width = 1
status_test_sub = "✅" if settings['test_subscription'] else "❌"
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_TEST_SUB']} | {status_test_sub}",
callback_data=f"users_bot_settings_test_sub:test_subscription"))
if settings['test_subscription']:
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_TEST_SUB_SIZE'],
callback_data=f"users_bot_settings_test_sub_size:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_TEST_SUB_DAYS'],
callback_data=f"users_bot_settings_test_sub_days:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_settings:None"))
return markup
# Users Bot Management - Settings - Reminder Notificaation - Inline Keyboard Markup
def users_bot_management_settings_notif_reminder_markup(settings):
markup = InlineKeyboardMarkup()
markup.row_width = 1
status_test_sub = "✅" if settings['reminder_notification'] else "❌"
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['USERS_BOT_SETTINGS_NOTIF_REMINDER']} | {status_test_sub}",
callback_data=f"users_bot_settings_notif_reminder:reminder_notification"))
if settings['reminder_notification']:
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_NOTIF_REMINDER_USAGE'],
callback_data=f"users_bot_settings_notif_reminder_usage:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_NOTIF_REMINDER_DAYS'],
callback_data=f"users_bot_settings_notif_reminder_days:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_settings:None"))
return markup
# Users Bot Management - Settings - Subscription Links - Inline Keyboard Markup
def users_bot_management_settings_visible_sub_markup(settings):
markup = InlineKeyboardMarkup()
markup.row_width = 1
status_visible_conf_dir = "✅" if settings['visible_conf_dir'] else "❌"
status_conf_sub_auto = "✅" if settings['visible_conf_sub_auto'] else "❌"
status_conf_sub_url = "✅" if settings['visible_conf_sub_url'] else "❌"
status_conf_sub_url_b64 = "✅" if settings['visible_conf_sub_url_b64'] else "❌"
status_conf_clash = "✅" if settings['visible_conf_clash'] else "❌"
status_conf_hiddify = "✅" if settings['visible_conf_hiddify'] else "❌"
status_conf_sub_sing_box = "✅" if settings['visible_conf_sub_sing_box'] else "❌"
status_conf_sub_full_sing_box = "✅" if settings['visible_conf_sub_full_sing_box'] else "❌"
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['CONFIGS_DIR']} | {status_visible_conf_dir}",
callback_data=f"users_bot_settings_visible_sub:visible_conf_dir"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['CONFIGS_SUB_AUTO']} | {status_conf_sub_auto}",
callback_data=f"users_bot_settings_visible_sub:visible_conf_sub_auto"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['CONFIGS_SUB']} | {status_conf_sub_url}",
callback_data=f"users_bot_settings_visible_sub:visible_conf_sub_url"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['CONFIGS_SUB_B64']} | {status_conf_sub_url_b64}",
callback_data=f"users_bot_settings_visible_sub:visible_conf_sub_url_b64"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['CONFIGS_CLASH']} | {status_conf_clash}",
callback_data=f"users_bot_settings_visible_sub:visible_conf_clash"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['CONFIGS_HIDDIFY']} | {status_conf_hiddify}",
callback_data=f"users_bot_settings_visible_sub:visible_conf_hiddify"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['CONFIGS_SING_BOX']} | {status_conf_sub_sing_box}",
callback_data=f"users_bot_settings_visible_sub:visible_conf_sub_sing_box"))
markup.add(InlineKeyboardButton(f"{KEY_MARKUP['CONFIGS_FULL_SING_BOX']} | {status_conf_sub_full_sing_box}",
callback_data=f"users_bot_settings_visible_sub:visible_conf_sub_full_sing_box"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_settings:None"))
return markup
# Users Bot Management - Settings - Manual - Inline Keyboard Markup
def users_bot_management_settings_panel_manual_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_PANEL_MANUAL_ANDROID'],
callback_data=f"users_bot_settings_panel_manual:msg_manual_android"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_PANEL_MANUAL_IOS'],
callback_data=f"users_bot_settings_panel_manual:msg_manual_ios"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_PANEL_MANUAL_WIN'],
callback_data=f"users_bot_settings_panel_manual:msg_manual_windows"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_PANEL_MANUAL_MAC'],
callback_data=f"users_bot_settings_panel_manual:msg_manual_mac"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_PANEL_MANUAL_LIN'],
callback_data=f"users_bot_settings_panel_manual:msg_manual_linux"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_settings:None"))
return markup
def users_bot_management_settings_faq_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 1
settings = all_configs_settings()
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_SET_FAQ_MESSAGE'],
callback_data=f"users_bot_settings_set_faq_msg:None"))
if settings['msg_faq']:
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_SETTINGS_HIDE_FAQ'],
callback_data=f"users_bot_settings_hide_faq:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_settings:None"))
return markup
# Users Bot Management - Edit Owner Info - Inline Keyboard Markup
def users_bot_edit_owner_info_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_OWNER_INFO_EDIT_USERNAME'],
callback_data=f"users_bot_owner_info_edit_username:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_OWNER_INFO_EDIT_CARD_NUMBER'],
callback_data=f"users_bot_owner_info_edit_card_number:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_OWNER_INFO_EDIT_CARD_NAME'],
callback_data=f"users_bot_owner_info_edit_card_name:None"))
return markup
def users_bot_management_settings_reset_free_test_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIRM'],
callback_data=f"users_bot_management_settings_reset_free_test_confirm:None"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"users_bot_settings:None"))
return markup
# Single Subscription Inline Keyboard Markup
def sub_search_info_markup(uuid,user):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_USER'], callback_data=f"user_config:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['EDIT_USER'], callback_data=f"user_edit:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['DELETE_USER'], callback_data=f"user_delete:{uuid}"))
name = user['full_name'] if user['full_name'] else user['telegram_id']
markup.add(InlineKeyboardButton(f"{name}", callback_data=f"bot_user_info:{user['telegram_id']}"))
return markup
#--------------------------------------End Bot User Management -----------------------------------
#----------------------------------End Bot User Settings Management ------------------------------
#-----------------------------------------Servers Management -------------------------------------
# Server Management - Server List - Inline Keyboard Markup
def servers_management_markup(servers):
markup = InlineKeyboardMarkup(row_width=1)
keys = []
if servers:
for server in servers:
#if server['status']:
keys.append(InlineKeyboardButton(f"{server['title']}",
callback_data=f"server_selected:{server['id']}"))
keys.append(InlineKeyboardButton(KEY_MARKUP['ADD_SERVER'],
callback_data=f"add_server:None"))
markup.add(*keys)
return markup
# Server Management - Server Info - Inline Keyboard Markup
def server_selected_markup(server_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['SERVER_LIST_OF_USERS'],
callback_data=f"server_list_of_users:{server_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SERVER_LIST_OF_PLANS'],
callback_data=f"server_list_of_plans:{server_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['EDIT_SERVER'],
callback_data=f"edit_server:{server_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_server_management:None"))
return markup
# Server Management - Server Delete - Inline Keyboard Markup
def server_delete_markup(server_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIRM'],
callback_data=f"confirm_delete_server:{server_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['CANCEL'],
callback_data=f"server_selected:{server_id}"))
return markup
# Server Management - Server Edit - Inline Keyboard Markup
def server_edit_markup(server_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['SERVER_EDIT_TITLE'],
callback_data=f"server_edit_title:{server_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SERVER_EDIT_USER_LIMIT'],
callback_data=f"server_edit_user_limit:{server_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SERVER_EDIT_URL'],
callback_data=f"server_edit_url:{server_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['DELETE_SERVER'],
callback_data=f"delete_server:{server_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_server_selected:{server_id}"))
return markup
# Server Management - Plans List - Inline Keyboard Markup
def plans_list_markup(plans, server_id, delete_mode=False):
markup = InlineKeyboardMarkup(row_width=1)
plan_selected_callback_data = "users_bot_del_plan:" if delete_mode else "info_plan_selected:"
back_callback_data = "back_to_server_list_of_plans:" if delete_mode else "back_to_server_selected:"
keys = []
if plans:
for plan in plans:
keys.append(InlineKeyboardButton(
f"{plan['size_gb']}{MESSAGES['GB']} | {plan['days']}{MESSAGES['DAY']} | {rial_to_toman(plan['price'])} {MESSAGES['TOMAN']}",
callback_data = f"{plan_selected_callback_data}{plan['id']}"))
if not delete_mode:
keys.append(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_ADD_PLAN'], callback_data=f"users_bot_add_plan:{server_id}"))
keys.append(InlineKeyboardButton(KEY_MARKUP['USERS_BOT_DEL_PLAN'], callback_data=f"users_bot_list_plans:{server_id}"))
keys.append(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"{back_callback_data}{server_id}"))
markup.add(*keys)
return markup
# Server Management - Plans List - Inline Keyboard Markup
def plan_info_selected_markup(server_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_server_list_of_plans:{server_id}"))
return markup
#-------------------------------------End Servers Management -------------------------------------
def start_bot_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 1
bot_id = HIDY_BOT_ID.replace("@", "")
markup.add(InlineKeyboardButton(KEY_MARKUP['SUPPORT_GROUP'], url=f"https://t.me/{bot_id}"))
return markup
def server_status_markup(servers):
markup = InlineKeyboardMarkup()
markup.row_width = 1
keys = []
for server in servers:
if server['status']:
keys.append(InlineKeyboardButton(f"{server['title']}",
callback_data=f"server_status:{server['id']}"))
markup.add(*keys)
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"del_msg:None"))
return markup
================================================
FILE: AdminBot/templates.py
================================================
# Description: This file contains all the templates used in the bot.
from config import LANG, VERSION, API_PATH
from AdminBot.content import MESSAGES
from Utils import api, utils
import datetime
import urllib.parse
# Single User Info Message Template
def user_info_template(usr, server, header=""):
if not usr['comment']:
usr['comment'] = "-"
if usr['remaining_day'] == 0:
usr['remaining_day'] = MESSAGES['USER_TIME_EXPIRED']
elif usr['remaining_day'] == 1:
usr['remaining_day'] = MESSAGES['USER_LAST_DAY']
else:
usr['remaining_day'] = f"{usr['remaining_day']} {MESSAGES['DAY_EXPIRE']}"
return f"""
{header}
{MESSAGES['INFO_USER_NAME']} {usr['name']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['SERVER']} {server['title']}
{MESSAGES['INFO_USAGE']} {usr['usage']['current_usage_GB']} {MESSAGES['OF']} {usr['usage']['usage_limit_GB']} {MESSAGES['GB']}
{MESSAGES['INFO_REMAINING_DAYS']} {usr['remaining_day']}
{MESSAGES['INFO_LAST_CONNECTION']} {usr['last_connection']}
{MESSAGES['INFO_COMMENT']} {usr['comment']}
"""
# Server Info Message Template
def server_info_template(server, plans, header=""):
plans_num = 0
user_index = 0
URL = server['url'] + API_PATH
users_list = api.select(URL)
if users_list:
user_index = len(users_list)
if plans:
for plan in plans:
if plan['status']:
if plan['server_id'] == server['id']:
plans_num += 1
return f"""
{header}
{MESSAGES['INFO_SERVER']} {server['title']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['INFO_SERVER_USER_NUMBER']} {user_index} {MESSAGES['OF']} {server['user_limit']}
{MESSAGES['INFO_SERVER_USER_PLAN']} {plans_num}
"""
# Plan Info Message Template
def plan_info_template(plan, orders, header=""):
num_orders = 0
if orders:
for order in orders:
num_orders += 1
sale = num_orders * plan['price']
return f"""
{header}
{MESSAGES['INFO_PLAN_ID']} {plan['id']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['INFO_PLAN_USAGE']} {plan['size_gb']}
{MESSAGES['INFO_PLAN_DAYS']} {plan['days']}
{MESSAGES['INFO_PLAN_PRICE']} {utils.rial_to_toman(plan['price'])} {MESSAGES['TOMAN']}
{MESSAGES['INFO_PLAN_DESC']} {plan['description']}
{MESSAGES['INFO_PLAN_NUM_ORDER']} {num_orders}
{MESSAGES['INFO_PLAN_TOTAL_SALE']} {utils.rial_to_toman(sale)} {MESSAGES['TOMAN']}
"""
# Users List Message Template
def users_list_template(users, heder=""):
# Number of Online Users
online_users = 0
for user in users:
if user['last_connection'] == "Online" or user['last_connection'] == "آنلاین":
online_users += 1
return f"""
{heder}
{MESSAGES['HEADER_USERS_LIST']}
{MESSAGES['HEADER_USERS_LIST_MSG']}
{MESSAGES['NUM_USERS']} {len(users)}
{MESSAGES['NUM_USERS_ONLINE']} {online_users}
"""
# Bot Users List Message Template
def bot_users_list_template(users, wallets, orders, header=""):
users_get_free = 0
ordered_users = 0
total_balance_wallets= 0
if wallets:
for wallet in wallets:
total_balance_wallets += wallet['balance']
if orders:
for user in users:
if user['test_subscription']:
users_get_free += 1
for order in orders:
if order['telegram_id'] == user['telegram_id']:
ordered_users += 1
break
else:
for user in users:
if user['test_subscription']:
users_get_free += 1
return f"""
{header}
{MESSAGES['HEADER_USERS_LIST']}
{MESSAGES['HEADER_USERS_LIST_MSG']}
{MESSAGES['NUM_USERS']} {len(users)}
{MESSAGES['NUM_GET_FREE_USERS']} {users_get_free}
{MESSAGES['NUM_ORDERED_USERS']} {ordered_users}
{MESSAGES['TOTAL_BALANCE_USERS']} {utils.rial_to_toman(total_balance_wallets)}{MESSAGES['TOMAN']}
"""
# Bot Users Info Message Template
def bot_users_info_template(user, orders, payments, wallet, non_order_subs, order_subs, plans, header=""):
total_orders = 0
total_payment = 0
approved_payment = 0
total_order_subs = 0
total_non_order_subs = 0
total_balance = 0
total_valume = 0
total_sales = 0
if orders:
total_orders = len(orders)
if plans:
for order in orders:
for plan in plans:
if order['plan_id'] == plan['id']:
total_valume += plan['size_gb']
total_sales += plan['price']
break
if payments:
total_payment = len(payments)
approved_payments = [payment for payment in payments if payment['approved'] == 1]
if approved_payments:
approved_payment = len(approved_payments)
if non_order_subs:
total_non_order_subs = len(non_order_subs)
if order_subs:
total_order_subs = len(order_subs)
if wallet:
total_balance = wallet['balance']
name = user['full_name'] if user['full_name'] else user['telegram_id']
username = f"@{user['username']}" if user['username'] else MESSAGES['NOT_SET']
free_test_status = "✅" if user['test_subscription'] else "❌"
return f"""
{header}
{MESSAGES['INFO_USER_NAME']}{name}
{MESSAGES['INFO_USER_USERNAME']}{username}
{MESSAGES['INFO_USER_NUM_ID']}{user['telegram_id']}
{MESSAGES['GET_FREE_TEST_STATUS']}{free_test_status}
{MESSAGES['WALLET_BALANCE']}{utils.rial_to_toman(total_balance)}{MESSAGES['TOMAN']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['NUM_ORDER_SUB']} {total_order_subs}
{MESSAGES['NUM_NON_ORDER_SUB']} {total_non_order_subs}
{MESSAGES['NUM_PAYMENTS']} {total_payment}
{MESSAGES['NUM_APPROVED_PAYMENTS']} {approved_payment}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['NUM_ORDERS']} {total_orders}
{MESSAGES['TOTAL_ORDERS_VALUME']} {total_valume}
{MESSAGES['TOTAL_ORDERS_SALES']} {utils.rial_to_toman(total_sales)}{MESSAGES['TOMAN']}
"""
# Bot Users Order Info Message Template
def bot_orders_info_template(order, plan, user, server, header=""):
name = user['full_name'] if user['full_name'] else user['telegram_id']
username = f"@{user['username']}" if user['username'] else MESSAGES['NOT_SET']
return f"""
{header}
{MESSAGES['BOT_ORDER_ID']}{order['id']}
{MESSAGES['BOT_ORDER_DATE']}{order['created_at']}
{MESSAGES['INFO_USER_NAME']}{name}
{MESSAGES['INFO_USER_USERNAME']}{username}
{MESSAGES['INFO_USER_NUM_ID']}{user['telegram_id']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['ORDERED_VALUME']}{plan['size_gb']}
{MESSAGES['ORDERED_DAYS']}{plan['days']}
{MESSAGES['ORDERED_PRICE']}{utils.rial_to_toman(plan['price'])}{MESSAGES['TOMAN']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['SUB_NAME']}{order['user_name']}
{MESSAGES['SERVER']}{server['title']}
"""
# Payment Received Template - Send to Admin
def bot_payment_info_template(payment,user, header="", footer=""):
#approved = "✅" if payment['approved'] else "❌"
if payment['approved']: approved = "✅"
elif payment['approved'] == False: approved = "❌"
else: approved = "⏳"
username = f"@{user['username']}" if user['username'] else MESSAGES['NOT_SET']
name = user['full_name'] if user['full_name'] else user['telegram_id']
return f"""
{header}
{MESSAGES['PAYMENTS_ID']} {payment['id']}
{MESSAGES['INFO_USER_NAME']} {name}
{MESSAGES['INFO_USER_USERNAME']} {username}
{MESSAGES['INFO_USER_NUM_ID']} {user['telegram_id']}
{MESSAGES['BOT_PAYMENT_DATE']} {payment['created_at']}
{MESSAGES['PAIED_AMOUNT']} {utils.rial_to_toman(payment['payment_amount'])} {MESSAGES['TOMAN']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['STATUS']} {approved}
{MESSAGES['PAYMENTS_METHOD']} {payment['payment_method']}
{footer}
"""
# Bot Users List Message Template
def bot_orders_list_template(orders, plans, header=""):
total_orders = 0
total_valume = 0
total_sales = 0
last30day = datetime.datetime.now() - datetime.timedelta(days=30)
last30days_orders = [order for order in orders if datetime.datetime.strptime(order['created_at'], "%Y-%m-%d %H:%M:%S") >= last30day]
last30days_num_orders = 0
last30days_valume = 0
last30days_sales = 0
first_day_this_month = datetime.datetime.today().replace(day=1)
this_month_orders = [order for order in orders if datetime.datetime.strptime(order['created_at'], "%Y-%m-%d %H:%M:%S") >= first_day_this_month]
this_month_num_orders = 0
this_month_valume = 0
this_month_sales = 0
if orders:
total_orders = len(orders)
if plans:
for order in orders:
for plan in plans:
if order['plan_id'] == plan['id']:
total_valume += plan['size_gb']
total_sales += plan['price']
break
if last30days_orders:
last30days_num_orders = len(last30days_orders)
if plans:
for order in last30days_orders:
for plan in plans:
if order['plan_id'] == plan['id']:
last30days_valume += plan['size_gb']
last30days_sales += plan['price']
break
if this_month_orders:
this_month_num_orders = len(this_month_orders)
if plans:
for order in this_month_orders:
for plan in plans:
if order['plan_id'] == plan['id']:
this_month_valume += plan['size_gb']
this_month_sales += plan['price']
break
return f"""
{header}
{MESSAGES['HEADER_ORDERS_LIST']}
{MESSAGES['NUM_ORDERS']} {total_orders}
{MESSAGES['TOTAL_ORDERS_VALUME']} {total_valume}
{MESSAGES['TOTAL_ORDERS_SALES']} {utils.rial_to_toman(total_sales)}{MESSAGES['TOMAN']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['LAST_30DAYS_NUM_ORDERS']} {last30days_num_orders}
{MESSAGES['LAST_30DAYS_ORDERS_VALUME']} {last30days_valume }
{MESSAGES['LAST_30DAYS_ORDERS_SALES']} {utils.rial_to_toman(last30days_sales)}{MESSAGES['TOMAN']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['THIS_MONTH_NUM_ORDERS']} {this_month_num_orders}
{MESSAGES['THIS_MONTH_ORDERS_VALUME']} {this_month_valume}
{MESSAGES['THIS_MONTH_ORDERS_SALES']} {utils.rial_to_toman(this_month_sales)}{MESSAGES['TOMAN']}
"""
# Bot Users List Message Template
def bot_payments_list_template(payments, header=""):
total_payments = 0
total_amount = 0
last30day = datetime.datetime.now() - datetime.timedelta(days=30)
last30days_payments = [payment for payment in payments if datetime.datetime.strptime(payment['created_at'], "%Y-%m-%d %H:%M:%S") >= last30day]
last30days_num_payments = 0
last30days_amount = 0
first_day_this_month = datetime.datetime.today().replace(day=1)
this_month_orders = [payment for payment in payments if datetime.datetime.strptime(payment['created_at'], "%Y-%m-%d %H:%M:%S") >= first_day_this_month]
this_month_num_payments = 0
this_month_amount = 0
if payments:
total_payments = len(payments)
for payment in payments:
total_amount += payment['payment_amount']
if last30days_payments:
last30days_num_payments = len(last30days_payments)
for payment in last30days_payments:
last30days_amount += payment['payment_amount']
if this_month_orders:
this_month_num_payments = len(this_month_orders)
for payment in this_month_orders:
this_month_amount += payment['payment_amount']
return f"""
{header}
{MESSAGES['HEADER_PAYMENT_LIST']}
{MESSAGES['NUM_PAYMENTS']}{total_payments}
{MESSAGES['TOTAL_PAYMENTS_AMOUNT']}{utils.rial_to_toman(total_amount)}{MESSAGES['TOMAN']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['LAST_30DAYS_NUM_PAYMENTS']}{last30days_num_payments}
{MESSAGES['LAST_30DAYS_PAYMENTS_AMOUNT']}{utils.rial_to_toman(last30days_amount)}{MESSAGES['TOMAN']}
❖⬩╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍╍⬩❖
{MESSAGES['THIS_MONTH_NUM_PAYMENTS']}{this_month_num_payments}
{MESSAGES['THIS_MONTH_PAYMENTS_AMOUNT']}{utils.rial_to_toman(this_month_amount)}{MESSAGES['TOMAN']}
"""
# Configs List Message Template
def configs_template(configs):
messages = []
result = []
chunk_size = 5
for config in configs:
messages.append(f"{urllib.parse.unquote(config[1])}\n{config[0]}\n")
for i in range(0, len(messages), chunk_size):
chunk = messages[i:i + chunk_size]
result.append("\n".join(chunk))
return result
# System Status Message Template
def system_status_template(status):
return f"""
System Status
--------------------------------
CPU: {status['cpu']}%
RAM: {status['ram']}%
DISK: {status['disk']}%
"""
# Last Online Time Template
def last_online_time_template(last_online_time):
if last_online_time.days >= 30:
return f"{last_online_time.days // 30} {MESSAGES['MONTH']} {MESSAGES['AGO']} "
elif last_online_time.days >= 7:
return f"{last_online_time.days // 7} {MESSAGES['WEEK']} {MESSAGES['AGO']}"
elif last_online_time.days > 0:
return f"{last_online_time.days} {MESSAGES['DAY']} {MESSAGES['AGO']}"
elif last_online_time.seconds > 3600:
return f"{last_online_time.seconds // 3600} {MESSAGES['HOUR']} {MESSAGES['AGO']}"
elif last_online_time.seconds <= 5 * 60:
return f"{MESSAGES['ONLINE']}"
elif last_online_time.seconds > 60:
return f"{last_online_time.seconds // 60} {MESSAGES['MINUTE']} {MESSAGES['AGO']}"
else:
return MESSAGES['NEVER']
# Owner Info Message Template
def owner_info_template(username, card_number_card, card_name):
username = username if username else "-"
card_number_card = card_number_card if card_number_card else "-"
card_name = card_name if card_name else "-"
if LANG == 'FA':
return f"""
اطلاعات مالک
--------------------------------
نام کاربری پشتیبان: {username}
شماره کارت بانکی: {card_number_card}
نام صاحب حساب بانکی: {card_name}
"""
elif LANG == 'EN':
return f"""
Owner Info
--------------------------------
Telegram Support Username: {username}
Bank Card Number: {card_number_card}
Bank Card Name: {card_name}
"""
# About Bot Message Template
def about_template():
if LANG == 'FA':
return f"""
🤖هیدی بات، راحت تر از همیشه!
لینک پروژه
گروه پشتیبانی | کانال اطلاع رسانی
این پروژه به صورت رایگان توسعه داده شده و جهت ادامه توسعه رایگان، حمایت های شما میتواند انگیزه بخش باشد❤️
نسخه: {VERSION}
"""
elif LANG == 'EN':
return f"""
🤖Hiddify Bot, Easier than ever!
Project | Support Group
This project is developed for free and your financial support can be motivating for further development❤️
Version: {VERSION}
"""
================================================
FILE: Cronjob/backup.py
================================================
from AdminBot.bot import bot
from config import ADMINS_ID
from Utils.utils import full_backup,all_configs_settings
import logging
try:
bot.remove_webhook()
except:
pass
def cron_backup():
zip_file_name = full_backup()
if not zip_file_name:
logging.error("Backup failed")
return
settings = all_configs_settings()
if not settings['panel_auto_backup']:
return
for admin_id in ADMINS_ID:
bot.send_document(admin_id, open(zip_file_name, 'rb'), caption="🤖Backup",disable_notification=True)
================================================
FILE: Cronjob/backupBot.py
================================================
from Utils.utils import all_configs_settings, backup_json_bot
from AdminBot.bot import bot
from config import ADMINS_ID
try:
bot.remove_webhook()
except:
pass
# Send backup file to admins
def cron_backup_bot():
file_name = backup_json_bot()
settings = all_configs_settings()
if not settings['bot_auto_backup']:
return
if file_name:
for admin_id in ADMINS_ID:
bot.send_document(admin_id, open(file_name, 'rb'), caption="🤖Bot Backup",disable_notification=True)
================================================
FILE: Cronjob/reminder.py
================================================
from Utils.utils import *
from UserBot.bot import bot
from config import CLIENT_TOKEN
from UserBot.templates import package_size_end_soon_template, package_days_expire_soon_template
try:
bot.remove_webhook()
except:
pass
settings = all_configs_settings()
ALERT_PACKAGE_GB = settings.get('reminder_notification_usage', 3)
ALERT_PACKAGE_DAYS = settings.get('reminder_notification_days', 3)
def alert_package_gb(package_remaining_gb):
if package_remaining_gb <= ALERT_PACKAGE_GB:
return True
return False
def alert_package_days(package_remaining_days):
if package_remaining_days <= ALERT_PACKAGE_DAYS:
return True
return False
# Send a reminder to users about their packages
def cron_reminder():
if not CLIENT_TOKEN:
return
if not settings['reminder_notification']:
return
telegram_users = USERS_DB.select_users()
if telegram_users:
for user in telegram_users:
user_telegram_id = user['telegram_id']
user_subscriptions_list = non_order_user_info(user_telegram_id) + order_user_info(user_telegram_id)
if user_subscriptions_list:
for user_subscription in user_subscriptions_list:
package_days = user_subscription.get('remaining_day', 0)
package_gb = user_subscription.get('usage', {}).get('remaining_usage_GB', 0)
sub_id = user_subscription.get('sub_id')
if package_days == 0:
continue
if alert_package_gb(package_gb):
bot.send_message(user_telegram_id, package_size_end_soon_template(sub_id, package_gb))
if alert_package_days(package_days):
bot.send_message(user_telegram_id, package_days_expire_soon_template(sub_id, package_days))
================================================
FILE: Database/dbManager.py
================================================
import datetime
import json
import logging
import os
import sqlite3
from sqlite3 import Error
from version import is_version_less
#from urllib.parse import urlparse
#from Utils import api
#from config import PANEL_URL, API_PATH, USERS_DB_LOC
class UserDBManager:
def __init__(self, db_file):
self.conn = self.create_connection(db_file)
self.create_user_table()
#self.set_default_configs()
#close connection
def __del__(self):
self.conn.close()
def close(self):
self.conn.close()
def create_connection(self, db_file):
""" Create a database connection to a SQLite database """
try:
conn = sqlite3.connect(db_file, check_same_thread=False)
return conn
except Error as e:
logging.error(f"Error while connecting to database \n Error:{e}")
return None
def create_user_table(self):
cur = self.conn.cursor()
try:
cur.execute("CREATE TABLE IF NOT EXISTS users ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"telegram_id INTEGER NOT NULL UNIQUE,"
"full_name TEXT NULL,"
"username TEXT NULL,"
# "referral_code INTEGER NOT NULL,"
# "referred_by INTEGER NULL,"
# "discount_percent INTEGER NOT NULL DEFAULT 0,"
# "count_warn INTEGER NOT NULL DEFAULT 0,"
"test_subscription BOOLEAN NOT NULL DEFAULT 0,"
"banned BOOLEAN NOT NULL DEFAULT 0,"
"created_at TEXT NOT NULL)")
self.conn.commit()
logging.info("User table created successfully!")
cur.execute("CREATE TABLE IF NOT EXISTS plans ("
"id INTEGER PRIMARY KEY,"
"size_gb INTEGER NOT NULL,"
"days INTEGER NOT NULL,"
"price INTEGER NOT NULL,"
"server_id INTEGER NOT NULL,"
"description TEXT NULL,"
"status BOOLEAN NOT NULL,"
"FOREIGN KEY (server_id) REFERENCES server (id))")
self.conn.commit()
logging.info("Plans table created successfully!")
# cur.execute("CREATE TABLE IF NOT EXISTS user_plans ("
# "id INTEGER PRIMARY KEY,"
# "telegram_id INTEGER NOT NULL UNIQUE,"
# "plan_id INTEGER NOT NULL,"
# "FOREIGN KEY (telegram_id) REFERENCES users (telegram_id),"
# "FOREIGN KEY (plan_id) REFERENCES plans (id))")
# self.conn.commit()
# logging.info("Plans table created successfully!")
cur.execute("CREATE TABLE IF NOT EXISTS orders ("
"id INTEGER PRIMARY KEY,"
"telegram_id INTEGER NOT NULL,"
"plan_id INTEGER NOT NULL,"
"user_name TEXT NOT NULL,"
"created_at TEXT NOT NULL,"
"FOREIGN KEY (telegram_id) REFERENCES user (telegram_id),"
"FOREIGN KEY (plan_id) REFERENCES plans (id))")
self.conn.commit()
logging.info("Orders table created successfully!")
cur.execute("CREATE TABLE IF NOT EXISTS order_subscriptions ("
"id INTEGER PRIMARY KEY,"
"order_id INTEGER NOT NULL,"
"uuid TEXT NOT NULL,"
"server_id INTEGER NOT NULL,"
"FOREIGN KEY (server_id) REFERENCES server (id),"
"FOREIGN KEY (order_id) REFERENCES orders (id))")
self.conn.commit()
logging.info("Order subscriptions table created successfully!")
cur.execute("CREATE TABLE IF NOT EXISTS non_order_subscriptions ("
"id INTEGER PRIMARY KEY,"
"telegram_id INTEGER NOT NULL,"
"uuid TEXT NOT NULL UNIQUE,"
"server_id INTEGER NOT NULL,"
"FOREIGN KEY (server_id) REFERENCES server (id),"
"FOREIGN KEY (telegram_id) REFERENCES users (telegram_id))")
self.conn.commit()
logging.info("Non order subscriptions table created successfully!")
cur.execute("CREATE TABLE IF NOT EXISTS str_config ("
"key TEXT NOT NULL UNIQUE,"
"value TEXT NULL)")
self.conn.commit()
logging.info("str_config table created successfully!")
cur.execute("CREATE TABLE IF NOT EXISTS int_config ("
"key TEXT NOT NULL UNIQUE,"
"value INTEGER NOT NULL)")
self.conn.commit()
logging.info("int_config table created successfully!")
cur.execute("CREATE TABLE IF NOT EXISTS bool_config ("
"key TEXT NOT NULL UNIQUE,"
"value BOOLEAN NOT NULL)")
self.conn.commit()
logging.info("bool_config table created successfully!")
cur.execute("CREATE TABLE IF NOT EXISTS wallet ("
"telegram_id INTEGER NOT NULL UNIQUE,"
"balance INTEGER NOT NULL DEFAULT 0,"
"FOREIGN KEY (telegram_id) REFERENCES users (telegram_id))")
self.conn.commit()
logging.info("wallet table created successfully!")
cur.execute("CREATE TABLE IF NOT EXISTS payments ("
"id INTEGER PRIMARY KEY,"
"telegram_id INTEGER NOT NULL,"
"payment_amount INTEGER NOT NULL,"
"payment_method TEXT NOT NULL,"
"payment_image TEXT NOT NULL,"
# "user_name TEXT NOT NULL,"
"approved BOOLEAN NULL,"
"created_at TEXT NOT NULL,"
"FOREIGN KEY (telegram_id) REFERENCES users (telegram_id))")
self.conn.commit()
logging.info("Payments table created successfully!")
cur.execute("CREATE TABLE IF NOT EXISTS servers ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"url TEXT NOT NULL,"
"title TEXT, description TEXT,"
"user_limit INTEGER NOT NULL,"
"status BOOLEAN NOT NULL,"
"default_server BOOLEAN NOT NULL DEFAULT 0)")
self.conn.commit()
logging.info("Servers table created successfully!")
except Error as e:
logging.error(f"Error while creating user table \n Error:{e}")
return False
return True
def select_users(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM users")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all users \n Error:{e}")
return None
def find_user(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find user!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM users WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"User {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding user {kwargs} \n Error:{e}")
return None
def delete_user(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to delete user!")
return False
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"DELETE FROM users WHERE {key}=?", (value,))
self.conn.commit()
logging.info(f"User {kwargs} deleted successfully!")
return True
except Error as e:
logging.error(f"Error while deleting user {kwargs} \n Error:{e}")
return False
def edit_user(self, telegram_id, **kwargs):
cur = self.conn.cursor()
for key, value in kwargs.items():
try:
cur.execute(f"UPDATE users SET {key}=? WHERE telegram_id=?", (value, telegram_id))
self.conn.commit()
logging.info(f"User [{telegram_id}] successfully update [{key}] to [{value}]")
except Error as e:
logging.error(f"Error while updating user [{telegram_id}] [{key}] to [{value}] \n Error: {e}")
return False
return True
def add_user(self, telegram_id, full_name,username, created_at):
cur = self.conn.cursor()
try:
cur.execute("INSERT INTO users(telegram_id, full_name,username, created_at) VALUES(?,?,?,?)",
(telegram_id, full_name,username, created_at))
self.conn.commit()
logging.info(f"User [{telegram_id}] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding user [{telegram_id}] \n Error: {e}")
return False
def add_plan(self, plan_id, size_gb, days, price, server_id, description=None, status=True):
cur = self.conn.cursor()
try:
cur.execute("INSERT INTO plans(id,size_gb, days, price, server_id, description, status) VALUES(?,?,?,?,?,?,?)",
(plan_id, size_gb, days, price, server_id, description, status))
self.conn.commit()
logging.info(f"Plan [{size_gb}GB] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding plan [{size_gb}GB] \n Error: {e}")
return False
def select_plans(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM plans ORDER BY price ASC")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all plans \n Error:{e}")
return None
def find_plan(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find plan!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM plans WHERE {key}=? ORDER BY price ASC", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Plan {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding plan {kwargs} \n Error:{e}")
return None
def delete_plan(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to delete plan!")
return False
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"DELETE FROM plans WHERE {key}=?", (value,))
self.conn.commit()
logging.info(f"Plan {kwargs} deleted successfully!")
return True
except Error as e:
logging.error(f"Error while deleting plan {kwargs} \n Error:{e}")
return False
def edit_plan(self, plan_id, **kwargs):
cur = self.conn.cursor()
for key, value in kwargs.items():
try:
cur.execute(f"UPDATE plans SET {key}=? WHERE id=?", (value, plan_id))
self.conn.commit()
logging.info(f"Plan [{plan_id}] successfully update [{key}] to [{value}]")
except Error as e:
logging.error(f"Error while updating plan [{plan_id}] [{key}] to [{value}] \n Error: {e}")
return False
return True
def add_user_plans(self, telegram_id, plan_id):
cur = self.conn.cursor()
try:
cur.execute("INSERT INTO user_plans(telegram_id, plan_id) VALUES(?,?)",
(telegram_id, plan_id))
self.conn.commit()
logging.info(f"Plan [{plan_id}] Reserved for [{telegram_id}] successfully!")
return True
except Error as e:
logging.error(f"Error while Reserving plan [{plan_id}] for [{telegram_id}] \n Error: {e}")
return False
def select_user_plans(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM user_plans")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all user_plans \n Error:{e}")
return None
def find_user_plans(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find user_plan!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM user_plans WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Plan {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding user_plans {kwargs} \n Error:{e}")
return None
def delete_user_plans(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to delete user_plan!")
return False
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"DELETE FROM user_plans WHERE {key}=?", (value,))
self.conn.commit()
logging.info(f"Plan {kwargs} deleted successfully!")
return True
except Error as e:
logging.error(f"Error while deleting user_plans {kwargs} \n Error:{e}")
return False
def edit_user_plans(self, user_plans_id, **kwargs):
cur = self.conn.cursor()
for key, value in kwargs.items():
try:
cur.execute(f"UPDATE user_plans SET {key}=? WHERE id=?", (value, user_plans_id))
self.conn.commit()
logging.info(f"user_plans [{user_plans_id}] successfully update [{key}] to [{value}]")
except Error as e:
logging.error(f"Error while updating user_plans [{user_plans_id}] [{key}] to [{value}] \n Error: {e}")
return False
return True
def add_order(self, order_id, telegram_id,user_name, plan_id, created_at):
cur = self.conn.cursor()
try:
cur.execute(
"INSERT INTO orders(id,telegram_id, plan_id,user_name,created_at) VALUES(?,?,?,?,?)",
(order_id, telegram_id, plan_id,user_name, created_at))
self.conn.commit()
logging.info(f"Order [{order_id}] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding order [{order_id}] \n Error: {e}")
return False
def select_orders(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM orders")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all orders \n Error:{e}")
return None
def find_order(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find order!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM orders WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Order {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding order {kwargs} \n Error:{e}")
return None
def edit_order(self, order_id, **kwargs):
cur = self.conn.cursor()
for key, value in kwargs.items():
try:
cur.execute(f"UPDATE orders SET {key}=? WHERE id=?", (value, order_id))
self.conn.commit()
logging.info(f"Order [{order_id}] successfully update [{key}] to [{value}]")
except Error as e:
logging.error(f"Error while updating order [{order_id}] [{key}] to [{value}] \n Error: {e}")
return False
return True
def add_order_subscription(self, sub_id, order_id, uuid, server_id):
cur = self.conn.cursor()
try:
cur.execute(
"INSERT INTO order_subscriptions(id,order_id,uuid,server_id) VALUES(?,?,?,?)",
(sub_id, order_id, uuid, server_id))
self.conn.commit()
logging.info(f"Order [{order_id}] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding order [{order_id}] \n Error: {e}")
return False
def select_order_subscription(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM order_subscriptions")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all orders \n Error:{e}")
return None
def find_order_subscription(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find order!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM order_subscriptions WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Order {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding order {kwargs} \n Error:{e}")
return None
def edit_order_subscriptions(self, order_id, **kwargs):
cur = self.conn.cursor()
for key, value in kwargs.items():
try:
cur.execute(f"UPDATE order_subscriptions SET {key}=? WHERE order_id=?", (value, order_id))
self.conn.commit()
logging.info(f"Order [{order_id}] successfully update [{key}] to [{value}]")
except Error as e:
logging.error(f"Error while updating order [{order_id}] [{key}] to [{value}] \n Error: {e}")
return False
return True
def delete_order_subscription(self, **kwargs):
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"DELETE FROM order_subscriptions WHERE {key}=?", (value,))
self.conn.commit()
logging.info(f"Order [{value}] deleted successfully!")
return True
except Error as e:
logging.error(f"Error while deleting order [{kwargs}] \n Error: {e}")
return False
def add_non_order_subscription(self, non_sub_id, telegram_id, uuid, server_id):
cur = self.conn.cursor()
try:
cur.execute(
"INSERT INTO non_order_subscriptions(id,telegram_id,uuid,server_id) VALUES(?,?,?,?)",
(non_sub_id, telegram_id, uuid, server_id))
self.conn.commit()
logging.info(f"Order [{telegram_id}] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding order [{telegram_id}] \n Error: {e}")
return False
def select_non_order_subscriptions(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM non_order_subscriptions")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all orders \n Error:{e}")
return None
def find_non_order_subscription(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find order!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM non_order_subscriptions WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Order {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding order {kwargs} \n Error:{e}")
return None
def delete_non_order_subscription(self, **kwargs):
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"DELETE FROM non_order_subscriptions WHERE {key}=?", (value,))
self.conn.commit()
logging.info(f"Order [{value}] deleted successfully!")
return True
except Error as e:
logging.error(f"Error while deleting order [{kwargs}] \n Error: {e}")
return False
def edit_bool_config(self, key_row, **kwargs):
cur = self.conn.cursor()
for key, value in kwargs.items():
try:
cur.execute(f"UPDATE bool_config SET {key}=? WHERE key=?", (value, key_row))
self.conn.commit()
logging.info(f"Settings [{key}] successfully update [{key}] to [{value}]")
except Error as e:
logging.error(f"Error while updating settings [{key}] [{key}] to [{value}] \n Error: {e}")
return False
return True
def find_bool_config(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find settings!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM bool_config WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Settings {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding settings {kwargs} \n Error:{e}")
return None
def add_bool_config(self, key, value):
cur = self.conn.cursor()
try:
cur.execute(
"INSERT or IGNORE INTO bool_config(key,value) VALUES(?,?)",
(key, value))
self.conn.commit()
logging.info(f"Settings [{key}] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding settings [{key}] \n Error: {e}")
return False
finally:
cur.close()
def select_bool_config(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM bool_config")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all settings \n Error:{e}")
return None
def select_str_config(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM str_config")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all settings \n Error:{e}")
return None
def find_str_config(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find settings!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM str_config WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Settings {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding settings {kwargs} \n Error:{e}")
return None
def edit_str_config(self, key_row, **kwargs):
cur = self.conn.cursor()
for key, value in kwargs.items():
try:
cur.execute(f"UPDATE str_config SET {key}=? WHERE key=?", (value, key_row))
self.conn.commit()
logging.info(f"Settings [{key}] successfully update [{key}] to [{value}]")
except Error as e:
logging.error(f"Error while updating settings [{key}] [{key}] to [{value}] \n Error: {e}")
return False
return True
def add_str_config(self, key, value):
cur = self.conn.cursor()
try:
cur.execute(
"INSERT or IGNORE INTO str_config(key,value) VALUES(?,?)",
(key, value))
self.conn.commit()
logging.info(f"Settings [{key}] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding settings [{key}] \n Error: {e}")
return False
finally:
cur.close()
def select_int_config(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM int_config")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all settings \n Error:{e}")
return None
def find_int_config(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find settings!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM int_config WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Settings {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding settings {kwargs} \n Error:{e}")
return None
def edit_int_config(self, key_row, **kwargs):
cur = self.conn.cursor()
for key, value in kwargs.items():
try:
cur.execute(f"UPDATE int_config SET {key}=? WHERE key=?", (value, key_row))
self.conn.commit()
logging.info(f"Settings [{key}] successfully update [{key}] to [{value}]")
except Error as e:
logging.error(f"Error while updating settings [{key}] [{key}] to [{value}] \n Error: {e}")
return False
return True
def add_int_config(self, key, value):
cur = self.conn.cursor()
try:
cur.execute(
"INSERT or IGNORE INTO int_config(key,value) VALUES(?,?)",
(key, value))
self.conn.commit()
logging.info(f"Settings [{key}] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding settings [{key}] \n Error: {e}")
return False
finally:
cur.close()
def set_default_configs(self):
self.add_bool_config("visible_hiddify_hyperlink", True)
self.add_bool_config("three_random_num_price", False)
self.add_bool_config("force_join_channel", False)
self.add_bool_config("panel_auto_backup", True)
self.add_bool_config("bot_auto_backup", True)
self.add_bool_config("test_subscription", True)
self.add_bool_config("reminder_notification", True)
self.add_bool_config("renewal_subscription_status", True)
self.add_bool_config("buy_subscription_status", True)
self.add_bool_config("visible_conf_dir", False)
self.add_bool_config("visible_conf_sub_auto", True)
self.add_bool_config("visible_conf_sub_url", False)
self.add_bool_config("visible_conf_sub_url_b64", False)
self.add_bool_config("visible_conf_clash", False)
self.add_bool_config("visible_conf_hiddify", False)
self.add_bool_config("visible_conf_sub_sing_box", False)
self.add_bool_config("visible_conf_sub_full_sing_box", False)
self.add_str_config("bot_admin_id", None)
self.add_str_config("bot_token_admin", None)
self.add_str_config("bot_token_client", None)
self.add_str_config("bot_lang", None)
self.add_str_config("card_number", None)
self.add_str_config("card_holder", None)
self.add_str_config("support_username", None)
self.add_str_config("channel_id", None)
self.add_str_config("msg_user_start", None)
self.add_str_config("msg_manual_android", None)
self.add_str_config("msg_manual_ios", None)
self.add_str_config("msg_manual_windows", None)
self.add_str_config("msg_manual_mac", None)
self.add_str_config("msg_manual_linux", None)
self.add_str_config("msg_faq", None)
self.add_int_config("min_deposit_amount", 10000)
self.add_int_config("reminder_notification_days", 3)
self.add_int_config("reminder_notification_usage", 3)
self.add_int_config("test_sub_days", 1)
self.add_int_config("test_sub_size_gb", 1)
self.add_int_config("advanced_renewal_days", 3)
self.add_int_config("advanced_renewal_usage", 3)
self.add_int_config("renewal_method", 1)
def add_wallet(self, telegram_id):
cur = self.conn.cursor()
try:
cur.execute(
"INSERT INTO wallet(telegram_id) VALUES(?)",
(telegram_id,))
self.conn.commit()
logging.info(f"Balance [{telegram_id}] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding balance [{telegram_id}] \n Error: {e}")
return False
def select_wallet(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM wallet")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all balance \n Error:{e}")
return None
def find_wallet(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find balance!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM wallet WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Balance {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding balance {kwargs} \n Error:{e}")
return None
def edit_wallet(self, telegram_id, **kwargs):
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"UPDATE wallet SET {key}=? WHERE telegram_id=?", (value, telegram_id,))
self.conn.commit()
logging.info(f"balance successfully update [{key}] to [{value}]")
return True
except Error as e:
logging.error(f"Error while updating balance [{key}] to [{value}] \n Error: {e}")
return False
def add_payment(self, payment_id, telegram_id, payment_amount, payment_method, payment_image, created_at):
cur = self.conn.cursor()
try:
cur.execute(
"INSERT INTO payments(id,telegram_id, payment_amount,payment_method,payment_image,created_at) VALUES(?,?,?,?,?,?)",
(payment_id, telegram_id, payment_amount, payment_method, payment_image, created_at))
self.conn.commit()
logging.info(f"Payment [{payment_id}] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding payment [{payment_id}] \n Error: {e}")
return False
def edit_payment(self, payment_id, **kwargs):
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"UPDATE payments SET {key}=? WHERE id=?", (value, payment_id))
self.conn.commit()
logging.info(f"payment successfully update [{key}] to [{value}]")
return True
except Error as e:
logging.error(f"Error while updating payment [{key}] to [{value}] \n Error: {e}")
return False
def find_payment(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find payment!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM payments WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Payment {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding payment {kwargs} \n Error:{e}")
return None
def select_payments(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM payments")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all payments \n Error:{e}")
return None
def select_servers(self):
cur = self.conn.cursor()
try:
cur.execute("SELECT * FROM servers")
rows = cur.fetchall()
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while selecting all servers \n Error:{e}")
return None
def add_server(self, url, user_limit, title=None, description=None, status=True, default_server=False):
cur = self.conn.cursor()
try:
cur.execute(
"INSERT INTO servers(url,title,description,user_limit,status,default_server) VALUES(?,?,?,?,?,?)",
(url, title, description, user_limit, status, default_server))
self.conn.commit()
logging.info(f"Server [{url}] added successfully!")
return True
except Error as e:
logging.error(f"Error while adding server [{url}] \n Error: {e}")
return False
def edit_server(self, server_id, **kwargs):
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"UPDATE servers SET {key}=? WHERE id=?", (value, server_id))
self.conn.commit()
logging.info(f"Server [{server_id}] successfully update [{key}] to [{value}]")
return True
except Error as e:
logging.error(f"Error while updating server [{server_id}] [{key}] to [{value}] \n Error: {e}")
return False
def find_server(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to find server!")
return None
rows = []
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"SELECT * FROM servers WHERE {key}=?", (value,))
rows = cur.fetchall()
if len(rows) == 0:
logging.info(f"Server {kwargs} not found!")
return None
rows = [dict(zip([key[0] for key in cur.description], row)) for row in rows]
return rows
except Error as e:
logging.error(f"Error while finding server {kwargs} \n Error:{e}")
return None
def delete_server(self, **kwargs):
if len(kwargs) != 1:
logging.warning("You can only use one key to delete server!")
return False
cur = self.conn.cursor()
try:
for key, value in kwargs.items():
cur.execute(f"DELETE FROM servers WHERE {key}=?", (value,))
self.conn.commit()
logging.info(f"server {kwargs} deleted successfully!")
return True
except Error as e:
logging.error(f"Error while deleting server {kwargs} \n Error:{e}")
return False
def backup_to_json(self, backup_dir):
try:
backup_data = {} # Store backup data in a dictionary
# List of tables to backup
tables = ['users', 'plans', 'orders', 'order_subscriptions', 'non_order_subscriptions',
'str_config', 'int_config', 'bool_config', 'wallet', 'payments', 'servers']
for table in tables:
cur = self.conn.cursor()
cur.execute(f"SELECT * FROM {table}")
rows = cur.fetchall()
# Convert rows to list of dictionaries
table_data = []
for row in rows:
columns = [column[0] for column in cur.description]
table_data.append(dict(zip(columns, row)))
backup_data[table] = table_data
return backup_data
except sqlite3.Error as e:
logging.error('SQLite error:', str(e))
return False
def restore_from_json(self, backup_file):
logging.info(f"Restoring database from {backup_file}...")
try:
cur = self.conn.cursor()
with open(backup_file, 'r') as json_file:
backup_data = json.load(json_file)
if not isinstance(backup_data, dict):
logging.error('Backup data should be a dictionary.')
print('Backup data should be a dictionary.')
return
# print(backup_data.get('version'), VERSION)
# if backup_data.get('version') != VERSION:
# if backup_data.get('version') is None:
# logging.error('Backup data version is not found.')
# print('Backup data version is not found.')
# return
# if VERSION.find('-pre'):
# VERSION = VERSION.split('-pre')[0]
# if is_version_less(backup_data.get('version'),VERSION ):
# logging.error('Backup data version is less than current version.')
# print('Backup data version is less than current version.')
# if is_version_less(backup_data.get('version'), '5.5.0'):
# logging.error('Backup data version is less than 5.5.0.')
# print('Backup data version is less than 5.5.0.')
# return
self.conn.execute('BEGIN TRANSACTION')
for table, data in backup_data.items():
if table == 'version':
continue
logging.info(f"Restoring table {table}...")
for entry in data:
if not isinstance(entry, dict):
logging.error('Invalid entry format. Expected a dictionary.')
print('Invalid entry format. Expected a dictionary.')
continue
keys = ', '.join(entry.keys())
placeholders = ', '.join(['?' for _ in entry.values()])
values = tuple(entry.values())
query = f"INSERT OR REPLACE INTO {table} ({keys}) VALUES ({placeholders})"
logging.info(f"Query: {query}")
try:
cur.execute(query, values)
except sqlite3.Error as e:
logging.error('SQLite error:', str(e))
logging.error('Entry:', entry)
print('SQLite error:', str(e))
print('Entry:', entry)
self.conn.commit()
logging.info('Database restored successfully.')
return True
except sqlite3.Error as e:
logging.error('SQLite error:', str(e))
return False
USERS_DB_LOC = os.path.join(os.getcwd(), "Database", "hidyBot.db")
USERS_DB = UserDBManager(USERS_DB_LOC)
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
-
-
-
#### ربات ادمین
-
-
-
-
-
-
-
-
================================================
FILE: README.md
================================================
English |
فارسی
Telegram Group
Commercial-Edition Documentation
-
-
-
#### Admin Bot
-
-
-
-
-
-
-
-
================================================
FILE: Shared/common.py
================================================
# Common file for avoiding circular import.
def admin_bot():
from AdminBot.bot import bot as admin_bot
return admin_bot
def user_bot():
from UserBot.bot import bot as user_bot
return user_bot
================================================
FILE: UserBot/Json/buttons.json
================================================
{
"EN": {
"BACK": "🔙Back",
"SUBSCRIPTION_STATUS": "📊Subscription Status",
"YES": "✅Yes",
"NO": "❌No",
"CONFIGS_DIR": "Configs",
"CONFIGS_SUB_AUTO": "Auto Subscription",
"CONFIGS_SUB": "Subscription Link",
"CONFIGS_SUB_B64": "Subscription Link b64",
"CONFIGS_CLASH": "Clash Subscription",
"CONFIGS_HIDDIFY": "Hiddify Subscription",
"CONFIGS_SING_BOX": "Sing-box",
"CONFIGS_FULL_SING_BOX": "Full Sing-box",
"UNLINK_SUBSCRIPTION": "⭕️Unlink Subscription",
"BUY_SUBSCRIPTION": "💳Buy Subscription",
"BUY_PLAN": "💳Card",
"BUY_FROM_WALLET": "💰From wallet",
"SEND_SCREENSHOT": "✅I paid, send receipt",
"CANCEL": "❌Cancel",
"CONFIRM_PAYMENT": "✅Confirm Payment",
"LINK_SUBSCRIPTION": "🔗Link Subscription",
"MANUAL": "📚Manual",
"MANUAL_ANDROID": "Android Manual",
"MANUAL_IOS": "IOS Manual",
"MANUAL_WIN": "Windows Manual",
"MANUAL_MAC": "Mac Manual",
"MANUAL_LIN": "Linux Manual",
"SEND_TICKET": "📩Supporter",
"SEND_TICKET_TO_SUPPORT": "📩Send Message To Support",
"ANSWER": "Answer",
"TO_QR": "ً🖼QR",
"CONFIGS_LIST": "📝Configs",
"WALLET": "💰Wallet",
"INCREASE_WALLET_BALANCE": "💵Increase wallet balance",
"FREE_TEST": "🔥Free Test",
"RENEWAL_SUBSCRIPTION": "🔄Renewal Subscription",
"UPDATE_SUBSCRIPTION_INFO": "🔄Update Subscription Info",
"JOIN_CHANNEL": "📢Join Channel",
"FORCE_JOIN_CHANNEL_ACCEPTED": "✅I joined",
"SEND_MESSAGE": "Send Message",
"FAQ": "⁉FAQ"
},
"FA": {
"BACK": "🔙بازگشت",
"SUBSCRIPTION_STATUS": "📊وضعیت اشتراک",
"YES": "✅بله",
"NO": "❌خیر",
"CONFIGS_DIR": "کانفیگ مستقیم",
"CONFIGS_SUB_AUTO": "اشتراک خودکار",
"CONFIGS_SUB": "لینک اشتراک",
"CONFIGS_SUB_B64": "لینک اشتراک b64",
"CONFIGS_CLASH": "اشتراک Clash",
"CONFIGS_HIDDIFY": "اشتراک Hiddify",
"CONFIGS_SING_BOX": "Sing-box",
"CONFIGS_FULL_SING_BOX": "Full Sing-box",
"UNLINK_SUBSCRIPTION": "⭕جداسازی اشتراک",
"BUY_SUBSCRIPTION": "💳خرید اشتراک",
"BUY_PLAN": "💳کارت به کارت",
"BUY_FROM_WALLET": "💰پرداخت از کیف پول",
"SEND_SCREENSHOT": "✅پرداخت کردم، ارسال رسید",
"CANCEL": "❌لغو",
"CONFIRM_PAYMENT": "✅تایید پرداخت",
"LINK_SUBSCRIPTION": "🔗اتصال اشتراک",
"MANUAL": "📚راهنما",
"MANUAL_ANDROID": "راهنمای اندروید",
"MANUAL_IOS": "راهنمای IOS",
"MANUAL_WIN": "راهنمای ویندوز",
"MANUAL_MAC": "راهنمای مک",
"MANUAL_LIN": "راهنمای لینوکس",
"SEND_TICKET": "📩پشتیبانی",
"SEND_TICKET_TO_SUPPORT": "📤 ارسال پیام به پشتیبانی",
"ANSWER": "📤پاسخ",
"TO_QR": "ً🖼کیوآر",
"CONFIGS_LIST": "📝 کانفیگ ها",
"WALLET": "💰کیف پول",
"INCREASE_WALLET_BALANCE": "💵افزایش موجودی",
"FREE_TEST": "🔥تست رایگان",
"RENEWAL_SUBSCRIPTION": "♾ تمدید اشتراک",
"UPDATE_SUBSCRIPTION_INFO": "🔄 بروزرسانی اطلاعات",
"JOIN_CHANNEL": "📢عضویت در کانال",
"FORCE_JOIN_CHANNEL_ACCEPTED": "✅عضو شدم",
"SEND_MESSAGE": "📤ارسال پیام",
"FAQ": "⁉سوالات متداول"
}
}
================================================
FILE: UserBot/Json/commands.json
================================================
{
"EN": {
"START": "start"
},
"FA": {
"START": "شروع"
}
}
================================================
FILE: UserBot/Json/messages.json
================================================
{
"EN": {
"WELCOME": "Welcome to users bot",
"INFO_USER": "📄Your Subscription Info",
"SUBSCRIPTION_STATUS": "☑️Status:",
"ACTIVE_SUBSCRIPTION_STATUS": "🟢 Active",
"DEACTIVE_SUBSCRIPTION_STATUS": "🔴 Deactive",
"SERVER": "📡Server:",
"INFO_USAGE": "📊Usage:",
"INFO_REMAINING_DAYS": "⏳Remaining Days:",
"INFO_ID": "🔑UUID:",
"OF": "of",
"GB": "GB",
"DAY_EXPIRE": "Days",
"CONFIRM_SUBSCRIPTION_QUESTION": "Is this your subscription?",
"NAME": "Name:",
"CANCEL_SUBSCRIPTION": "Subscription not confirmed",
"SUBSCRIPTION_CONFIRMED": "Your subscription has been confirmed. Now you can get your subscription status.",
"WAIT": "Please wait...",
"UNKNOWN_ERROR": "Unknown error!",
"ENTER_SUBSCRIPTION_INFO": "Please enter your subscription info\n One of the configs, uuid or subscription link",
"SUBSCRIPTION_INFO_NOT_FOUND": "Subscription info not found!",
"SUBSCRIPTION_UNLINKED": "Subscription unlinked!",
"USER_NOT_FOUND": "User not found!",
"USER_NAME": "👤Name:",
"PLANS_LIST": "📋Plans List:",
"SERVERS_LIST": "🖥Server List:",
"PLANS_NOT_FOUND": "Plans not found!",
"SERVERS_NOT_FOUND": "Servers not found!",
"PLAN_ADD_NAME": "Please enter your name:",
"SUBSCRIPTION_SUCCESS_ADDED": "Your subscription has been successfully added.",
"PLAN_INFO": "📄Plan Info:",
"PLAN_INFO_SIZE": "Size:",
"PLAN_INFO_DAYS": "Days:",
"PLAN_INFO_PRICE": "Price:",
"PLAN_INFO_DESC": "Description:",
"TOMAN": "T",
"RIAL": "R",
"REQUEST_SEND_SCREENSHOT": "Please send your payment receipt.",
"ERROR_TYPE_SEND_SCREENSHOT": "Please send your payment receipt as a photo!",
"REQUEST_SEND_NAME": "Please send your name.",
"NO_SUBSCRIPTION": "You have no subscription!",
"WAIT_FOR_ADMIN_CONFIRMATION": "✅Your subscription is waiting for confirmation by the admin.\nPlease wait...",
"NEW_PAYMENT_RECEIVED": "New payment received",
"PAYMENT_ASK_TO_CONFIRM": "Do you want to confirm this payment?",
"REQUEST_SEND_TO_QR": "Please send your config or subscription link:",
"REQUEST_SEND_TO_QR_ERROR": "Please send your config or subscription!",
"USER_CONFIGS_LIST": "📋Your Configs:",
"USER_CONFIGS_NOT_FOUND": "Configs not found!",
"ERROR_CONFIG_NOT_FOUND": "Config not found!",
"ERROR_INVALID_COMMAND": "Invalid command!",
"ALREADY_SUBSCRIBED": "You are already subscribed!",
"ERROR_INVALID_NUMBER": "Invalid number!",
"CANCELED": "Cancelled!",
"SUBSCRIPTION_NOT_FOUND": "Subscription not found!",
"ZERO_BALANCE": "🔻Your wallet balance is zero",
"WALLET_INFO_PART_1": "🔻Your wallet balance is",
"WALLET_INFO_PART_2": "",
"INCREASE_WALLET_BALANCE_AMOUNT": "🔻Please enter the amount that you want to charge your wallet in Tomans",
"MINIMUM_DEPOSIT_AMOUNT": "🔻Please enter an amount more than",
"LACK_OF_WALLET_BALANCE": "❌Your wallet balance is not enough\nplease top up your wallet",
"ORDER_ID": "Payment number:",
"PAYMENT_CONFIRMED": "✅Payment confirmed",
"ALREADY_RECEIVED_FREE": "You have already received your free test account!",
"GET_FREE_CONFIRMED": "✅Your free account has been successfully registered",
"SUCCESSFUL_RENEWAL": "✅Your subscription has been successfully renewed",
"REQUEST_START": "Please update the bot with /start command",
"CANCEL_INCREASE_WALLET_BALANCE": "❌Increase balance not confirmed",
"REQUEST_JOIN_CHANNEL": "Please join our channel to use the bot",
"ADMIN_NOTIFY_NEW_SUB" : "A new subscription was registered with the name of:",
"ADMIN_NOTIFY_CONFIRM" : "",
"ADMIN_NOTIFY_NEW_FREE_TEST" : "A new free tesst subscription was registered with the name of:",
"ADMIN_NOTIFY_NEW_RENEWAL" : "",
"ADMIN_NOTIFY_NEW_RENEWAL_2" : "subscription was extended",
"FREE_TEST_NOT_AVAILABLE" : "Free test is not available at the moment",
"REQUEST_SELECT_OS_MANUAL": "📥Please select your operating system:",
"MANUAL_ANDROID": "\uD83D\uDCE5Android:\nV2RayNG\nHiddifyNG",
"MANUAL_IOS": "\uD83D\uDCE5iOS:\nStreisand\nFoxray\nV2box",
"MANUAL_WIN": "\uD83D\uDCE5Windows:\nNekoray\nV2rayN\nHiddifyN",
"MANUAL_LIN": "📥Linux:Nekoray",
"MANUAL_MAC": "📥Mac:Nekoray",
"MANUAL_HDR": "⭕Connection Guide",
"WELCOME_TO_ADMIN": "Users bot has been successfully launched.\nPlease send /start command to start working.",
"BUY_SUBSCRIPTION_CLOSED": "Buy subscription is not available at the moment.",
"RENEWAL_SUBSCRIPTION_CLOSED": "Renewal subscription is not available at the moment.",
"INFO_USER_NAME": "⬖ User:",
"INFO_USER_USERNAME": "⬖ Username:",
"INFO_USER_NUM_ID": "⬖ User ID:",
"ANSWER_TO_ADMIN": "Please submit your answer:",
"MESSAGE_SENDED": "Message Sended",
"NOT_SET":"Not set",
"JOIN_CHANNEL_SUCCESSFUL":"Join channel successful",
"SEND_TICKET_TO_ADMIN": "Please submit your question:",
"SEND_TICKET_TO_ADMIN_RESPONSE": "✅Your message has been sent to support\n⏳We will respond as soon as possible.",
"SEND_TICKET_TO_ADMIN_TEMPLATE":"Do you have any questions?\nContact us.",
"NEW_TICKET_RECEIVED": "📩New ticket received",
"TICKET_TEXT": "📄Ticket text:",
"SERVER_IS_FULL": "⛔️The capacity of the selected server is full\nPlease select another server\nWe will try to increase the capacity of the servers as soon as possible",
"BANNED_USER": "⛔️You are banned from using the bot"
},
"FA": {
"WELCOME": "به ربات کاربران خوش آمدید",
"INFO_USER": "📄اطلاعات اشتراک شما",
"SUBSCRIPTION_STATUS": "❔وضعیت:",
"ACTIVE_SUBSCRIPTION_STATUS": "🟢 فعال",
"DEACTIVE_SUBSCRIPTION_STATUS": "🔴 غیر فعال",
"SERVER": "📡سرور:",
"INFO_USAGE": "📊میزان استفاده:",
"INFO_REMAINING_DAYS": "⏳زمان باقی مانده:",
"INFO_ID": "🔑شناسه:",
"OF": "از",
"GB": "گیگ",
"DAY_EXPIRE": "روز",
"CONFIRM_SUBSCRIPTION_QUESTION": "آیا این اشتراک شماست؟",
"NAME": "نام:",
"CANCEL_SUBSCRIPTION": "❌اشتراک تایید نشد",
"SUBSCRIPTION_CONFIRMED": "✅اشتراک شما تایید شد. حالا میتوانید وضعیت اشتراک خود را دریافت کنید.",
"WAIT": "لطفا صبر کنید...",
"UNKNOWN_ERROR": "❌خطای ناشناخته!",
"ENTER_SUBSCRIPTION_INFO": "لطفا اطلاعات اشتراک خود را وارد کنید.\nیکی از کانفیگ ها، uuid یا لینک اشتراک⬇️",
"SUBSCRIPTION_INFO_NOT_FOUND": "❌اطلاعات اشتراک یافت نشد!",
"USER_NOT_FOUND": "❌کاربر یافت نشد.",
"SUBSCRIPTION_UNLINKED": "✅اشتراک از ربات جداسازی شد",
"USER_NAME": "👤نام:",
"PLANS_LIST": "📋پلن های موجود",
"SERVERS_LIST": "📡لیست سرورها",
"PLANS_NOT_FOUND": "❌پلنی یافت نشد!",
"SERVERS_NOT_FOUND": "❌سروری یافت نشد!",
"PLAN_ADD_NAME": "لطفا نام خود را وارد کنید:",
"SUBSCRIPTION_SUCCESS_ADDED": "✅اشتراک شما با موفقیت اضافه شد.",
"PLAN_INFO": "📋اطلاعات پلن انتخاب شده",
"PLAN_INFO_SIZE": "📊حجم:",
"PLAN_INFO_PRICE": "💰قیمت:",
"PLAN_INFO_DAYS": "📆زمان:",
"PLAN_INFO_DESC": "✏️توضیحات:",
"TOMAN": "تومان",
"RIAL": "ریال",
"REQUEST_SEND_SCREENSHOT": "⬇️لطفا رسید پرداخت خود را در زیر این پیام ارسال کنید:",
"ERROR_TYPE_SEND_SCREENSHOT": "⬇️لطفا رسید پرداخت خود را به صورت عکس ارسال کنید:",
"REQUEST_SEND_NAME": "⬇️لطفا نام خود را ارسال کنید:",
"NO_SUBSCRIPTION": "❌شما هیچ اشتراکی ندارید!",
"WAIT_FOR_ADMIN_CONFIRMATION": "✅تراکنش شما در انتظار تایید توسط ادمین است.\nلطفا صبر کنید.",
"NEW_PAYMENT_RECEIVED": "تراکنش جدیدی ثبت شد",
"PAYMENT_ASK_TO_CONFIRM": "آیا شما این تراکنش را تایید میکنید؟",
"REQUEST_SEND_TO_QR": "لطفا کانفیگ یا لینک اشتراک خود را ارسال کنید:",
"REQUEST_SEND_TO_QR_ERROR": "متن ارسالی معتبر نیست\nلطفا کانفیگ یا لینک اشتراک خود را به صورت متنی ارسال کنید!",
"USER_CONFIGS_LIST": "📋لیست کانفیگ های شما",
"USER_CONFIGS_NOT_FOUND": "❌کانفیگی یافت نشد!",
"ERROR_CONFIG_NOT_FOUND": "❌کانفیگ یافت نشد!",
"ERROR_INVALID_COMMAND": "❌دستور نامعتبر!",
"ALREADY_SUBSCRIBED": "❌اشتراک شما قبلا اضافه شده است.",
"ERROR_INVALID_NUMBER": "❌لطفا مقداری عددی وارد کنید!",
"CANCELED": "❌لغو شد",
"SUBSCRIPTION_NOT_FOUND": "❌شما اشتراک فعالی ندارید!",
"ZERO_BALANCE": "🔻موجودی کیف پول شما صفر میباشد",
"WALLET_INFO_PART_1": "🔻موجودی کیف پول شما",
"WALLET_INFO_PART_2": "تومان میباشد",
"INCREASE_WALLET_BALANCE_AMOUNT": "🔻لطفا مبلغی که قصد شارژ حساب خود دارید را به تومان وارد کنید",
"MINIMUM_DEPOSIT_AMOUNT": "❗حداقل مبلغ شارژ حساب",
"LACK_OF_WALLET_BALANCE": "❌موجودی کیف پول شما کافی نیست\n⬇️لطفا از طریق دکمه زیر کیف پول خود را شارژ کنید و سپس پرداخت را انجام دهید",
"ORDER_ID": "شناسه تراکنش",
"PAYMENT_CONFIRMED": "تراکنش شما تایید شد\n از طریق دکمه [📊وضعیت اشتراک] میتوانید به اطلاعات اشتراک خود دسترسی داشته باشید.",
"ALREADY_RECEIVED_FREE": "شما قبلا اکانت تست رایگان خود را دریافت نمودهاید!",
"GET_FREE_CONFIRMED": "✅اکانت تست رایگان شما با موفقیت ثبت شد\n از طریق دکمه [📊وضعیت اشتراک] میتوانید به اطلاعات اشتراک خود دسترسی داشته باشید.",
"SUCCESSFUL_RENEWAL": "✅تمدید اشتراک شما با موفقیت انجام شد",
"REQUEST_START": "لطفا ربات را با دستور /start شروع کنید",
"CANCEL_INCREASE_WALLET_BALANCE": "❌افزایش موجودی لغو شد",
"REQUEST_JOIN_CHANNEL": "لطفا برای استفاده از ربات ابتدا در کانال ما عضو شوید",
"ADMIN_NOTIFY_NEW_SUB" : "👤اشتراک جدیدی با نام",
"ADMIN_NOTIFY_CONFIRM" : "ثبت شد",
"ADMIN_NOTIFY_NEW_FREE_TEST" : "اشتراک تست رایگان جدیدی با نام",
"ADMIN_NOTIFY_NEW_RENEWAL_2" : "تمدید شد",
"ADMIN_NOTIFY_NEW_RENEWAL" : "اشتراک",
"FREE_TEST_NOT_AVAILABLE" : "اکانت تست رایگان در حال حاضر در دسترس نمیباشد",
"REQUEST_SELECT_OS_MANUAL": "📥لطفا سیستم عامل خود را انتخاب کنید:",
"MANUAL_ANDROID": "\uD83D\uDCE5Android:\nV2RayNG\nHiddifyNG",
"MANUAL_IOS": "\uD83D\uDCE5iOS:\nStreisand\nFoxray\nV2box",
"MANUAL_WIN": "\uD83D\uDCE5Windows:\nNekoray\nV2rayN\nHiddifyN",
"MANUAL_LIN": "📥Linux:\nNekoray",
"MANUAL_MAC": "📥Mac:\nNekoray",
"MANUAL_HDR": "لطفا سیستم عامل خود را انتخاب کنید",
"WELCOME_TO_ADMIN": "ربات کاربران هیدی بات با موفقیت راهاندازی شد.\nبرای شروع کار، دستور /start را ارسال کنید.",
"BUY_SUBSCRIPTION_CLOSED": "در حال حاضر امکان خرید اشتراک وجود ندارد.",
"RENEWAL_SUBSCRIPTION_CLOSED": "در حال حاضر امکان تمدید اشتراک وجود ندارد.",
"INFO_USER_NAME": "⬖ کاربر:",
"INFO_USER_USERNAME": "⬖ نام کاربری:",
"INFO_USER_NUM_ID": "⬖ شناسه کاربر:",
"ANSWER_TO_ADMIN": "لطفا پاسخ خود را ارسال کنید:",
"MESSAGE_SENDED": "پیام ارسال شد",
"NOT_SET": "تنظیم نشده",
"JOIN_CHANNEL_SUCCESSFUL": "✅عضویت شما در کانال با موفقیت انجام شد",
"SEND_TICKET_TO_ADMIN": "📞لطفا سوال یا موضوع مورد بحث را در قالب یک پیام کامل و جامع ارسال کنید:",
"SEND_TICKET_TO_ADMIN_RESPONSE": "✅ پیام شما با موفقیت برای پشتیبانی ارسال شد\n⏳ما در سریع ترین زمان ممکن پاسخگو خواهیم بود.",
"SEND_TICKET_TO_ADMIN_TEMPLATE":"نیاز به پشتیبانی دارید؟\nبا ما در ارتباط باشید.",
"NEW_TICKET_RECEIVED": "📩تیکت جدیدی دریافت شد",
"TICKET_TEXT": "📄متن تیکت:",
"SERVER_IS_FULL": "⛔️ظرفیت سرور انتخاب شده تکمیل شده\nلطفا سرور دیگری انتخاب کنید\nسعی ما بر این است که در اسرع وقت ظرفیت سرورها را افزایش دهیم",
"BANNED_USER": "⛔️شما از استفاده از ربات محروم شدهاید"
}
}
================================================
FILE: UserBot/bot.py
================================================
import datetime
import random
import telebot
from telebot.types import Message, CallbackQuery
from config import *
from AdminBot.templates import configs_template
from UserBot.markups import *
from UserBot.templates import *
from UserBot.content import *
import Utils.utils as utils
from Shared.common import admin_bot
from Database.dbManager import USERS_DB
from Utils import api
# *********************************** Configuration Bot ***********************************
bot = telebot.TeleBot(CLIENT_TOKEN, parse_mode="HTML")
bot.remove_webhook()
admin_bot = admin_bot()
BASE_URL = f"{urlparse(PANEL_URL).scheme}://{urlparse(PANEL_URL).netloc}"
selected_server_id = 0
# *********************************** Helper Functions ***********************************
# Check if message is digit
def is_it_digit(message: Message,allow_float=False, response=MESSAGES['ERROR_INVALID_NUMBER'], markup=main_menu_keyboard_markup()):
if not message.text:
bot.send_message(message.chat.id, response, reply_markup=markup)
return False
try:
value = float(message.text) if allow_float else int(message.text)
return True
except ValueError:
bot.send_message(message.chat.id, response, reply_markup=markup)
return False
# Check if message is cancel
def is_it_cancel(message: Message, response=MESSAGES['CANCELED']):
if message.text == KEY_MARKUP['CANCEL']:
bot.send_message(message.chat.id, response, reply_markup=main_menu_keyboard_markup())
return True
return False
# Check if message is command
def is_it_command(message: Message):
if message.text.startswith("/"):
return True
return False
# Check is it UUID, Config or Subscription Link
def type_of_subscription(text):
if text.startswith("vmess://"):
config = text.replace("vmess://", "")
config = utils.base64decoder(config)
if not config:
return False
uuid = config['id']
else:
uuid = utils.extract_uuid_from_config(text)
return uuid
# check is user banned
def is_user_banned(user_id):
user = USERS_DB.find_user(telegram_id=user_id)
if user:
user = user[0]
if user['banned']:
bot.send_message(user_id, MESSAGES['BANNED_USER'], reply_markup=main_menu_keyboard_markup())
return True
return False
# *********************************** Next-Step Handlers ***********************************
# ----------------------------------- Buy Plan Area -----------------------------------
charge_wallet = {}
renew_subscription_dict = {}
def user_channel_status(user_id):
try:
settings = utils.all_configs_settings()
if settings['channel_id']:
user = bot.get_chat_member(settings['channel_id'], user_id)
return user.status in ['member', 'administrator', 'creator']
else:
return True
except telebot.apihelper.ApiException as e:
logging.error("ApiException: %s" % e)
return False
def is_user_in_channel(user_id):
settings = all_configs_settings()
if settings['force_join_channel'] == 1:
if not settings['channel_id']:
return True
if not user_channel_status(user_id):
bot.send_message(user_id, MESSAGES['REQUEST_JOIN_CHANNEL'],
reply_markup=force_join_channel_markup(settings['channel_id']))
return False
return True
# Next Step Buy From Wallet - Confirm
def buy_from_wallet_confirm(message: Message, plan):
if not plan:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
wallet = USERS_DB.find_wallet(telegram_id=message.chat.id)
if not wallet:
# Wallet not created
bot.send_message(message.chat.id, MESSAGES['LACK_OF_WALLET_BALANCE'],
reply_markup=wallet_info_markup())
if wallet:
wallet = wallet[0]
if plan['price'] > wallet['balance']:
bot.send_message(message.chat.id, MESSAGES['LACK_OF_WALLET_BALANCE'],
reply_markup=wallet_info_specific_markup(plan['price'] - wallet['balance']))
return
else:
bot.delete_message(message.chat.id, message.message_id)
bot.send_message(message.chat.id, MESSAGES['REQUEST_SEND_NAME'], reply_markup=cancel_markup())
bot.register_next_step_handler(message, next_step_send_name_for_buy_from_wallet, plan)
def renewal_from_wallet_confirm(message: Message):
if not renew_subscription_dict:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
if not renew_subscription_dict[message.chat.id]:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
if not renew_subscription_dict[message.chat.id]['plan_id'] or not renew_subscription_dict[message.chat.id][
'uuid']:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
uuid = renew_subscription_dict[message.chat.id]['uuid']
plan_id = renew_subscription_dict[message.chat.id]['plan_id']
wallet = USERS_DB.find_wallet(telegram_id=message.chat.id)
if not wallet:
status = USERS_DB.add_wallet(telegram_id=message.chat.id)
if not status:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
wallet = wallet[0]
plan_info = USERS_DB.find_plan(id=plan_id)
if not plan_info:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
plan_info = plan_info[0]
if plan_info['price'] > wallet['balance']:
bot.send_message(message.chat.id, MESSAGES['LACK_OF_WALLET_BALANCE'],reply_markup=wallet_info_specific_markup(plan_info['price'] - wallet['balance']))
del renew_subscription_dict[message.chat.id]
return
server_id = plan_info['server_id']
server = USERS_DB.find_server(id=server_id)
if not server:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
server = server[0]
URL = server['url'] + API_PATH
user = api.find(URL, uuid=uuid)
if not user:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
user_info = utils.users_to_dict([user])
if not user_info:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
user_info_process = utils.dict_process(URL, user_info)
user_info = user_info[0]
if not user_info_process:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
user_info_process = user_info_process[0]
new_balance = int(wallet['balance']) - int(plan_info['price'])
edit_wallet = USERS_DB.edit_wallet(message.chat.id, balance=new_balance)
if not edit_wallet:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
last_reset_time = datetime.datetime.now().strftime("%Y-%m-%d")
sub = utils.find_order_subscription_by_uuid(uuid)
if not sub:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
settings = utils.all_configs_settings()
#Default renewal mode
if settings['renewal_method'] == 1:
if user_info_process['remaining_day'] <= 0 or user_info_process['usage']['remaining_usage_GB'] <= 0:
new_usage_limit = plan_info['size_gb']
new_package_days = plan_info['days']
current_usage_GB = 0
edit_status = api.update(URL, uuid=uuid, usage_limit_GB=new_usage_limit, package_days=new_package_days,start_date=last_reset_time, current_usage_GB=current_usage_GB,comment=f"HidyBot:{sub['id']}")
else:
new_usage_limit = user_info['usage_limit_GB'] + plan_info['size_gb']
new_package_days = plan_info['days'] + (user_info['package_days'] - user_info_process['remaining_day'])
edit_status = api.update(URL, uuid=uuid, usage_limit_GB=new_usage_limit, package_days=new_package_days,last_reset_time=last_reset_time,comment=f"HidyBot:{sub['id']}")
#advance renewal mode
elif settings['renewal_method'] == 2:
new_usage_limit = plan_info['size_gb']
new_package_days = plan_info['days']
current_usage_GB = 0
edit_status = api.update(URL, uuid=uuid, usage_limit_GB=new_usage_limit, start_date=last_reset_time, package_days=new_package_days, current_usage_GB=current_usage_GB,comment=f"HidyBot:{sub['id']}")
#Fair renewal mode
elif settings['renewal_method'] == 3:
if user_info_process['remaining_day'] <= 0 or user_info_process['usage']['remaining_usage_GB'] <= 0:
new_usage_limit = plan_info['size_gb']
new_package_days = plan_info['days']
current_usage_GB = 0
edit_status = api.update(URL, uuid=uuid, usage_limit_GB=new_usage_limit, package_days=new_package_days,start_date=last_reset_time, current_usage_GB=current_usage_GB,comment=f"HidyBot:{sub['id']}")
else:
print(user_info)
new_usage_limit = user_info['usage_limit_GB'] + plan_info['size_gb']
new_package_days = plan_info['days'] + user_info['package_days']
edit_status = api.update(URL, uuid=uuid, usage_limit_GB=new_usage_limit,package_days=new_package_days,last_reset_time=last_reset_time,comment=f"HidyBot:{sub['id']}")
if not edit_status:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
# Add New Order
order_id = random.randint(1000000, 9999999)
created_at = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
status = USERS_DB.add_order(order_id, message.chat.id,user_info_process['name'], plan_id, created_at)
if not status:
bot.send_message(message.chat.id,
f"{MESSAGES['UNKNOWN_ERROR']}\n{MESSAGES['ORDER_ID']} {order_id}",
reply_markup=main_menu_keyboard_markup())
return
# edit_status = ADMIN_DB.edit_user(uuid=uuid, usage_limit_GB=new_usage_limit, package_days=new_package_days)
# edit_status = api.update(URL, uuid=uuid, usage_limit_GB=new_usage_limit, package_days=new_package_days)
# if not edit_status:
# bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
# reply_markup=main_menu_keyboard_markup())
# return
bot.send_message(message.chat.id, MESSAGES['SUCCESSFUL_RENEWAL'], reply_markup=main_menu_keyboard_markup())
update_info_subscription(message, uuid)
BASE_URL = urlparse(server['url']).scheme + "://" + urlparse(server['url']).netloc
link = f"{BASE_URL}/{urlparse(server['url']).path.split('/')[1]}/{uuid}/"
user_name = f" {user_info_process['name']} "
bot_users = USERS_DB.find_user(telegram_id=message.chat.id)
if bot_users:
bot_user = bot_users[0]
for ADMIN in ADMINS_ID:
admin_bot.send_message(ADMIN,
f"""{MESSAGES['ADMIN_NOTIFY_NEW_RENEWAL']} {user_name} {MESSAGES['ADMIN_NOTIFY_NEW_RENEWAL_2']}
{MESSAGES['SERVER']} {server['title']}
{MESSAGES['INFO_ID']} {sub['id']}""", reply_markup=notify_to_admin_markup(bot_user))
# Next Step Buy Plan - Send Screenshot
def next_step_send_screenshot(message, charge_wallet):
if is_it_cancel(message):
return
if not charge_wallet:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
if message.content_type != 'photo':
bot.send_message(message.chat.id, MESSAGES['ERROR_TYPE_SEND_SCREENSHOT'], reply_markup=cancel_markup())
bot.register_next_step_handler(message, next_step_send_screenshot, charge_wallet)
return
file_info = bot.get_file(message.photo[-1].file_id)
downloaded_file = bot.download_file(file_info.file_path)
file_name = f"{message.chat.id}-{charge_wallet['id']}.jpg"
path_recp = os.path.join(os.getcwd(), 'UserBot', 'Receiptions', file_name)
if not os.path.exists(os.path.join(os.getcwd(), 'UserBot', 'Receiptions')):
os.makedirs(os.path.join(os.getcwd(), 'UserBot', 'Receiptions'))
with open(path_recp, 'wb') as new_file:
new_file.write(downloaded_file)
created_at = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
payment_method = "Card"
status = USERS_DB.add_payment(charge_wallet['id'], message.chat.id,
charge_wallet['amount'], payment_method, file_name, created_at)
if status:
payment = USERS_DB.find_payment(id=charge_wallet['id'])
if not payment:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
payment = payment[0]
user_data = USERS_DB.find_user(telegram_id=message.chat.id)
if not user_data:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
user_data = user_data[0]
for ADMIN in ADMINS_ID:
admin_bot.send_photo(ADMIN, open(path_recp, 'rb'),
caption=payment_received_template(payment,user_data),
reply_markup=confirm_payment_by_admin(charge_wallet['id']))
bot.send_message(message.chat.id, MESSAGES['WAIT_FOR_ADMIN_CONFIRMATION'],
reply_markup=main_menu_keyboard_markup())
else:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
# Next Step Payment - Send Answer
def next_step_answer_to_admin(message, admin_id):
if is_it_cancel(message):
return
bot_users = USERS_DB.find_user(telegram_id=message.chat.id)
if bot_users:
bot_user = bot_users[0]
admin_bot.send_message(int(admin_id), f"{MESSAGES['NEW_TICKET_RECEIVED']}\n{MESSAGES['TICKET_TEXT']} {message.text}",
reply_markup=answer_to_user_markup(bot_user,message.chat.id))
bot.send_message(message.chat.id, MESSAGES['SEND_TICKET_TO_ADMIN_RESPONSE'],
reply_markup=main_menu_keyboard_markup())
# Next Step Payment - Send Ticket To Admin
def next_step_send_ticket_to_admin(message):
if is_it_cancel(message):
return
bot_users = USERS_DB.find_user(telegram_id=message.chat.id)
if bot_users:
bot_user = bot_users[0]
for ADMIN in ADMINS_ID:
admin_bot.send_message(ADMIN, f"{MESSAGES['NEW_TICKET_RECEIVED']}\n{MESSAGES['TICKET_TEXT']} {message.text}",
reply_markup=answer_to_user_markup(bot_user,message.chat.id))
bot.send_message(message.chat.id, MESSAGES['SEND_TICKET_TO_ADMIN_RESPONSE'],
reply_markup=main_menu_keyboard_markup())
# ----------------------------------- Buy From Wallet Area -----------------------------------
# Next Step Buy From Wallet - Send Name
def next_step_send_name_for_buy_from_wallet(message: Message, plan):
if is_it_cancel(message):
return
if not plan:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
name = message.text
while is_it_command(message):
message = bot.send_message(message.chat.id, MESSAGES['REQUEST_SEND_NAME'])
bot.register_next_step_handler(message, next_step_send_name_for_buy_from_wallet, plan)
return
created_at = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
paid_amount = plan['price']
order_id = random.randint(1000000, 9999999)
server_id = plan['server_id']
server = USERS_DB.find_server(id=server_id)
if not server:
bot.send_message(message.chat.id, f"{MESSAGES['UNKNOWN_ERROR']}:Server Not Found",
reply_markup=main_menu_keyboard_markup())
return
server = server[0]
URL = server['url'] + API_PATH
# value = ADMIN_DB.add_default_user(name, plan['days'], plan['size_gb'],)
sub_id = random.randint(1000000, 9999999)
value = api.insert(URL, name=name, usage_limit_GB=plan['size_gb'], package_days=plan['days'],comment=f"HidyBot:{sub_id}")
if not value:
bot.send_message(message.chat.id,
f"{MESSAGES['UNKNOWN_ERROR']}:Create User Error\n{MESSAGES['ORDER_ID']} {order_id}",
reply_markup=main_menu_keyboard_markup())
return
add_sub_status = USERS_DB.add_order_subscription(sub_id, order_id, value, server_id)
if not add_sub_status:
bot.send_message(message.chat.id,
f"{MESSAGES['UNKNOWN_ERROR']}:Add Subscription Error\n{MESSAGES['ORDER_ID']} {order_id}",
reply_markup=main_menu_keyboard_markup())
return
status = USERS_DB.add_order(order_id, message.chat.id,name, plan['id'], created_at)
if not status:
bot.send_message(message.chat.id,
f"{MESSAGES['UNKNOWN_ERROR']}:Add Order Error\n{MESSAGES['ORDER_ID']} {order_id}",
reply_markup=main_menu_keyboard_markup())
return
wallet = USERS_DB.find_wallet(telegram_id=message.chat.id)
if wallet:
wallet = wallet[0]
wallet_balance = int(wallet['balance']) - int(paid_amount)
user_info = USERS_DB.edit_wallet(message.chat.id, balance=wallet_balance)
if not user_info:
bot.send_message(message.chat.id,
f"{MESSAGES['UNKNOWN_ERROR']}:Edit Wallet Balance Error\n{MESSAGES['ORDER_ID']} {order_id}",
reply_markup=main_menu_keyboard_markup())
return
bot.send_message(message.chat.id,
f"{MESSAGES['PAYMENT_CONFIRMED']}\n{MESSAGES['ORDER_ID']} {order_id}",
reply_markup=main_menu_keyboard_markup())
user_info = api.find(URL, value)
user_info = utils.users_to_dict([user_info])
user_info = utils.dict_process(URL, user_info)
user_info = user_info[0]
api_user_data = user_info_template(sub_id, server, user_info, MESSAGES['INFO_USER'])
bot.send_message(message.chat.id, api_user_data,
reply_markup=user_info_markup(user_info['uuid']))
BASE_URL = urlparse(server['url']).scheme + "://" + urlparse(server['url']).netloc
link = f"{BASE_URL}/{urlparse(server['url']).path.split('/')[1]}/{value}/"
user_name = f" {name} "
bot_users = USERS_DB.find_user(telegram_id=message.chat.id)
if bot_users:
bot_user = bot_users[0]
for ADMIN in ADMINS_ID:
admin_bot.send_message(ADMIN,
f"""{MESSAGES['ADMIN_NOTIFY_NEW_SUB']} {user_name} {MESSAGES['ADMIN_NOTIFY_CONFIRM']}
{MESSAGES['SERVER']} {server['title']}
{MESSAGES['INFO_ID']} {sub_id}""", reply_markup=notify_to_admin_markup(bot_user))
# ----------------------------------- Get Free Test Area -----------------------------------
# Next Step Get Free Test - Send Name
def next_step_send_name_for_get_free_test(message: Message, server_id):
if is_it_cancel(message):
return
name = message.text
while is_it_command(message):
message = bot.send_message(message.chat.id, MESSAGES['REQUEST_SEND_NAME'])
bot.register_next_step_handler(message, next_step_send_name_for_get_free_test)
return
settings = utils.all_configs_settings()
test_user_comment = "HidyBot:FreeTest"
server = USERS_DB.find_server(id=server_id)
if not server:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
server = server[0]
URL = server['url'] + API_PATH
# uuid = ADMIN_DB.add_default_user(name, test_user_days, test_user_size_gb, int(PANEL_ADMIN_ID), test_user_comment)
uuid = api.insert(URL, name=name, usage_limit_GB=settings['test_sub_size_gb'], package_days=settings['test_sub_days'],
comment=test_user_comment)
if not uuid:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
non_order_id = random.randint(10000000, 99999999)
non_order_status = USERS_DB.add_non_order_subscription(non_order_id, message.chat.id, uuid, server_id)
if not non_order_status:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
edit_user_status = USERS_DB.edit_user(message.chat.id, test_subscription=True)
if not edit_user_status:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['GET_FREE_CONFIRMED'],
reply_markup=main_menu_keyboard_markup())
user_info = api.find(URL, uuid)
user_info = utils.users_to_dict([user_info])
user_info = utils.dict_process(URL, user_info)
user_info = user_info[0]
api_user_data = user_info_template(non_order_id, server, user_info, MESSAGES['INFO_USER'])
bot.send_message(message.chat.id, api_user_data,
reply_markup=user_info_markup(user_info['uuid']))
BASE_URL = urlparse(server['url']).scheme + "://" + urlparse(server['url']).netloc
link = f"{BASE_URL}/{urlparse(server['url']).path.split('/')[1]}/{uuid}/"
user_name = f" {name} "
bot_users = USERS_DB.find_user(telegram_id=message.chat.id)
if bot_users:
bot_user = bot_users[0]
for ADMIN in ADMINS_ID:
admin_bot.send_message(ADMIN,
f"""{MESSAGES['ADMIN_NOTIFY_NEW_FREE_TEST']} {user_name} {MESSAGES['ADMIN_NOTIFY_CONFIRM']}
{MESSAGES['SERVER']} {server['title']}
{MESSAGES['INFO_ID']} {non_order_id}""", reply_markup=notify_to_admin_markup(bot_user))
# ----------------------------------- To QR Area -----------------------------------
# Next Step QR - QR Code
def next_step_to_qr(message: Message):
if is_it_cancel(message):
return
if not message.text:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
is_it_valid = utils.is_it_config_or_sub(message.text)
if is_it_valid:
qr_code = utils.txt_to_qr(message.text)
if qr_code:
bot.send_photo(message.chat.id, qr_code, reply_markup=main_menu_keyboard_markup())
else:
bot.send_message(message.chat.id, MESSAGES['REQUEST_SEND_TO_QR_ERROR'],
reply_markup=main_menu_keyboard_markup())
# ----------------------------------- Link Subscription Area -----------------------------------
# Next Step Link Subscription to bot
def next_step_link_subscription(message: Message):
if not message.text:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
if is_it_cancel(message):
return
uuid = utils.is_it_config_or_sub(message.text)
if uuid:
# check is it already subscribed
is_it_subscribed = utils.is_it_subscription_by_uuid_and_telegram_id(uuid, message.chat.id)
if is_it_subscribed:
bot.send_message(message.chat.id, MESSAGES['ALREADY_SUBSCRIBED'],
reply_markup=main_menu_keyboard_markup())
return
non_sub_id = random.randint(10000000, 99999999)
servers = USERS_DB.select_servers()
if not servers:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'], reply_markup=main_menu_keyboard_markup())
return
for server in servers:
users_list = api.find(server['url'] + API_PATH, uuid)
if users_list:
server_id = server['id']
break
status = USERS_DB.add_non_order_subscription(non_sub_id, message.chat.id, uuid, server_id)
if status:
bot.send_message(message.chat.id, MESSAGES['SUBSCRIPTION_CONFIRMED'],
reply_markup=main_menu_keyboard_markup())
else:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
else:
bot.send_message(message.chat.id, MESSAGES['SUBSCRIPTION_INFO_NOT_FOUND'],
reply_markup=main_menu_keyboard_markup())
# ----------------------------------- wallet balance Area -----------------------------------
# Next Step increase wallet balance - Send amount
def next_step_increase_wallet_balance(message):
if is_it_cancel(message):
return
if not is_it_digit(message, markup=cancel_markup()):
bot.register_next_step_handler(message, next_step_increase_wallet_balance)
return
minimum_deposit_amount = utils.all_configs_settings()
minimum_deposit_amount = minimum_deposit_amount['min_deposit_amount']
amount = utils.toman_to_rial(message.text)
if amount < minimum_deposit_amount:
bot.send_message(message.chat.id,
f"{MESSAGES['INCREASE_WALLET_BALANCE_AMOUNT']}\n{MESSAGES['MINIMUM_DEPOSIT_AMOUNT']}: "
f"{rial_to_toman(minimum_deposit_amount)} {MESSAGES['TOMAN']}", reply_markup=cancel_markup())
bot.register_next_step_handler(message, next_step_increase_wallet_balance)
return
settings = utils.all_configs_settings()
if not settings:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
charge_wallet['amount'] = str(amount)
if settings['three_random_num_price'] == 1:
charge_wallet['amount'] = utils.replace_last_three_with_random(str(amount))
charge_wallet['id'] = random.randint(1000000, 9999999)
# Send 0 to identify wallet balance charge
bot.send_message(message.chat.id,
owner_info_template(settings['card_number'], settings['card_holder'], charge_wallet['amount']),
reply_markup=send_screenshot_markup(plan_id=charge_wallet['id']))
def increase_wallet_balance_specific(message,amount):
settings = utils.all_configs_settings()
user = USERS_DB.find_user(telegram_id=message.chat.id)
if user:
wallet_status = USERS_DB.find_wallet(telegram_id=message.chat.id)
if not wallet_status:
status = USERS_DB.add_wallet(telegram_id=message.chat.id)
if not status:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
charge_wallet['amount'] = str(amount)
if settings['three_random_num_price'] == 1:
charge_wallet['amount'] = utils.replace_last_three_with_random(str(amount))
charge_wallet['id'] = random.randint(1000000, 9999999)
# Send 0 to identify wallet balance charge
bot.send_message(message.chat.id,
owner_info_template(settings['card_number'], settings['card_holder'], charge_wallet['amount']),
reply_markup=send_screenshot_markup(plan_id=charge_wallet['id']))
def update_info_subscription(message: Message, uuid,markup=None):
value = uuid
sub = utils.find_order_subscription_by_uuid(value)
if not sub:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
if not markup:
if sub.get('telegram_id', None):
# Non-Order Subscription markup
mrkup = user_info_non_sub_markup(sub['uuid'])
else:
# Ordered Subscription markup
mrkup = user_info_markup(sub['uuid'])
else:
mrkup = markup
server_id = sub['server_id']
server = USERS_DB.find_server(id=server_id)
if not server:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
server = server[0]
URL = server['url'] + API_PATH
user = api.find(URL, uuid=sub['uuid'])
if not user:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
user = utils.dict_process(URL, utils.users_to_dict([user]))[0]
try:
bot.edit_message_text(chat_id=message.chat.id, message_id=message.message_id,
text=user_info_template(sub['id'], server, user, MESSAGES['INFO_USER']),
reply_markup=mrkup)
except:
pass
# *********************************** Callback Query Area ***********************************
@bot.callback_query_handler(func=lambda call: True)
def callback_query(call: CallbackQuery):
bot.answer_callback_query(call.id, MESSAGES['WAIT'])
bot.clear_step_handler(call.message)
if is_user_banned(call.message.chat.id):
return
# Split Callback Data to Key(Command) and UUID
data = call.data.split(':')
key = data[0]
value = data[1]
global selected_server_id
# ----------------------------------- Link Subscription Area -----------------------------------
# Confirm Link Subscription
if key == 'force_join_status':
bot.delete_message(call.message.chat.id, call.message.message_id)
join_status = is_user_in_channel(call.message.chat.id)
if not join_status:
return
else:
bot.send_message(call.message.chat.id, MESSAGES['JOIN_CHANNEL_SUCCESSFUL'])
elif key == 'confirm_subscription':
edit_status = USERS_DB.add_non_order_subscription(call.message.chat.id, value, )
if edit_status:
bot.delete_message(call.message.chat.id, call.message.message_id)
bot.send_message(call.message.chat.id, MESSAGES['SUBSCRIPTION_CONFIRMED'],
reply_markup=main_menu_keyboard_markup())
else:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
# Reject Link Subscription
elif key == 'cancel_subscription':
bot.delete_message(call.message.chat.id, call.message.message_id)
bot.send_message(call.message.chat.id, MESSAGES['CANCEL_SUBSCRIPTION'],
reply_markup=main_menu_keyboard_markup())
# ----------------------------------- Buy Plan Area -----------------------------------
elif key == 'server_selected':
if value == 'False':
bot.send_message(call.message.chat.id, MESSAGES['SERVER_IS_FULL'], reply_markup=main_menu_keyboard_markup())
return
selected_server_id = int(value)
plans = USERS_DB.find_plan(server_id=int(value))
if not plans:
bot.send_message(call.message.chat.id, MESSAGES['PLANS_NOT_FOUND'], reply_markup=main_menu_keyboard_markup())
return
plan_markup = plans_list_markup(plans)
if not plan_markup:
bot.send_message(call.message.chat.id, MESSAGES['PLANS_NOT_FOUND'], reply_markup=main_menu_keyboard_markup())
return
bot.edit_message_text(MESSAGES['PLANS_LIST'], call.message.chat.id, call.message.message_id,
reply_markup=plan_markup)
elif key == 'free_test_server_selected':
if value == 'False':
bot.send_message(call.message.chat.id, MESSAGES['SERVER_IS_FULL'], reply_markup=main_menu_keyboard_markup())
return
users = USERS_DB.find_user(telegram_id=call.message.chat.id)
if users:
user = users[0]
if user['test_subscription']:
bot.send_message(call.message.chat.id, MESSAGES['ALREADY_RECEIVED_FREE'],
reply_markup=main_menu_keyboard_markup())
return
bot.delete_message(call.message.chat.id, call.message.message_id)
bot.send_message(call.message.chat.id, MESSAGES['REQUEST_SEND_NAME'], reply_markup=cancel_markup())
bot.register_next_step_handler(call.message, next_step_send_name_for_get_free_test, value)
# Send Asked Plan Info
elif key == 'plan_selected':
plan = USERS_DB.find_plan(id=value)[0]
if not plan:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
text=plan_info_template(plan),
reply_markup=confirm_buy_plan_markup(plan['id']))
# Confirm To Buy From Wallet
elif key == 'confirm_buy_from_wallet':
plan = USERS_DB.find_plan(id=value)[0]
buy_from_wallet_confirm(call.message, plan)
elif key == 'confirm_renewal_from_wallet':
plan = USERS_DB.find_plan(id=value)[0]
renewal_from_wallet_confirm(call.message)
# Ask To Send Screenshot
elif key == 'send_screenshot':
bot.delete_message(call.message.chat.id, call.message.message_id)
bot.send_message(call.message.chat.id, MESSAGES['REQUEST_SEND_SCREENSHOT'])
bot.register_next_step_handler(call.message, next_step_send_screenshot, charge_wallet)
#Answer to Admin After send Screenshot
elif key == 'answer_to_admin':
#bot.delete_message(call.message.chat.id,call.message.message_id)
bot.send_message(call.message.chat.id, MESSAGES['ANSWER_TO_ADMIN'],
reply_markup=cancel_markup())
bot.register_next_step_handler(call.message, next_step_answer_to_admin, value)
#Send Ticket to Admin
elif key == 'send_ticket_to_support':
bot.delete_message(call.message.chat.id,call.message.message_id)
bot.send_message(call.message.chat.id, MESSAGES['SEND_TICKET_TO_ADMIN'],
reply_markup=cancel_markup())
bot.register_next_step_handler(call.message, next_step_send_ticket_to_admin)
# ----------------------------------- User Subscriptions Info Area -----------------------------------
# Unlink non-order subscription
elif key == 'unlink_subscription':
delete_status = USERS_DB.delete_non_order_subscription(uuid=value)
if delete_status:
bot.delete_message(call.message.chat.id, call.message.message_id)
bot.send_message(call.message.chat.id, MESSAGES['SUBSCRIPTION_UNLINKED'],
reply_markup=main_menu_keyboard_markup())
else:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
elif key == 'update_info_subscription':
update_info_subscription(call.message, value)
# ----------------------------------- wallet Area -----------------------------------
# INCREASE WALLET BALANCE
elif key == 'increase_wallet_balance':
bot.send_message(call.message.chat.id, MESSAGES['INCREASE_WALLET_BALANCE_AMOUNT'], reply_markup=cancel_markup())
bot.register_next_step_handler(call.message, next_step_increase_wallet_balance)
elif key == 'increase_wallet_balance_specific':
bot.delete_message(call.message.chat.id, call.message.message_id)
increase_wallet_balance_specific(call.message,value)
elif key == 'renewal_subscription':
settings = utils.all_configs_settings()
if not settings['renewal_subscription_status']:
bot.send_message(call.message.chat.id, MESSAGES['RENEWAL_SUBSCRIPTION_CLOSED'],
reply_markup=main_menu_keyboard_markup())
return
servers = USERS_DB.select_servers()
server_id = 0
user= []
URL = "url"
if servers:
for server in servers:
user = api.find(server['url'] + API_PATH, value)
if user:
selected_server_id = server['id']
URL = server['url'] + API_PATH
break
if not user:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
user_info = utils.users_to_dict([user])
if not user_info:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
user_info_process = utils.dict_process(URL, user_info)
if not user_info_process:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
user_info_process = user_info_process[0]
if settings['renewal_method'] == 2:
if user_info_process['remaining_day'] > settings['advanced_renewal_days'] and user_info_process['usage']['remaining_usage_GB'] > settings['advanced_renewal_usage']:
bot.send_message(call.message.chat.id, renewal_unvalable_template(settings),
reply_markup=main_menu_keyboard_markup())
return
renew_subscription_dict[call.message.chat.id] = {
'uuid': None,
'plan_id': None,
}
plans = USERS_DB.find_plan(server_id=selected_server_id)
if not plans:
bot.send_message(call.message.chat.id, MESSAGES['PLANS_NOT_FOUND'],
reply_markup=main_menu_keyboard_markup())
return
renew_subscription_dict[call.message.chat.id]['uuid'] = value
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=plans_list_markup(plans, renewal=True,uuid=user_info_process['uuid']))
elif key == 'renewal_plan_selected':
plan = USERS_DB.find_plan(id=value)[0]
if not plan:
bot.send_message(call.message.chat.id, MESSAGES['PLANS_NOT_FOUND'],
reply_markup=main_menu_keyboard_markup())
return
renew_subscription_dict[call.message.chat.id]['plan_id'] = plan['id']
bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
text=plan_info_template(plan),
reply_markup=confirm_buy_plan_markup(plan['id'], renewal=True,uuid=renew_subscription_dict[call.message.chat.id]['uuid']))
elif key == 'cancel_increase_wallet_balance':
bot.delete_message(call.message.chat.id, call.message.message_id)
bot.send_message(call.message.chat.id, MESSAGES['CANCEL_INCREASE_WALLET_BALANCE'],
reply_markup=main_menu_keyboard_markup())
# ----------------------------------- User Configs Area -----------------------------------
# User Configs - Main Menu
elif key == 'configs_list':
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=sub_url_user_list_markup(value))
# User Configs - Direct Link
elif key == 'conf_dir':
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
configs = utils.sub_parse(sub['sub_link'])
if not configs:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=sub_user_list_markup(value,configs))
# User Configs - Vless Configs Callback
elif key == "conf_dir_vless":
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
configs = utils.sub_parse(sub['sub_link'])
if not configs:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
if not configs['vless']:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
msgs = configs_template(configs['vless'])
for message in msgs:
if message:
bot.send_message(call.message.chat.id, f"{message}",
reply_markup=main_menu_keyboard_markup())
# User Configs - VMess Configs Callback
elif key == "conf_dir_vmess":
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
configs = utils.sub_parse(sub['sub_link'])
if not configs:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
if not configs['vmess']:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
msgs = configs_template(configs['vmess'])
for message in msgs:
if message:
bot.send_message(call.message.chat.id, f"{message}",
reply_markup=main_menu_keyboard_markup())
# User Configs - Trojan Configs Callback
elif key == "conf_dir_trojan":
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
configs = utils.sub_parse(sub['sub_link'])
if not configs:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
if not configs['trojan']:
bot.send_message(call.message.chat.id, MESSAGES['ERROR_CONFIG_NOT_FOUND'])
return
msgs = configs_template(configs['trojan'])
for message in msgs:
if message:
bot.send_message(call.message.chat.id, f"{message}",
reply_markup=main_menu_keyboard_markup())
# User Configs - Subscription Configs Callback
elif key == "conf_sub_url":
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['sub_link'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_SUB']}\n{sub['sub_link']}",
reply_markup=main_menu_keyboard_markup()
)
# User Configs - Base64 Subscription Configs Callback
elif key == "conf_sub_url_b64":
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['sub_link_b64'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_SUB_B64']}\n{sub['sub_link_b64']}",
reply_markup=main_menu_keyboard_markup()
)
# User Configs - Subscription Configs For Clash Callback
elif key == "conf_clash":
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['clash_configs'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_CLASH']}\n{sub['clash_configs']}",
reply_markup=main_menu_keyboard_markup()
)
# User Configs - Subscription Configs For Hiddify Callback
elif key == "conf_hiddify":
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['hiddify_configs'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_HIDDIFY']}\n{sub['hiddify_configs']}",
reply_markup=main_menu_keyboard_markup()
)
elif key == "conf_sub_auto":
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['sub_link_auto'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_SUB_AUTO']}\n{sub['sub_link_auto']}",
reply_markup=main_menu_keyboard_markup()
)
elif key == "conf_sub_sing_box":
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['sing_box'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_SING_BOX']}\n{sub['sing_box']}",
reply_markup=main_menu_keyboard_markup()
)
elif key == "conf_sub_full_sing_box":
sub = utils.sub_links(value)
if not sub:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
qr_code = utils.txt_to_qr(sub['sing_box_full'])
if not qr_code:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
bot.send_photo(
call.message.chat.id,
photo=qr_code,
caption=f"{KEY_MARKUP['CONFIGS_FULL_SING_BOX']}\n{sub['sing_box_full']}",
reply_markup=main_menu_keyboard_markup()
)
# manual
elif key == "msg_manual":
settings = utils.all_configs_settings()
android_msg = settings['msg_manual_android'] if settings['msg_manual_android'] else MESSAGES['MANUAL_ANDROID']
ios_msg = settings['msg_manual_ios'] if settings['msg_manual_ios'] else MESSAGES['MANUAL_IOS']
win_msg = settings['msg_manual_windows'] if settings['msg_manual_windows'] else MESSAGES['MANUAL_WIN']
mac_msg = settings['msg_manual_mac'] if settings['msg_manual_mac'] else MESSAGES['MANUAL_MAC']
linux_msg = settings['msg_manual_linux'] if settings['msg_manual_linux'] else MESSAGES['MANUAL_LIN']
if value == 'android':
bot.send_message(call.message.chat.id, android_msg, reply_markup=main_menu_keyboard_markup())
elif value == 'ios':
bot.send_message(call.message.chat.id, ios_msg, reply_markup=main_menu_keyboard_markup())
elif value == 'win':
bot.send_message(call.message.chat.id, win_msg, reply_markup=main_menu_keyboard_markup())
elif value == 'mac':
bot.send_message(call.message.chat.id, mac_msg, reply_markup=main_menu_keyboard_markup())
elif value == 'lin':
bot.send_message(call.message.chat.id, linux_msg, reply_markup=main_menu_keyboard_markup())
# ----------------------------------- Back Area -----------------------------------
# Back To User Menu
elif key == "back_to_user_panel":
bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
reply_markup=user_info_markup(value))
# Back To Plans
elif key == "back_to_plans":
plans = USERS_DB.find_plan(server_id=selected_server_id)
if not plans:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
text=MESSAGES['PLANS_LIST'], reply_markup=plans_list_markup(plans))
# Back To Renewal Plans
elif key == "back_to_renewal_plans":
plans = USERS_DB.find_plan(server_id=selected_server_id)
if not plans:
bot.send_message(call.message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
# bot.edit_message_reply_markup(call.message.chat.id, call.message.message_id,
# reply_markup=plans_list_markup(plans, renewal=True,uuid=value))
update_info_subscription(call.message, value,plans_list_markup(plans, renewal=True,uuid=value))
elif key == "back_to_servers":
servers = USERS_DB.select_servers()
server_list = []
if not servers:
bot.send_message(message.chat.id, MESSAGES['SERVERS_NOT_FOUND'], reply_markup=main_menu_keyboard_markup())
return
for server in servers:
user_index = 0
#if server['status']:
users_list = api.select(server['url'] + API_PATH)
if users_list:
user_index = len(users_list)
if server['user_limit'] > user_index:
server_list.append([server,True])
else:
server_list.append([server,False])
# bad request telbot api
# bot.edit_message_text(chat_id=message.chat.id, message_id=msg_wait.message_id,
# text= MESSAGES['SERVERS_LIST'], reply_markup=servers_list_markup(server_list))
#bot.delete_message(message.chat.id, msg_wait.message_id)
bot.edit_message_text(reply_markup=servers_list_markup(server_list), chat_id=call.message.chat.id, message_id=call.message.message_id,
text=MESSAGES['SERVERS_LIST'])
# Delete Message
elif key == "del_msg":
bot.delete_message(call.message.chat.id, call.message.message_id)
# Invalid Command
else:
bot.answer_callback_query(call.id, MESSAGES['ERROR_INVALID_COMMAND'])
# *********************************** Message Handler Area ***********************************
# Bot Start Message Handler
@bot.message_handler(commands=['start'])
def start_bot(message: Message):
if is_user_banned(message.chat.id):
return
settings = utils.all_configs_settings()
MESSAGES['WELCOME'] = MESSAGES['WELCOME'] if not settings['msg_user_start'] else settings['msg_user_start']
if USERS_DB.find_user(telegram_id=message.chat.id):
edit_name= USERS_DB.edit_user(telegram_id=message.chat.id,full_name=message.from_user.full_name)
edit_username = USERS_DB.edit_user(telegram_id=message.chat.id,username=message.from_user.username)
bot.send_message(message.chat.id, MESSAGES['WELCOME'], reply_markup=main_menu_keyboard_markup())
else:
created_at = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
status = USERS_DB.add_user(telegram_id=message.chat.id,username=message.from_user.username, full_name=message.from_user.full_name, created_at=created_at)
if not status:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
wallet_status = USERS_DB.find_wallet(telegram_id=message.chat.id)
if not wallet_status:
status = USERS_DB.add_wallet(telegram_id=message.chat.id)
if not status:
bot.send_message(message.chat.id, f"{MESSAGES['UNKNOWN_ERROR']}:Wallet",
reply_markup=main_menu_keyboard_markup())
return
bot.send_message(message.chat.id, MESSAGES['WELCOME'], reply_markup=main_menu_keyboard_markup())
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
# If user is not in users table, request /start
@bot.message_handler(func=lambda message: not USERS_DB.find_user(telegram_id=message.chat.id))
def not_in_users_table(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
bot.send_message(message.chat.id, MESSAGES['REQUEST_START'], reply_markup=main_menu_keyboard_markup())
# User Subscription Status Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['SUBSCRIPTION_STATUS'])
def subscription_status(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
non_order_subs = utils.non_order_user_info(message.chat.id)
order_subs = utils.order_user_info(message.chat.id)
if not non_order_subs and not order_subs:
bot.send_message(message.chat.id, MESSAGES['SUBSCRIPTION_NOT_FOUND'], reply_markup=main_menu_keyboard_markup())
return
if non_order_subs:
for non_order_sub in non_order_subs:
if non_order_sub:
server_id = non_order_sub['server_id']
server = USERS_DB.find_server(id=server_id)
if not server:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
server = server[0]
api_user_data = user_info_template(non_order_sub['sub_id'], server, non_order_sub, MESSAGES['INFO_USER'])
bot.send_message(message.chat.id, api_user_data,
reply_markup=user_info_non_sub_markup(non_order_sub['uuid']))
if order_subs:
for order_sub in order_subs:
if order_sub:
server_id = order_sub['server_id']
server = USERS_DB.find_server(id=server_id)
if not server:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'],
reply_markup=main_menu_keyboard_markup())
return
server = server[0]
api_user_data = user_info_template(order_sub['sub_id'], server, order_sub, MESSAGES['INFO_USER'])
bot.send_message(message.chat.id, api_user_data,
reply_markup=user_info_markup(order_sub['uuid']))
# User Buy Subscription Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['BUY_SUBSCRIPTION'])
def buy_subscription(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
settings = utils.all_configs_settings()
if not settings['buy_subscription_status']:
bot.send_message(message.chat.id, MESSAGES['BUY_SUBSCRIPTION_CLOSED'], reply_markup=main_menu_keyboard_markup())
return
wallet = USERS_DB.find_wallet(telegram_id=message.chat.id)
if not wallet:
create_wallet_status = USERS_DB.add_wallet(message.chat.id)
if not create_wallet_status:
bot.send_message(message.chat.id, MESSAGES['ERROR_UNKNOWN'])
return
wallet = USERS_DB.find_wallet(telegram_id=message.chat.id)
#msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'], reply_markup=main_menu_keyboard_markup())
servers = USERS_DB.select_servers()
server_list = []
if not servers:
bot.send_message(message.chat.id, MESSAGES['SERVERS_NOT_FOUND'], reply_markup=main_menu_keyboard_markup())
return
for server in servers:
user_index = 0
#if server['status']:
users_list = api.select(server['url'] + API_PATH)
if users_list:
user_index = len(users_list)
if server['user_limit'] > user_index:
server_list.append([server,True])
else:
server_list.append([server,False])
# bad request telbot api
# bot.edit_message_text(chat_id=message.chat.id, message_id=msg_wait.message_id,
# text= MESSAGES['SERVERS_LIST'], reply_markup=servers_list_markup(server_list))
#bot.delete_message(message.chat.id, msg_wait.message_id)
bot.send_message(message.chat.id, MESSAGES['SERVERS_LIST'], reply_markup=servers_list_markup(server_list))
# Config To QR Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['TO_QR'])
def to_qr(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
bot.send_message(message.chat.id, MESSAGES['REQUEST_SEND_TO_QR'], reply_markup=cancel_markup())
bot.register_next_step_handler(message, next_step_to_qr)
# Help Guide Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['MANUAL'])
def help_guide(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
bot.send_message(message.chat.id, MESSAGES['MANUAL_HDR'],
reply_markup=users_bot_management_settings_panel_manual_markup())
# Help Guide Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['FAQ'])
def faq(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
settings = utils.all_configs_settings()
faq_msg = settings['msg_faq'] if settings['msg_faq'] else MESSAGES['UNKNOWN_ERROR']
bot.send_message(message.chat.id, faq_msg, reply_markup=main_menu_keyboard_markup())
# Ticket To Support Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['SEND_TICKET'])
def send_ticket(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
bot.send_message(message.chat.id, MESSAGES['SEND_TICKET_TO_ADMIN_TEMPLATE'], reply_markup=send_ticket_to_admin())
# Link Subscription Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['LINK_SUBSCRIPTION'])
def link_subscription(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
bot.send_message(message.chat.id, MESSAGES['ENTER_SUBSCRIPTION_INFO'], reply_markup=cancel_markup())
bot.register_next_step_handler(message, next_step_link_subscription)
# User Buy Subscription Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['WALLET'])
def wallet_balance(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
user = USERS_DB.find_user(telegram_id=message.chat.id)
if user:
wallet_status = USERS_DB.find_wallet(telegram_id=message.chat.id)
if not wallet_status:
status = USERS_DB.add_wallet(telegram_id=message.chat.id)
if not status:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'])
return
wallet = USERS_DB.find_wallet(telegram_id=message.chat.id)
wallet = wallet[0]
telegram_user_data = wallet_info_template(wallet['balance'])
bot.send_message(message.chat.id, telegram_user_data,
reply_markup=wallet_info_markup())
else:
bot.send_message(message.chat.id, MESSAGES['UNKNOWN_ERROR'])
# User Buy Subscription Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['FREE_TEST'])
def free_test(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
settings = utils.all_configs_settings()
if not settings['test_subscription']:
bot.send_message(message.chat.id, MESSAGES['FREE_TEST_NOT_AVAILABLE'], reply_markup=main_menu_keyboard_markup())
return
users = USERS_DB.find_user(telegram_id=message.chat.id)
if users:
user = users[0]
if user['test_subscription']:
bot.send_message(message.chat.id, MESSAGES['ALREADY_RECEIVED_FREE'],
reply_markup=main_menu_keyboard_markup())
return
else:
# bot.send_message(message.chat.id, MESSAGES['REQUEST_SEND_NAME'], reply_markup=cancel_markup())
# bot.register_next_step_handler(message, next_step_send_name_for_get_free_test)
msg_wait = bot.send_message(message.chat.id, MESSAGES['WAIT'])
servers = USERS_DB.select_servers()
server_list = []
if not servers:
bot.send_message(message.chat.id, MESSAGES['SERVERS_NOT_FOUND'], reply_markup=main_menu_keyboard_markup())
return
for server in servers:
user_index = 0
#if server['status']:
users_list = api.select(server['url'] + API_PATH)
if users_list:
user_index = len(users_list)
if server['user_limit'] > user_index:
server_list.append([server,True])
else:
server_list.append([server,False])
# bad request telbot api
# bot.edit_message_text(chat_id=message.chat.id, message_id=msg_wait.message_id,
# text= MESSAGES['SERVERS_LIST'], reply_markup=servers_list_markup(server_list))
bot.delete_message(message.chat.id, msg_wait.message_id)
bot.send_message(message.chat.id, MESSAGES['SERVERS_LIST'], reply_markup=servers_list_markup(server_list, True))
# Cancel Message Handler
@bot.message_handler(func=lambda message: message.text == KEY_MARKUP['CANCEL'])
def cancel(message: Message):
if is_user_banned(message.chat.id):
return
join_status = is_user_in_channel(message.chat.id)
if not join_status:
return
bot.send_message(message.chat.id, MESSAGES['CANCELED'], reply_markup=main_menu_keyboard_markup())
# *********************************** Main Area ***********************************
def start():
# Bot Start Commands
try:
bot.set_my_commands([
telebot.types.BotCommand("/start", BOT_COMMANDS['START']),
])
except telebot.apihelper.ApiTelegramException as e:
if e.result.status_code == 401:
logging.error("Invalid Telegram Bot Token!")
exit(1)
# Welcome to Admin
for admin in ADMINS_ID:
try:
bot.send_message(admin, MESSAGES['WELCOME_TO_ADMIN'])
except Exception as e:
logging.warning(f"Error in send message to admin {admin}: {e}")
bot.enable_save_next_step_handlers()
bot.load_next_step_handlers()
bot.infinity_polling()
================================================
FILE: UserBot/content.py
================================================
import os
import json
from config import LANG
from Utils.utils import all_configs_settings
FOLDER = "Json"
MSG_FILE = "messages.json"
BTN_FILE = "buttons.json"
CMD_FILE = "commands.json"
settings = all_configs_settings()
with open(os.path.join(os.path.dirname(__file__), FOLDER, MSG_FILE), encoding='utf-8') as f:
MESSAGES = json.load(f)
MESSAGES = MESSAGES[LANG]
if settings['msg_user_start']:
MESSAGES['WELCOME'] = settings['msg_user_start']
with open(os.path.join(os.path.dirname(__file__), FOLDER, BTN_FILE), encoding='utf-8') as f:
KEY_MARKUP = json.load(f)
KEY_MARKUP = KEY_MARKUP[LANG]
with open(os.path.join(os.path.dirname(__file__), FOLDER, CMD_FILE), encoding='utf-8') as f:
BOT_COMMANDS = json.load(f)
BOT_COMMANDS = BOT_COMMANDS[LANG]
================================================
FILE: UserBot/markups.py
================================================
# Description: This file contains all the reply and inline keyboard markups used in the bot.
from telebot import types
from telebot.types import ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton
from UserBot.content import KEY_MARKUP, MESSAGES
from UserBot.content import MESSAGES
from Utils.utils import rial_to_toman,all_configs_settings
from Utils.api import *
# Main Menu Reply Keyboard Markup
def main_menu_keyboard_markup():
markup = ReplyKeyboardMarkup(row_width=3, resize_keyboard=True)
markup.add(KeyboardButton(KEY_MARKUP['SUBSCRIPTION_STATUS']))
markup.add(KeyboardButton(KEY_MARKUP['LINK_SUBSCRIPTION']), KeyboardButton(KEY_MARKUP['BUY_SUBSCRIPTION']))
markup.add(KeyboardButton(KEY_MARKUP['FREE_TEST']), KeyboardButton(KEY_MARKUP['WALLET']))
# KeyboardButton(KEY_MARKUP['TO_QR']),
settings = all_configs_settings()
if settings['msg_faq']:
markup.add(KeyboardButton(KEY_MARKUP['SEND_TICKET']),
KeyboardButton(KEY_MARKUP['MANUAL']), KeyboardButton(KEY_MARKUP['FAQ']))
else:
markup.add(KeyboardButton(KEY_MARKUP['SEND_TICKET']),
KeyboardButton(KEY_MARKUP['MANUAL']))
return markup
def user_info_markup(uuid):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_LIST'], callback_data=f"configs_list:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['RENEWAL_SUBSCRIPTION'], callback_data=f"renewal_subscription:{uuid}"))
markup.add(
InlineKeyboardButton(KEY_MARKUP['UPDATE_SUBSCRIPTION_INFO'], callback_data=f"update_info_subscription:{uuid}"))
return markup
# Subscription URL Inline Keyboard Markup
def sub_url_user_list_markup(uuid):
markup = InlineKeyboardMarkup()
markup.row_width = 2
settings = all_configs_settings()
if settings['visible_conf_dir']:
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_DIR'], callback_data=f"conf_dir:{uuid}"))
if settings['visible_conf_sub_auto']:
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_SUB_AUTO'], callback_data=f"conf_sub_auto:{uuid}"))
if settings['visible_conf_sub_url']:
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_SUB'], callback_data=f"conf_sub_url:{uuid}"))
if settings['visible_conf_sub_url_b64']:
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_SUB_B64'], callback_data=f"conf_sub_url_b64:{uuid}"))
if settings['visible_conf_clash']:
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_CLASH'], callback_data=f"conf_clash:{uuid}"))
if settings['visible_conf_hiddify']:
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_HIDDIFY'], callback_data=f"conf_hiddify:{uuid}"))
if settings['visible_conf_sub_sing_box']:
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_SING_BOX'], callback_data=f"conf_sub_sing_box:{uuid}"))
if settings['visible_conf_sub_full_sing_box']:
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_FULL_SING_BOX'],
callback_data=f"conf_sub_full_sing_box:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_user_panel:{uuid}"))
return markup
# Subscription Configs Inline Keyboard Markup
def sub_user_list_markup(uuid,configs):
markup = InlineKeyboardMarkup()
markup.row_width = 1
if configs['vless']:
markup.add(InlineKeyboardButton('Vless', callback_data=f"conf_dir_vless:{uuid}"))
if configs['vmess']:
markup.add(InlineKeyboardButton('Vmess', callback_data=f"conf_dir_vmess:{uuid}"))
if configs['trojan']:
markup.add(InlineKeyboardButton('Trojan', callback_data=f"conf_dir_trojan:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_user_panel:{uuid}"))
# markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_user_panel:{uuid}"))
# markup.add(InlineKeyboardButton('Vmess', callback_data=f"conf_dir_vmess:{uuid}"))
# markup.add(InlineKeyboardButton('Trojan', callback_data=f"conf_dir_trojan:{uuid}"))
return markup
def user_info_non_sub_markup(uuid):
markup = InlineKeyboardMarkup()
markup.row_width = 2
markup.add(InlineKeyboardButton(KEY_MARKUP['CONFIGS_LIST'], callback_data=f"configs_list:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['RENEWAL_SUBSCRIPTION'], callback_data=f"renewal_subscription:{uuid}"))
markup.add(
InlineKeyboardButton(KEY_MARKUP['UPDATE_SUBSCRIPTION_INFO'], callback_data=f"update_info_subscription:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['UNLINK_SUBSCRIPTION'], callback_data=f"unlink_subscription:{uuid}"))
return markup
def confirm_subscription_markup(uuid):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['YES'], callback_data=f"confirm_subscription:{uuid}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['NO'], callback_data=f"cancel_subscription:{uuid}"))
return markup
def confirm_buy_plan_markup(plan_id, renewal=False,uuid=None):
markup = InlineKeyboardMarkup()
markup.row_width = 1
callback = "confirm_buy_from_wallet" if not renewal else "confirm_renewal_from_wallet"
markup.add(InlineKeyboardButton(KEY_MARKUP['BUY_FROM_WALLET'], callback_data=f"{callback}:{plan_id}"))
if renewal:
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_renewal_plans:{uuid}"))
else:
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_plans:None"))
return markup
def send_screenshot_markup(plan_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['SEND_SCREENSHOT'], callback_data=f"send_screenshot:{plan_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['CANCEL'], callback_data=f"cancel_increase_wallet_balance:{plan_id}"))
return markup
def plans_list_markup(plans, renewal=False,uuid=None):
markup = InlineKeyboardMarkup(row_width=1)
callback = "renewal_plan_selected" if renewal else "plan_selected"
keys = []
for plan in plans:
if plan['status']:
keys.append(InlineKeyboardButton(
f"{plan['size_gb']}{MESSAGES['GB']} | {plan['days']}{MESSAGES['DAY_EXPIRE']} | {rial_to_toman(plan['price'])} {MESSAGES['TOMAN']}",
callback_data=f"{callback}:{plan['id']}"))
if len(keys) == 0:
return None
if renewal:
keys.append(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_user_panel:{uuid}"))
else:
keys.append(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"back_to_servers:None"))
markup.add(*keys)
return markup
# Server List - Server List - Inline Keyboard Markup
def servers_list_markup(servers, free_test=False):
markup = InlineKeyboardMarkup(row_width=1)
callback = "free_test_server_selected" if free_test else "server_selected"
keys = []
if servers:
for server in servers:
server_title = server[0]['title'] if server[1] else f"{server[0]['title']}⛔️"
callback_2 = f"{server[0]['id']}" if server[1] else "False"
keys.append(InlineKeyboardButton(f"{server_title}",
callback_data=f"{callback}:{callback_2}"))
keys.append(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"del_msg:None"))
if len(keys) == 0:
return None
markup.add(*keys)
return markup
def confirm_payment_by_admin(order_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton(KEY_MARKUP['CONFIRM_PAYMENT'], callback_data=f"confirm_payment_by_admin:{order_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['NO'], callback_data=f"cancel_payment_by_admin:{order_id}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['SEND_MESSAGE'], callback_data=f"send_message_by_admin:{order_id}"))
return markup
def notify_to_admin_markup(user):
name = user['full_name'] if user['full_name'] else user['telegram_id']
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(f"{name}", callback_data=f"bot_user_info:{user['telegram_id']}"))
return markup
def send_ticket_to_admin():
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton(KEY_MARKUP['SEND_TICKET_TO_SUPPORT'], callback_data=f"send_ticket_to_support:None"))
markup.add(
InlineKeyboardButton(KEY_MARKUP['CANCEL'], callback_data=f"del_msg:None"))
return markup
def answer_to_user_markup(user,user_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
name = user['full_name'] if user['full_name'] else user['telegram_id']
markup.add(InlineKeyboardButton(f"{name}", callback_data=f"bot_user_info:{user['telegram_id']}"))
markup.add(InlineKeyboardButton(KEY_MARKUP['ANSWER'], callback_data=f"users_bot_send_message_by_admin:{user_id}"))
return markup
def cancel_markup():
markup = ReplyKeyboardMarkup(row_width=3, resize_keyboard=True)
markup.add(KeyboardButton(KEY_MARKUP['CANCEL']))
return markup
def wallet_info_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton(KEY_MARKUP['INCREASE_WALLET_BALANCE'], callback_data=f"increase_wallet_balance:wallet"))
return markup
def wallet_info_specific_markup(amount):
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton(KEY_MARKUP['INCREASE_WALLET_BALANCE'], callback_data=f"increase_wallet_balance_specific:{amount}"))
return markup
def force_join_channel_markup(channel_id):
markup = InlineKeyboardMarkup()
markup.row_width = 1
channel_id = channel_id.replace("@", "")
markup.add(
InlineKeyboardButton(KEY_MARKUP['JOIN_CHANNEL'], url=f"https://t.me/{channel_id}",)
)
markup.add(
InlineKeyboardButton(KEY_MARKUP['FORCE_JOIN_CHANNEL_ACCEPTED'], callback_data=f"force_join_status:None")
)
return markup
def users_bot_management_settings_panel_manual_markup():
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(InlineKeyboardButton(KEY_MARKUP['MANUAL_ANDROID'],
callback_data=f"msg_manual:android"))
markup.add(InlineKeyboardButton(KEY_MARKUP['MANUAL_IOS'],
callback_data=f"msg_manual:ios"))
markup.add(InlineKeyboardButton(KEY_MARKUP['MANUAL_WIN'],
callback_data=f"msg_manual:win"))
markup.add(InlineKeyboardButton(KEY_MARKUP['MANUAL_MAC'],
callback_data=f"msg_manual:mac"))
markup.add(InlineKeyboardButton(KEY_MARKUP['MANUAL_LIN'],
callback_data=f"msg_manual:lin"))
markup.add(InlineKeyboardButton(KEY_MARKUP['BACK'], callback_data=f"del_msg:None"))
return markup
================================================
FILE: UserBot/templates.py
================================================
# Description: This file contains all the templates used in the bot.
from config import LANG
from UserBot.content import MESSAGES
from Utils.utils import rial_to_toman, toman_to_rial,all_configs_settings
from Database.dbManager import USERS_DB
# User Subscription Info Template
def user_info_template(sub_id, server, usr, header=""):
settings = USERS_DB.find_bool_config(key='visible_hiddify_hyperlink')
if settings:
settings = settings[0]
if settings['value']:
user_name = f" {usr['name']} "
else:
user_name = usr['name']
else:
user_name = usr['name']
# if usr['enable'] == 1:
# status = MESSAGES['ACTIVE_SUBSCRIPTION_STATUS']
# else:
# status = MESSAGES['DEACTIVE_SUBSCRIPTION_STATUS']
return f"""
{header}
{MESSAGES['USER_NAME']} {user_name}
{MESSAGES['SERVER']} {server['title']}
{MESSAGES['INFO_USAGE']} {usr['usage']['current_usage_GB']} {MESSAGES['OF']} {usr['usage']['usage_limit_GB']} {MESSAGES['GB']}
{MESSAGES['INFO_REMAINING_DAYS']} {usr['remaining_day']} {MESSAGES['DAY_EXPIRE']}
{MESSAGES['INFO_ID']} {sub_id}
"""
# {MESSAGES['SUBSCRIPTION_STATUS']} {status}
# Wallet Info Template
def wallet_info_template(balance):
if balance == 0:
return MESSAGES['ZERO_BALANCE']
else:
return f"""
{MESSAGES['WALLET_INFO_PART_1']} {rial_to_toman(balance)} {MESSAGES['WALLET_INFO_PART_2']}
"""
# Plan Info Template
def plan_info_template(plan, header=""):
msg = f"""
{header}
{MESSAGES['PLAN_INFO']}
{MESSAGES['PLAN_INFO_SIZE']} {plan['size_gb']} {MESSAGES['GB']}
{MESSAGES['PLAN_INFO_DAYS']} {plan['days']} {MESSAGES['DAY_EXPIRE']}
{MESSAGES['PLAN_INFO_PRICE']} {rial_to_toman(plan['price'])} {MESSAGES['TOMAN']}
"""
if plan['description']:
msg += f"""{MESSAGES['PLAN_INFO_DESC']} {plan['description']}"""
return msg
# Owner Info Template (For Payment)
def owner_info_template(card_number, card_holder_name, price, header=""):
card_number = card_number if card_number else "-"
card_holder_name = card_holder_name if card_holder_name else "-"
if LANG == 'FA':
return f"""
{header}
💰لطفا دقیقا مبلغ: {price} {MESSAGES['RIAL']}
💴معادل: {rial_to_toman(price)} {MESSAGES['TOMAN']}
💳را به شماره کارت: {card_number}
👤به نام {card_holder_name} واریز کنید.
❗️بعد از واریز مبلغ، اسکرین شات از تراکنش را برای ما ارسال کنید.
"""
elif LANG == 'EN':
return f"""
{header}
💰Please pay exactly: {price} {MESSAGES['TOMAN']}
💳To card number: {card_number}
Card owner {card_holder_name}
❗️After paying the amount, send us a screenshot of the transaction.
"""
# Payment Received Template - Send to Admin
def payment_received_template(payment,user, header="", footer=""):
username = f"@{user['username']}" if user['username'] else MESSAGES['NOT_SET']
name = user['full_name'] if user['full_name'] else user['telegram_id']
if LANG == 'FA':
return f"""
{header}
شناسه تراکنش: {payment['id']}
مبلغ تراکنش: {rial_to_toman(payment['payment_amount'])} {MESSAGES['TOMAN']}
{MESSAGES['INFO_USER_NAME']} {name}
{MESSAGES['INFO_USER_USERNAME']} {username}
{MESSAGES['INFO_USER_NUM_ID']} {user['telegram_id']}
---------------------
⬇️درخواست افزایش موجودی کیف پول⬇️
{footer}
"""
elif LANG == 'EN':
return f"""
{header}
Payment number: {payment['id']}
Paid amount: {payment['payment_amount']} {MESSAGES['TOMAN']}
{MESSAGES['INFO_USER_NAME']} {name}
{MESSAGES['INFO_USER_USERNAME']} {username}
{MESSAGES['INFO_USER_NUM_ID']} {user['telegram_id']}
---------------------
⬇️Request to increase wallet balance⬇️
"""
# Help Guide Template
def connection_help_template(header=""):
if LANG == 'FA':
return f"""
{header}
⭕️ نرم افزار های مورد نیاز برای اتصال به کانفیگ
📥اندروید:
V2RayNG
HiddifyNG
📥آی او اس:
Streisand
Foxray
V2box
📥ویندوز:
Nekoray
V2rayN
HiddifyN
📥مک و لینوکس:
Nekoray
"""
elif LANG == 'EN':
return f"""
{header}
⭕️Required software for connecting to config
📥Android:
V2RayNG
HiddifyNG
📥iOS:
Streisand
Foxray
V2box
📥Windows:
Nekoray
V2rayN
HiddifyN
📥Mac and Linux:
Nekoray
"""
# Support Info Template
# def support_template(owner_info, header=""):
# username = None
# owner_info = all_configs_settings()
# if owner_info:
# username = owner_info['support_username'] if owner_info['support_username'] else "-"
# else:
# username = "-"
# if LANG == 'FA':
# return f"""
# {header}
# 📞پشتیبانی: {username}
# """
# elif LANG == 'EN':
# return f"""
# {header}
# 📞Supporter: {username}
# """
# Alert Package Days Template
def package_days_expire_soon_template(sub_id, remaining_days):
if LANG == 'FA':
return f"""
تنها {remaining_days} روز تا اتمام اعتبار پکیج شما باقی مانده است.
لطفا برای تمدید پکیج اقدام کنید.
شناسه پکیج شما: {sub_id}
"""
elif LANG == 'EN':
return f"""
Only {remaining_days} days left until your package expires.
Please purchase a new package.
Your package ID: {sub_id}
"""
# Alert Package Size Template
def package_size_end_soon_template(sub_id, remaining_size):
if LANG == 'FA':
return f"""
تنها {remaining_size} گیگابایت تا اتمام اعتبار پکیج شما باقی مانده است.
لطفا برای تمدید پکیج اقدام کنید.
شناسه پکیج شما: {sub_id}
"""
elif LANG == 'EN':
return f"""
Only {remaining_size} GB left until your package expires.
Please renewal package.
Your package ID: {sub_id}
"""
def renewal_unvalable_template(settings):
if LANG == 'FA':
return f"""
🛑در حال حاضر شما امکان تمدید اشتراک خود را ندارید.
جهت تمدید اشتراک باید یکی از شروط زیر برقرار باشد:
1- کمتر از {settings['advanced_renewal_days']} روز تا اتمام اشتراک شما باقی مانده باشد.
2- حجم باقی مانده اشتراک شما کمتر از {settings['advanced_renewal_usage']} گیگابایت باشد.
"""
elif LANG == 'EN':
return f"""
🛑You cannot renew your subscription at this time.
To renew your subscription, one of the following conditions must be met:
1- Less than {settings['advanced_renewal_days']} days left until your subscription expires.
2- The remaining volume of your subscription is less than {settings['advanced_renewal_usage']} GB.
"""
================================================
FILE: Utils/api.py
================================================
# from config import *
# from Utils.utils import *
import json
import logging
from urllib.parse import urlparse
import datetime
import requests
from config import API_PATH
import Utils
# Document: https://github.com/hiddify/hiddify-config/discussions/3209
# It not in uses now, but it will be used in the future.
def select(url, endpoint="/user/"):
try:
response = requests.get(url + endpoint)
res = Utils.utils.dict_process(url, Utils.utils.users_to_dict(response.json()))
return res
except Exception as e:
logging.error("API error: %s" % e)
return None
def find(url, uuid, endpoint="/user/"):
try:
response = requests.get(url + endpoint, data={"uuid": uuid})
jr = response.json()
if len(jr) != 1:
# Search for uuid
for user in jr:
if user['uuid'] == uuid:
return user
return None
return jr[0]
except Exception as e:
logging.error("API error: %s" % e)
return None
def insert(url, name, usage_limit_GB, package_days, last_reset_time=None, added_by_uuid=None, mode="no_reset",
last_online="1-01-01 00:00:00", telegram_id=None,
comment=None, current_usage_GB=0, start_date=None, endpoint="/user/"):
import uuid
uuid = str(uuid.uuid4())
# last_online = '1-01-01 00:00:00'
# expiry_time = (datetime.datetime.now() + datetime.timedelta(days=180)).strftime("%Y-%m-%d")
# start_date = None
# current_usage_GB = 0
added_by_uuid = urlparse(url).path.split('/')[2]
last_reset_time = datetime.datetime.now().strftime("%Y-%m-%d")
data = {
"uuid": uuid,
"name": name,
"usage_limit_GB": usage_limit_GB,
"package_days": package_days,
"added_by_uuid": added_by_uuid,
"last_reset_time": last_reset_time,
"mode": mode,
"last_online": last_online,
"telegram_id": telegram_id,
"comment": comment,
"current_usage_GB": current_usage_GB,
"start_date": start_date
}
jdata = json.dumps(data)
try:
response = requests.post(url + endpoint, data=jdata, headers={'Content-Type': 'application/json'})
return uuid
except Exception as e:
logging.error("API error: %s" % e)
return None
def update(url, uuid, endpoint="/user/", **kwargs, ):
try:
# use api.insert to update, replace new data with old data
user = find(url, uuid)
if not user:
return None
for key in kwargs:
user[key] = kwargs[key]
response = requests.post(url + endpoint, data=json.dumps(user),
headers={'Content-Type': 'application/json'})
return uuid
except Exception as e:
logging.error("API error: %s" % e)
return None
================================================
FILE: Utils/serverInfo.py
================================================
# Thanks to https://github.com/m-mjd/hiddybot_info_severs
import sqlite3
from urllib.parse import urlparse
import requests
from Database.dbManager import USERS_DB
def scrape_data_from_json_url(url):
try:
response = requests.get(url)
response.raise_for_status()
# Parse JSON data
json_data = response.json()
# Extract information from JSON using the shared function
extracted_data = json_template(json_data)
return extracted_data
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
def json_template(data):
system_stats = data.get('stats', {}).get('system', {})
top5_stats = data.get('stats', {}).get('top5', {})
usage_history = data.get('usage_history', {})
bytes_recv = system_stats.get('bytes_recv')
bytes_recv_cumulative = system_stats.get('bytes_recv_cumulative')
bytes_sent = system_stats.get('bytes_sent')
bytes_sent_cumulative = system_stats.get('bytes_sent_cumulative')
cpu_percent = system_stats.get('cpu_percent')
number_of_cores = system_stats.get('num_cpus')
disk_total = system_stats.get('disk_total')
disk_used = system_stats.get('disk_used')
ram_total = system_stats.get('ram_total')
ram_used = system_stats.get('ram_used')
total_upload_server = system_stats.get('net_sent_cumulative_GB')
total_download_server = system_stats.get('net_total_cumulative_GB')
hiddify_used = system_stats.get('hiddify_used')
load_avg_15min = system_stats.get('load_avg_15min')
load_avg_1min = system_stats.get('load_avg_1min')
load_avg_5min = system_stats.get('load_avg_5min')
total_connections = system_stats.get('total_connections')
total_unique_ips = system_stats.get('total_unique_ips')
cpu_top5 = top5_stats.get('cpu', [])
memory_top5 = top5_stats.get('memory', [])
ram_top5 = top5_stats.get('ram', [])
online_last_24h = usage_history.get('h24', {}).get('online')
usage_last_24h = usage_history.get('h24', {}).get('usage')
online_last_30_days = usage_history.get('last_30_days', {}).get('online')
usage_last_30_days = usage_history.get('last_30_days', {}).get('usage')
online_last_5min = usage_history.get('m5', {}).get('online')
usage_last_5min = usage_history.get('m5', {}).get('usage')
online_today = usage_history.get('today', {}).get('online')
usage_today = usage_history.get('today', {}).get('usage')
online_total = usage_history.get('total', {}).get('online')
usage_total = usage_history.get('total', {}).get('usage')
total_users = usage_history.get('total', {}).get('users')
online_yesterday = usage_history.get('yesterday', {}).get('online')
usage_yesterday = usage_history.get('yesterday', {}).get('usage')
return {
'bytes_recv': bytes_recv,
'bytes_recv_cumulative': bytes_recv_cumulative,
'bytes_sent': bytes_sent,
'bytes_sent_cumulative': bytes_sent_cumulative,
'cpu_percent': cpu_percent,
'number_of_cores': number_of_cores,
'disk_total': disk_total,
'disk_used': disk_used,
'ram_total': ram_total,
'ram_used': ram_used,
'total_upload_server': total_upload_server,
'total_download_server': total_download_server,
'hiddify_used': hiddify_used,
'load_avg_15min': load_avg_15min,
'load_avg_1min': load_avg_1min,
'load_avg_5min': load_avg_5min,
'total_connections': total_connections,
'total_unique_ips': total_unique_ips,
'cpu_top5': cpu_top5,
'memory_top5': memory_top5,
'ram_top5': ram_top5,
'online_last_24h': online_last_24h,
'usage_last_24h': usage_last_24h,
'online_last_30_days': online_last_30_days,
'usage_last_30_days': usage_last_30_days,
'online_last_5min': online_last_5min,
'usage_last_5min': usage_last_5min,
'online_today': online_today,
'usage_today': usage_today,
'online_total': online_total,
'usage_total': usage_total,
'total_users': total_users,
'online_yesterday': online_yesterday,
'usage_yesterday': usage_yesterday,
}
def server_status_template(result, server_name):
lline = (32 * "-")
bytes_recv = result.get('bytes_recv', 'N/A')
bytes_recv_cumulative = result.get('bytes_recv_cumulative', 'N/A')
bytes_sent = result.get('bytes_sent', 'N/A')
bytes_sent_cumulative = result.get('bytes_sent_cumulative', 'N/A')
cpu_percent = result.get('cpu_percent', 'N/A')
number_of_cores = result.get('number_of_cores', 'N/A')
disk_total = result.get('disk_total', 'N/A')
disk_used = result.get('disk_used', 'N/A')
ram_total = result.get('ram_total', 'N/A')
ram_used = result.get('ram_used', 'N/A')
total_upload_server = result.get('total_upload_server', 'N/A')
total_download_server = result.get('total_download_server', 'N/A')
online_last_24h = result.get('online_last_24h', 'N/A')
usage_last_24h = result.get('usage_last_24h', 'N/A')
usage_last_24h = f"{usage_last_24h / (1024 ** 3):.2f} GB" if usage_last_24h != 'N/A' else 'N/A'
online_last_30_days = result.get('online_last_30_days', 'N/A')
usage_last_30_days = result.get('usage_last_30_days', 'N/A')
usage_last_30_days = f"{usage_last_30_days / (1024 ** 3):.2f} GB" if usage_last_30_days != 'N/A' else 'N/A'
online_last_5min = result.get('online_last_5min', 'N/A')
usage_last_5min = result.get('usage_last_5min', 'N/A')
online_today = result.get('online_today', 'N/A')
usage_today = result.get('usage_today', 'N/A')
usage_today = f"{usage_today / (1024 ** 3):.2f} GB" if usage_today != 'N/A' else 'N/A'
online_total = result.get('online_total', 'N/A')
usage_total = result.get('usage_total', 'N/A')
usage_total = f"{usage_total / (1024 ** 3):.2f} GB" if usage_total != 'N/A' else 'N/A'
total_users = result.get('total_users', 'N/A')
online_yesterday = result.get('online_yesterday', 'N/A')
usage_yesterday = result.get('usage_yesterday', 'N/A')
hiddify_used = result.get('hiddify_used', 'N/A')
load_avg_15min = result.get('load_avg_15min', 'N/A')
load_avg_1min = result.get('load_avg_1min', 'N/A')
load_avg_5min = result.get('load_avg_5min', 'N/A')
total_connections = result.get('total_connections', 'N/A')
total_unique_ips = result.get('total_unique_ips', 'N/A')
cpu_top5 = result.get('cpu_top5', 'N/A')
memory_top5 = result.get('memory_top5', 'N/A')
ram_top5 = result.get('ram_top5', 'N/A')
# Calculate percentage for RAM and Disk
ram_percent = (ram_used / ram_total) * \
100 if ram_total != 'N/A' and ram_total != 0 else 'N/A'
disk_percent = (disk_used / disk_total) * \
100 if disk_total != 'N/A' and disk_total != 0 else 'N/A'
# Format bytes with appropriate units
formatted_bytes_recv = f"{bytes_recv / (1024 ** 2):.2f} MB" if bytes_recv != 'N/A' else 'N/A'
formatted_bytes_sent = f"{bytes_sent / (1024 ** 2):.2f} MB" if bytes_sent != 'N/A' else 'N/A'
# Add information for all servers
return f"Server: {server_name}\n{lline}\n" \
f"SYSTEM INFO\n"\
f"CPU: {cpu_percent}% - {number_of_cores} CORE\n" \
f"RAM: {ram_used:.2f} GB / {ram_total:.2f} GB ({ram_percent:.2f}%)\n" \
f"DISK: {disk_used:.2f} GB / {disk_total:.2f} GB ({disk_percent:.2f}%)\n\n" \
f"NETWORK INFO\n"\
f"Total Users: {total_users} User\n" \
f"Usage (Today): {usage_today}\n" \
f"Online (Now): {online_last_5min} User\n" \
f"Now Network Received: {formatted_bytes_recv}\n" \
f"Now Network Sent: {formatted_bytes_sent}\n" \
f"Online (Today): {online_today} User\n" \
f"Online(30 Days): {online_last_30_days} User\n" \
f"Usage(30 Days): {usage_last_30_days}\n"\
f"Total Download (Server): {total_download_server:.2f} GB\n" \
f"Total Upload (Server): {total_upload_server:.2f} GB\n" \
def get_server_status(server_row):
server_name = server_row['title']
server_url = server_row['url']
data = scrape_data_from_json_url(f"{server_url}/admin/get_data/")
if not data:
return False
txt = server_status_template(data, server_name)
return txt
================================================
FILE: Utils/utils.py
================================================
# Description: API for connecting to the panel
import json
import logging
import os
import random
import string
from io import BytesIO
import re
from datetime import datetime
from urllib.parse import urlparse
from Database.dbManager import USERS_DB
import psutil
import qrcode
import requests
from config import PANEL_URL, BACKUP_LOC, CLIENT_TOKEN, USERS_DB_LOC,RECEIPTIONS_LOC,BOT_BACKUP_LOC, API_PATH,LOG_DIR
import AdminBot.templates
from Utils import api
from version import __version__
import zipfile
import shutil
# Global variables
# Make Session for requests
session = requests.session()
# Base panel URL - example: https://panel.example.com
BASE_URL = urlparse(PANEL_URL).scheme + "://" + urlparse(PANEL_URL).netloc
# Users directory in panel
# USERS_DIR = "/admin/user/"
# Get request - return request object
def get_request(url):
logging.info(f"GET Request to {privacy_friendly_logging_request(url)}")
global session
try:
req = session.get(url)
logging.info(f"GET Request to {privacy_friendly_logging_request(url)} - Status Code: {req.status_code}")
return req
except requests.exceptions.ConnectionError as e:
logging.exception(f"Connection Exception: {e}")
return False
except requests.exceptions.Timeout as e:
logging.exception(f"Timeout Exception: {e}")
return False
except requests.exceptions.RequestException as e:
logging.exception(f"General Connection Exception: {e}")
return False
except Exception as e:
logging.exception(f"General Exception: {e}")
return False
# Post request - return request object
def post_request(url, data):
logging.info(f"POST Request to {privacy_friendly_logging_request(url)} - Data: {data}")
global session
try:
req = session.post(url, data=data)
return req
except requests.exceptions.ConnectionError as e:
logging.exception(f"Connection Exception: {e}")
return False
except requests.exceptions.Timeout as e:
logging.exception(f"Timeout Exception: {e}")
return False
except requests.exceptions.RequestException as e:
logging.exception(f"General Connection Exception: {e}")
return False
except Exception as e:
logging.exception(f"General Exception: {e}")
return False
def users_to_dict(users_dict):
if not users_dict:
return False
users_array = []
for user in users_dict:
users_array.append({'uuid': user['uuid'], 'name': user['name'], 'last_online': user['last_online'],
'expiry_time': None,
'usage_limit_GB': user['usage_limit_GB'], 'package_days': user['package_days'],
'mode': user['mode'],
'monthly': None, 'start_date': user['start_date'],
'current_usage_GB': user['current_usage_GB'],
'last_reset_time': user['last_reset_time'], 'comment': user['comment'],
'telegram_id': user['telegram_id'],
'added_by': user['added_by_uuid'], 'max_ips': None, 'enable': None})
return users_array
# Change telegram user data format
def Telegram_users_to_dict(Tel_users_dict):
if not Tel_users_dict:
return False
users_array = []
for user in Tel_users_dict:
users_array.append({'id': user[0], 'telegram_id': user[1], 'created_at': user[3], })
return users_array
# Calculate remaining days
def calculate_remaining_days(start_date, package_days):
import datetime
import pytz
datetime_iran = datetime.datetime.now(pytz.timezone('Asia/Tehran'))
datetime_iran = datetime_iran.replace(tzinfo=None)
if start_date is None:
return package_days
start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d")
# remaining_days = package_days - (datetime.datetime.now() - start_date).days
remaining_days = package_days - (datetime_iran - start_date).days + 1
if remaining_days < 0:
return 0
return remaining_days
# Calculate remaining usage
def calculate_remaining_usage(usage_limit_GB, current_usage_GB):
remaining_usage = usage_limit_GB - current_usage_GB
return round(remaining_usage, 2)
# Calculate last online time
def calculate_remaining_last_online(last_online_date_time):
import datetime
if last_online_date_time == "0001-01-01 00:00:00.000000" or last_online_date_time == "1-01-01 00:00:00":
return AdminBot.content.MESSAGES['NEVER']
# last_online_date_time = datetime.datetime.strptime(last_online_date_time, "%Y-%m-%d %H:%M:%S.%f")
last_online_date_time = datetime.datetime.strptime(last_online_date_time, "%Y-%m-%d %H:%M:%S")
last_online_time = (datetime.datetime.now() - last_online_date_time)
last_online = AdminBot.templates.last_online_time_template(last_online_time)
return last_online
# Process users data - return list of users
def dict_process(url, users_dict, sub_id=None, server_id=None):
BASE_URL = urlparse(url,).scheme + "://" + urlparse(url,).netloc
logging.info(f"Parse users page")
if not users_dict:
return False
users_list = []
for user in users_dict:
users_list.append({
"name": user['name'],
"usage": {
'usage_limit_GB': round(user['usage_limit_GB'], 2),
'current_usage_GB': round(user['current_usage_GB'], 2),
'remaining_usage_GB': calculate_remaining_usage(user['usage_limit_GB'], user['current_usage_GB'])
},
"remaining_day": calculate_remaining_days(user['start_date'], user['package_days']),
"comment": user['comment'],
"last_connection": calculate_remaining_last_online(user['last_online']) if user['last_online'] else None,
"uuid": user['uuid'],
"link": f"{BASE_URL}/{urlparse(url).path.split('/')[1]}/{user['uuid']}/",
"mode": user['mode'],
"enable": user['enable'],
"sub_id": sub_id,
"server_id": server_id
})
return users_list
# Get single user info - return dict of user info
def user_info(url, uuid):
logging.info(f"Get info of user single user - {uuid}")
lu = api.select(url)
if not lu:
return False
for user in lu:
if user['uuid'] == uuid:
return user
return False
# Get sub links - return dict of sub links
def sub_links(uuid, url= None):
if not url:
non_order_users = USERS_DB.find_non_order_subscription(uuid=uuid)
order_users = USERS_DB.find_order_subscription(uuid=uuid)
if order_users:
order_user = order_users[0]
servers = USERS_DB.find_server(id=order_user['server_id'])
if servers:
server = servers[0]
url = server['url']
elif non_order_users:
non_order_user = non_order_users[0]
servers = USERS_DB.find_server(id=non_order_user['server_id'])
if servers:
server = servers[0]
url = server['url']
# else:
# servers = USERS_DB.select_servers()
# if servers:
# for server in servers:
# users_list = api.find(server['url'] + API_PATH, uuid)
# if users_list:
# url = server['url']
# break
BASE_URL = urlparse(url).scheme + "://" + urlparse(url).netloc
logging.info(f"Get sub links of user - {uuid}")
sub = {}
PANEL_DIR = urlparse(url).path.split('/')
# Clash open app: clash://install-config?url=
# Hidden open app: clashmeta://install-config?url=
sub['clash_configs'] = f"{BASE_URL}/{PANEL_DIR[1]}/{uuid}/clash/all.yml"
sub['hiddify_configs'] = f"{BASE_URL}/{PANEL_DIR[1]}/{uuid}/clash/meta/all.yml"
sub['sub_link'] = f"{BASE_URL}/{PANEL_DIR[1]}/{uuid}/all.txt"
sub['sub_link_b64'] = f"{BASE_URL}/{PANEL_DIR[1]}/{uuid}/all.txt?base64=True"
# Add in v8.0 Hiddify
sub['sub_link_auto'] = f"{BASE_URL}/{PANEL_DIR[1]}/{uuid}/sub/?asn=unknown"
sub['sing_box_full'] = f"{BASE_URL}/{PANEL_DIR[1]}/{uuid}/full-singbox.json?asn=unknown"
sub['sing_box'] = f"{BASE_URL}/{PANEL_DIR[1]}/{uuid}/singbox.json?asn=unknown"
return sub
# Parse sub links
def sub_parse(sub):
logging.info(f"Parse sub links")
res = get_request(sub)
if not res or res.status_code != 200:
return False
urls = re.findall(r'(vless:\/\/[^\n]+)|(vmess:\/\/[^\n]+)|(trojan:\/\/[^\n]+)', res.text)
config_links = {
'vless': [],
'vmess': [],
'trojan': []
}
for url in urls:
if url[0]:
match = re.search(r'#(.+)$', url[0])
if match:
vless_title = match.group(1).replace("%20", " ")
config_links['vless'].append([url[0], vless_title])
elif url[1]:
config = url[1].replace("vmess://", "")
config_parsed = base64decoder(config)
if config_parsed:
vmess_title = config_parsed['ps'].replace("%20", " ")
config_links['vmess'].append([url[1], vmess_title])
elif url[2]:
match = re.search(r'#(.+)$', url[2])
if match:
trojan_title = match.group(1).replace("%20", " ")
trojan_sni = re.search(r'sni=([^&]+)', url[2])
if trojan_sni:
if trojan_sni.group(1) == "fake_ip_for_sub_link":
continue
config_links['trojan'].append([url[2], match.group(1)])
return config_links
# Backup panel
def backup_panel(url):
logging.info(f"Backup panel")
BASE_URL = urlparse(url,).scheme + "://" + urlparse(url,).netloc
dir_panel = urlparse(url).path.split('/')
backup_url = f"{BASE_URL}/{dir_panel[1]}/{dir_panel[2]}/admin/backup/backupfile/"
backup_req = get_request(backup_url)
if not backup_req or backup_req.status_code != 200:
return False
now = datetime.now()
dt_string = now.strftime("%d-%m-%Y_%H-%M-%S")
file_name = f"Backup_{urlparse(url,).netloc}_{dt_string}.json"
file_name = os.path.join(BACKUP_LOC, file_name)
if not os.path.exists(BACKUP_LOC):
os.makedirs(BACKUP_LOC)
with open(file_name, 'w+') as f:
f.write(backup_req.text)
return file_name
# zip an array of files
def zip_files(files, zip_file_name,path=None):
if path:
zip_file_name = os.path.join(path, zip_file_name)
with zipfile.ZipFile(zip_file_name, 'w', zipfile.ZIP_DEFLATED) as zip_file:
for file in files:
# Get the base name of the file (i.e. the file name without the parent folders)
base_name = os.path.basename(file)
# Write the file to the zip archive with the base name as the arcname
zip_file.write(file, arcname=base_name)
return zip_file_name
# full backup
def full_backup():
files = []
servers = USERS_DB.select_servers()
for server in servers:
file_name = backup_panel(server['url'])
if file_name:
files.append(file_name)
backup_bot = backup_json_bot()
if backup_bot:
files.append(backup_bot)
if files:
now = datetime.now()
dt_string = now.strftime("%d-%m-%Y_%H-%M-%S")
zip_title = f"Backup_{dt_string}.zip"
zip_file_name = zip_files(files, zip_title,path=BACKUP_LOC)
if zip_file_name:
return zip_file_name
return False
# Extract UUID from config
def extract_uuid_from_config(config):
logging.info(f"Extract UUID from config")
uuid_pattern = r"([0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12})"
match = re.search(uuid_pattern, config)
if match:
uuid = match.group(1)
return uuid
else:
return None
# System status
def system_status():
cpu_usage = psutil.cpu_percent()
ram_usage = psutil.virtual_memory().percent
disk_usage = psutil.disk_usage('/').percent
return {
'cpu': cpu_usage,
'ram': ram_usage,
'disk': disk_usage
}
# Search user by name
def search_user_by_name(url, name):
# users = dict_process(users_to_dict(ADMIN_DB.select_users()))
users = api.select(url)
if not users:
return False
res = []
for user in users:
if name.lower() in user['name'].lower():
res.append(user)
if res:
return res
return False
# Search user by uuid
def search_user_by_uuid(url, uuid):
# users = dict_process(users_to_dict(ADMIN_DB.select_users()))
users = api.select(url)
if not users:
return False
for user in users:
if user['uuid'] == uuid:
return user
return False
# Base64 decoder
def base64decoder(s):
import base64
try:
conf = base64.b64decode(s).decode("utf-8")
conf = json.loads(conf)
except Exception as e:
conf = False
return conf
# Search user by config
def search_user_by_config(url, config):
if config.startswith("vmess://"):
config = config.replace("vmess://", "")
config = base64decoder(config)
if config:
uuid = config['id']
user = search_user_by_uuid(url, uuid)
if user:
return user
uuid = extract_uuid_from_config(config)
if uuid:
user = search_user_by_uuid(url, uuid)
if user:
return user
return False
# Check text is it config or sub
def is_it_config_or_sub(config):
if config.startswith("vmess://"):
config = config.replace("vmess://", "")
config = base64decoder(config)
if config:
return config['id']
uuid = extract_uuid_from_config(config)
if uuid:
return uuid
# Users bot add plan
def users_bot_add_plan(size, days, price, server_id,description=None):
if not CLIENT_TOKEN:
return False
# randon 4 digit number
plan_id = random.randint(10000, 99999)
plan_status = USERS_DB.add_plan(plan_id, size, days, price, server_id,description=description)
if not plan_status:
return False
return True
#--------------------------Server area ----------------------------
# add server
def add_server(url, user_limit, title=None, description=None, status=True, default_server=False):
# randon 5 digit number
#server_id = random.randint(10000, 99999)
server_status = USERS_DB.add_server(url, user_limit, title, description, status, default_server)
if not server_status:
return False
return True
# Check user is expired
def is_user_expired(user):
if user['remaining_day'] == 0:
return True
return False
# Expired users list
def expired_users_list(users):
expired_users = []
for user in users:
if is_user_expired(user):
expired_users.append(user)
return expired_users
# Text to QR code
def txt_to_qr(txt):
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=1,
)
qr.add_data(txt)
qr.make(fit=True, )
img_qr = qr.make_image(fill_color="black", back_color="white")
stream = BytesIO()
img_qr.save(stream)
img = stream.getvalue()
return img
# List of users who not ordered from bot (Link Subscription)
def non_order_user_info(telegram_id):
users_list = []
non_ordered_subscriptions = USERS_DB.find_non_order_subscription(telegram_id=telegram_id)
if non_ordered_subscriptions:
for subscription in non_ordered_subscriptions:
server_id = subscription['server_id']
server = USERS_DB.find_server(id=server_id)
if server:
server = server[0]
#if server['status']:
URL = server['url'] + API_PATH
non_order_user = api.find(URL, subscription['uuid'])
if non_order_user:
non_order_user = users_to_dict([non_order_user])
non_order_user = dict_process(URL, non_order_user, subscription['id'],server_id)
if non_order_user:
non_order_user = non_order_user[0]
users_list.append(non_order_user)
return users_list
# List of users who ordered from bot and made payment
def order_user_info(telegram_id):
users_list = []
orders = USERS_DB.find_order(telegram_id=telegram_id)
if orders:
for order in orders:
ordered_subscriptions = USERS_DB.find_order_subscription(order_id=order['id'])
if ordered_subscriptions:
for subscription in ordered_subscriptions:
server_id = subscription['server_id']
server = USERS_DB.find_server(id=server_id)
if server:
server = server[0]
#if server['status']:
URL = server['url'] + API_PATH
order_user = api.find(URL, subscription['uuid'])
if order_user:
order_user = users_to_dict([order_user])
order_user = dict_process(URL, order_user, subscription['id'], server_id)
if order_user:
order_user = order_user[0]
users_list.append(order_user)
return users_list
# Replace last three characters of a string with random numbers (For Payment)
def replace_last_three_with_random(input_string):
if len(input_string) <= 3:
return input_string # Not enough characters to replace
input_string = int(input_string)
input_string += random.randint(1000, 9999)
return str(input_string)
# random_numbers = ''.join(random.choice(string.digits) for _ in range(3))
# modified_string = input_string[:-3] + random_numbers
# return modified_string
# Privacy-friendly logging - replace your panel url with panel.private.com
def privacy_friendly_logging_request(url):
url = urlparse(url)
url = url.scheme + "://" + "panel.private.com" + url.path
return url
def all_configs_settings():
bool_configs = USERS_DB.select_bool_config()
int_configs = USERS_DB.select_int_config()
str_configs = USERS_DB.select_str_config()
# all configs to one dict
all_configs = {}
for config in bool_configs:
all_configs[config['key']] = config['value']
for config in int_configs:
all_configs[config['key']] = config['value']
for config in str_configs:
all_configs[config['key']] = config['value']
return all_configs
def find_order_subscription_by_uuid(uuid):
order_subscription = USERS_DB.find_order_subscription(uuid=uuid)
non_order_subscription = USERS_DB.find_non_order_subscription(uuid=uuid)
if order_subscription:
return order_subscription[0]
elif non_order_subscription:
return non_order_subscription[0]
else:
return False
def is_it_subscription_by_uuid_and_telegram_id(uuid, telegram_id):
subs = []
flag = False
orders = USERS_DB.find_order(telegram_id=telegram_id)
if orders:
for order in orders:
ordered_subscriptions = USERS_DB.find_order_subscription(order_id=order['id'])
if ordered_subscriptions:
for subscription in ordered_subscriptions:
if subscription['uuid'] == uuid:
flag = True
subs.append(subscription)
break
if flag == True:
break
non_order_subscriptions = USERS_DB.find_non_order_subscription(telegram_id=telegram_id)
if non_order_subscriptions:
for subscription in non_order_subscriptions:
if subscription['uuid'] == uuid:
subs.append(subscription)
break
if subs:
return True
else:
return False
def toman_to_rial(toman):
return int(toman) * 10
def rial_to_toman(rial):
return "{:,.0f}".format(int(int(rial) / 10))
def backup_json_bot():
back_dir = BOT_BACKUP_LOC
if not os.path.exists(back_dir):
os.makedirs(back_dir)
bk_json_data = USERS_DB.backup_to_json(back_dir)
if not bk_json_data:
return False
bk_json_data['version'] = __version__
now = datetime.now()
dt_string = now.strftime("%d-%m-%Y_%H-%M-%S")
bk_json_file = os.path.join(back_dir, f"Backup_Bot_{dt_string}.json")
with open(bk_json_file, 'w+') as f:
json.dump(bk_json_data, f, indent=4)
zip_file = os.path.join(back_dir, f"Backup_Bot_{dt_string}.zip")
with zipfile.ZipFile(zip_file, 'w') as zip:
zip.write(bk_json_file,os.path.basename(bk_json_file))
zip.write(USERS_DB_LOC,os.path.basename(USERS_DB_LOC))
for file in os.listdir(RECEIPTIONS_LOC):
zip.write(os.path.join(RECEIPTIONS_LOC, file),os.path.join(os.path.basename(RECEIPTIONS_LOC),file))
os.remove(bk_json_file)
return zip_file
def restore_json_bot(file):
extract_path = os.path.join(BOT_BACKUP_LOC, "tmp", os.path.basename(file).replace(".zip", ""))
if not os.path.exists(file):
return False
if not file.endswith(".zip"):
return False
try:
if not os.path.exists(extract_path):
os.makedirs(extract_path)
except Exception as e:
logging.exception(f"Exception: {e}")
return False
try:
with zipfile.ZipFile(file, 'r') as outer_zip:
# Iterate through all entries in the outer zip
for entry in outer_zip.namelist():
# Check if the entry is a zip file
if entry.lower().endswith('.zip'):
nested_zip_filename = entry
# Extract the nested zip file
with outer_zip.open(nested_zip_filename) as nested_zip_file:
# Save the nested zip file to a temporary location
nested_zip_path = os.path.join(extract_path, nested_zip_filename)
with open(nested_zip_path, 'wb') as f:
f.write(nested_zip_file.read())
# Extract contents of the nested zip file
with zipfile.ZipFile(nested_zip_path, 'r') as nested_zip:
# Check if the JSON file exists
# select json file
json_filename = None
for file in nested_zip.namelist():
if file.endswith('.json'):
json_filename = file
break
if json_filename in nested_zip.namelist():
nested_zip.extractall(extract_path)
else:
json_filename = None
for file in outer_zip.namelist():
if file.endswith('.json'):
json_filename = file
break
if json_filename in outer_zip.namelist():
outer_zip.extractall(extract_path)
except Exception as e:
logging.exception(f"Exception: {e}")
return False
bk_json_file = os.path.join(extract_path, os.path.basename(json_filename))
# with open(bk_json_file, 'r') as f:
# bk_json_data = json.load(f)
status_db = USERS_DB.restore_from_json(bk_json_file)
if not status_db:
return False
if not os.path.exists(os.path.join(extract_path, os.path.basename(RECEIPTIONS_LOC))):
os.mkdir(os.path.join(extract_path, os.path.basename(RECEIPTIONS_LOC)))
# move reception files
for file in os.listdir(os.path.join(extract_path, os.path.basename(RECEIPTIONS_LOC))):
try:
os.rename(os.path.join(extract_path, os.path.basename(RECEIPTIONS_LOC), file),
os.path.join(RECEIPTIONS_LOC, file))
except Exception as e:
logging.exception(f"Exception: {e}")
try:
# # remove tmp folder
# os.remove(bk_json_file)
# # remove RECEIPTIONS all files
# for file in os.listdir(os.path.join(extract_path, os.path.basename(RECEIPTIONS_LOC))):
# os.remove(os.path.join(extract_path, os.path.basename(RECEIPTIONS_LOC), file))
# os.rmdir(os.path.join(extract_path, os.path.basename(RECEIPTIONS_LOC)))
# # romove hidyBot.db
# os.remove(os.path.join(extract_path, os.path.basename(USERS_DB_LOC)))
shutil.rmtree(extract_path)
except Exception as e:
logging.exception(f"Exception: {e}")
return False
return True
# Debug Data
def debug_data():
bk_json_data = USERS_DB.backup_to_json(BOT_BACKUP_LOC)
if not bk_json_data:
return False
bk_json_data['version'] = __version__
new_servers = []
for server in bk_json_data['servers']:
url = privacy_friendly_logging_request(server['url'])
server['url'] = url
new_servers.append(server)
bk_json_data['servers'] = new_servers
bk_json_data['str_config'] = [x for x in bk_json_data['str_config'] if x['key'] not in ['bot_token_admin','bot_token_client']]
now = datetime.now()
dt_string = now.strftime("%d-%m-%Y_%H-%M-%S")
bk_json_file = os.path.join(BOT_BACKUP_LOC, f"DB_Data_{dt_string}.json")
with open(bk_json_file, 'w+') as f:
json.dump(bk_json_data, f, indent=4)
zip_file = os.path.join(BOT_BACKUP_LOC, f"Debug_Data_{dt_string}.zip")
with zipfile.ZipFile(zip_file, 'w') as zip:
zip.write(bk_json_file,os.path.basename(bk_json_file))
if os.path.exists(os.path.join(os.getcwd(),"bot.log")):
# only send last 1000 lines of log
with open(os.path.join(os.getcwd(),"bot.log"), 'r') as f:
lines = f.readlines()
lines = lines[-1000:]
with open(os.path.join(os.getcwd(),"bot.log"), 'w') as f:
f.writelines(lines)
zip.write("bot.log",os.path.basename("bot.log"))
if os.path.exists(LOG_DIR):
for file in os.listdir(LOG_DIR):
zip.write(os.path.join(LOG_DIR, file),file)
os.remove(bk_json_file)
return zip_file
================================================
FILE: config.py
================================================
# Description: Configuration file for the bot
import json
import logging
import os
from urllib.parse import urlparse
import requests
from termcolor import colored
# import Utils.utils
from version import __version__
# PANEL_URL, API_PATH = None, None
# Bypass proxy
os.environ['no_proxy'] = '*'
VERSION = __version__
USERS_DB_LOC = os.path.join(os.getcwd(), "Database", "hidyBot.db")
LOG_DIR = os.path.join(os.getcwd(), "Logs")
LOG_LOC = os.path.join(LOG_DIR, "hidyBot.log")
BACKUP_LOC = os.path.join(os.getcwd(), "Backup")
RECEIPTIONS_LOC = os.path.join(os.getcwd(), "UserBot", "Receiptions")
BOT_BACKUP_LOC = os.path.join(os.getcwd(), "Backup", "Bot")
API_PATH = "/api/v1"
HIDY_BOT_ID = "@HidyBotGroup"
# if directories not exists, create it
if not os.path.exists(LOG_DIR):
os.mkdir(LOG_DIR)
if not os.path.exists(BACKUP_LOC):
os.mkdir(BACKUP_LOC)
if not os.path.exists(BOT_BACKUP_LOC):
os.mkdir(BOT_BACKUP_LOC)
if not os.path.exists(RECEIPTIONS_LOC):
os.mkdir(RECEIPTIONS_LOC)
# set logging
logging.basicConfig(handlers=[logging.FileHandler(filename=LOG_LOC,
encoding='utf-8', mode='w')],
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
def setup_users_db():
# global USERS_DB
try:
if not os.path.exists(USERS_DB_LOC):
logging.error(f"Database file not found in {USERS_DB_LOC} directory!")
with open(USERS_DB_LOC, "w") as f:
pass
# USERS_DB = Database.dbManager.UserDBManager(USERS_DB_LOC)
except Exception as e:
logging.error(f"Error while connecting to database \n Error:{e}")
raise Exception(f"Error while connecting to database \nBe in touch with {HIDY_BOT_ID}")
# return USERS_DB
setup_users_db()
from Database.dbManager import UserDBManager
def load_config(db):
try:
config = db.select_str_config()
if not config:
db.set_default_configs()
config = db.select_str_config()
configs = {}
for conf in config:
configs[conf['key']] = conf['value']
return configs
except Exception as e:
logging.error(f"Error while loading config \n Error:{e}")
raise Exception(f"Error while loading config \nBe in touch with {HIDY_BOT_ID}")
def load_server_url(db):
try:
panel_url = db.select_servers()
if not panel_url:
return None
return panel_url[0]['url']
except Exception as e:
logging.error(f"Error while loading panel_url \n Error:{e}")
raise Exception(f"Error while loading panel_url \nBe in touch with {HIDY_BOT_ID}")
ADMINS_ID, TELEGRAM_TOKEN, CLIENT_TOKEN, PANEL_URL, LANG, PANEL_ADMIN_ID = None, None, None, None, None, None
def set_config_variables(configs, server_url):
if not conf['bot_admin_id'] and not conf['bot_token_admin'] and not conf['bot_lang'] or not server_url:
print(colored("Config is not set! , Please run config.py first", "red"))
raise Exception(f"Config is not set!\nBe in touch with {HIDY_BOT_ID}")
global ADMINS_ID, TELEGRAM_TOKEN, PANEL_URL, LANG, PANEL_ADMIN_ID, CLIENT_TOKEN
json_admin_ids = configs["bot_admin_id"]
ADMINS_ID = json.loads(json_admin_ids)
TELEGRAM_TOKEN = configs["bot_token_admin"]
try:
CLIENT_TOKEN = configs["bot_token_client"]
except KeyError:
CLIENT_TOKEN = None
if CLIENT_TOKEN:
setup_users_db()
PANEL_URL = server_url
LANG = configs["bot_lang"]
# PANEL_ADMIN_ID = ADMIN_DB.find_admins(uuid=urlparse(PANEL_URL).path.split('/')[2])
PANEL_ADMIN_ID = urlparse(PANEL_URL).path.split('/')[2]
if not PANEL_ADMIN_ID:
print(colored("Admin panel UUID is not valid!", "red"))
raise Exception(f"Admin panel UUID is not valid!\nBe in touch with {HIDY_BOT_ID}")
PANEL_ADMIN_ID = PANEL_ADMIN_ID[0][0]
def panel_url_validator(url):
if not (url.startswith("https://") or url.startswith("http://")):
print(colored("URL must start with http:// or https://", "red"))
return False
if url.endswith("/"):
url = url[:-1]
if url.endswith("admin"):
url = url.replace("/admin", "")
if url.endswith("admin/user"):
url = url.replace("/admin/user", "")
print(colored("Checking URL...", "yellow"))
try:
request = requests.get(f"{url}/admin/")
except requests.exceptions.ConnectionError as e:
print(colored("URL is not valid! Error in connection", "red"))
print(colored(f"Error: {e}", "red"))
return False
if request.status_code != 200:
print(colored("URL is not valid!", "red"))
print(colored(f"Error: {request.status_code}", "red"))
return False
elif request.status_code == 200:
print(colored("URL is valid!", "green"))
return url
def bot_token_validator(token):
print(colored("Checking Bot Token...", "yellow"))
try:
request = requests.get(f"https://api.telegram.org/bot{token}/getMe")
except requests.exceptions.ConnectionError:
print(colored("Bot Token is not valid! Error in connection", "red"))
return False
if request.status_code != 200:
print(colored("Bot Token is not valid!", "red"))
return False
elif request.status_code == 200:
print(colored("Bot Token is valid!", "green"))
print(colored("Bot Username:", "green"), "@"+request.json()['result']['username'])
return True
def set_by_user():
print()
print(
colored("Example: 123456789\nIf you have more than one admin, split with comma(,)\n[get it from @userinfobot]",
"yellow"))
while True:
admin_id = input("[+] Enter Telegram Admin Number IDs: ")
admin_ids = admin_id.split(',')
admin_ids = [admin_id.strip() for admin_id in admin_ids]
if not all(admin_id.isdigit() for admin_id in admin_ids):
print(colored("Admin IDs must be numbers separated by commas!", "red"))
continue
admin_ids = [int(admin_id) for admin_id in admin_ids]
break
print()
print(colored("Example: 123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ\n[get it from @BotFather]", "yellow"))
while True:
token = input("[+] Enter your Admin bot token: ")
if not token:
print(colored("Token is required", "red"))
continue
if not bot_token_validator(token):
continue
break
print()
print(colored("You can use the bot as a userbot for your clients!", "yellow"))
while True:
userbot = input("Do you want a Bot for your users? (y/n): ").lower()
if userbot not in ["y", "n"]:
print(colored("Please enter y or n!", "red"))
continue
break
if userbot == "y":
print()
print(colored("Example: 123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ\n[get it from @BotFather]", "yellow"))
while True:
client_token = input("[+] Enter your client (For Users) bot token: ")
if not client_token:
print(colored("Token is required!", "red"))
continue
if client_token == token:
print(colored("Client token must be different from Admin token!", "red"))
continue
if not bot_token_validator(client_token):
continue
break
else:
client_token = None
print()
print(colored(
"Example: https://panel.example.com/7frgemkvtE0/78854985-68dp-425c-989b-7ap0c6kr9bd4\n[exactly like this!]",
"yellow"))
while True:
url = input("[+] Enter your panel URL:")
if not url:
print(colored("URL is required!", "red"))
continue
url = panel_url_validator(url)
if not url:
continue
break
print()
print(colored("Example: EN (default: FA)\n[It is better that the language of the bot is the same as the panel]",
"yellow"))
while True:
lang = input("[+] Select your language (EN(English), FA(Persian)): ") or "FA"
if lang not in ["EN", "FA"]:
print(colored("Language must be EN or FA!", "red"))
continue
break
return admin_ids, token, url, lang, client_token
def set_config_in_db(db, admin_ids, token, url, lang, client_token):
try:
# if str_config is not exists, create it
if not db.select_str_config():
db.add_str_config("bot_admin_id", value=json.dumps(admin_ids))
db.add_str_config("bot_token_admin", value=token)
db.add_str_config("bot_token_client", value=client_token)
db.add_str_config("bot_lang", value=lang)
else:
db.edit_str_config("bot_admin_id", value=json.dumps(admin_ids))
db.edit_str_config("bot_token_admin", value=token)
db.edit_str_config("bot_token_client", value=client_token)
db.edit_str_config("bot_lang", value=lang)
# if servers is not exists, create it
if not db.select_servers():
db.add_server(url, 2000, title="Main Server", default_server=True)
else:
# find default server
default_servers = db.find_server(default_server=True)
if default_servers:
default_server_id = default_servers[0]['id']
default_server = default_servers[0]
if default_server['url'] != url:
db.edit_server(default_server_id, url=url)
else:
db.add_server(url, 2000, title="Main Server", default_server=True)
except Exception as e:
logging.error(f"Error while inserting config to database \n Error:{e}")
raise Exception(f"Error while inserting config to database \nBe in touch with {HIDY_BOT_ID}")
def print_current_conf(conf, server_url):
print()
print(colored("Current configration data:", "yellow"))
print(f"[+] Admin IDs: {conf['bot_admin_id']}")
print(f"[+] Admin Bot Token: {conf['bot_token_admin']}")
print(f"[+] Client Bot Token: {conf['bot_token_client']}")
print(f"[+] Panel URL: {server_url}")
print(f"[+] Language: {conf['bot_lang']}")
print()
if __name__ == '__main__':
db = UserDBManager(USERS_DB_LOC)
conf = load_config(db)
server_url = load_server_url(db)
if conf['bot_admin_id'] and conf['bot_token_admin'] and conf['bot_lang'] and server_url:
print("Config is already set!")
print_current_conf(conf, server_url)
print("Do you want to change config? (y/n): ")
if input().lower() == "y":
admin_ids, token, url, lang, client_token = set_by_user()
set_config_in_db(db, admin_ids, token, url, lang, client_token)
conf = load_config(db)
server_url = load_server_url(db)
set_config_variables(conf, server_url)
else:
admin_ids, token, url, lang, client_token = set_by_user()
set_config_in_db(db, admin_ids, token, url, lang, client_token)
conf = load_config(db)
server_url = load_server_url(db)
set_config_variables(conf, server_url)
# close database connection
db.close()
db = UserDBManager(USERS_DB_LOC)
db.set_default_configs()
conf = load_config(db)
server_url = load_server_url(db)
set_config_variables(conf, server_url)
db.close()
================================================
FILE: crontab.py
================================================
# Crontab
import argparse
from config import CLIENT_TOKEN
# use argparse to get the arguments
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--backup", action="store_true", help="Backup the panel")
parser.add_argument("--reminder", action="store_true", help="Send reminder to users")
args = parser.parse_args()
# run the functions based on the arguments
if args.backup:
from Cronjob.backup import cron_backup
cron_backup()
elif args.reminder:
if CLIENT_TOKEN:
from Cronjob.reminder import cron_reminder
cron_reminder()
# To run this file, use this command:
# python3 crontab.py --backup
# python3 crontab.py --reminder
================================================
FILE: hiddifyTelegramBot.py
================================================
from threading import Thread
import AdminBot.bot
from config import CLIENT_TOKEN
# Start the admin bot
if __name__ == '__main__':
Thread(target=AdminBot.bot.start).start()
# Start the user bot if the client token is set
if CLIENT_TOKEN:
import UserBot.bot
Thread(target=UserBot.bot.start).start()
================================================
FILE: install.sh
================================================
#!/bin/bash
# Define text colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
RESET='\033[0m' # Reset text color
HIDY_BOT_ID="@HidyBotGroup"
# Function to display error messages and exit
function display_error_and_exit() {
echo -e "${RED}Error: $1${RESET}"
echo -e "${YELLOW}${HIDY_BOT_ID}${RESET}"
exit 1
}
install_git_if_needed() {
if ! command -v git &>/dev/null; then
echo "Git is not installed. Installing Git..."
# Install Git based on the operating system (Linux)
if [ -f /etc/os-release ]; then
source /etc/os-release
if [ "$ID" == "ubuntu" ] || [ "$ID" == "debian" ]; then
sudo apt update
sudo apt install -y git
elif [ "$ID" == "centos" ] || [ "$ID" == "rhel" ]; then
sudo yum install -y git
fi
elif [ "$(uname -s)" == "Darwin" ]; then # macOS
brew install git
else
echo "Unsupported operating system. Please install Git manually and try again."
exit 1
fi
if ! command -v git &>/dev/null; then
echo "Failed to install Git. Please install Git manually and try again."
exit 1
fi
echo "Git has been installed successfully."
fi
}
# Function to install Python 3 and pip if they are not already installed
install_python3_and_pip_if_needed() {
if ! command -v python3 &>/dev/null || ! command -v pip &>/dev/null; then
echo "Python 3 and pip are required. Installing Python 3 and pip..."
# Install Python 3 and pip based on the operating system (Linux)
if [ -f /etc/os-release ]; then
source /etc/os-release
if [ "$ID" == "ubuntu" ] || [ "$ID" == "debian" ]; then
sudo apt update
sudo apt install -y python3 python3-pip
elif [ "$ID" == "centos" ] || [ "$ID" == "rhel" ]; then
sudo yum install -y python3 python3-pip
fi
elif [ "$(uname -s)" == "Darwin" ]; then # macOS
brew install python@3
else
echo "Unsupported operating system. Please install Python 3 and pip manually and try again."
exit 1
fi
if ! command -v python3 &>/dev/null || ! command -v pip &>/dev/null; then
echo "Failed to install Python 3 and pip. Please install Python 3 and pip manually and try again."
exit 1
fi
echo "Python 3 and pip have been installed successfully."
fi
}
echo -e "${GREEN}Step 0: Checking requirements...${RESET}"
install_git_if_needed
install_python3_and_pip_if_needed
# Check if Git is installed
if ! command -v git &>/dev/null; then
display_error_and_exit "Git is not installed. Please install Git and try again."
fi
# Check if Python 3 and pip are installed
if ! command -v python3 &>/dev/null || ! command -v pip &>/dev/null; then
display_error_and_exit "Python 3 and pip are required. Please install them and try again."
fi
echo -e "${GREEN}Step 1: Cloning the repository and changing directory...${RESET}"
repository_url="https://github.com/B3H1Z/Hiddify-Telegram-Bot.git"
install_dir="/opt/Hiddify-Telegram-Bot"
branch="main"
if [ "$0" == "--pre-release" ]; then
branch="pre-release"
fi
echo "Selected branch: $branch"
if [ -d "$install_dir" ]; then
echo "Directory $install_dir exists."
else
git clone -b "$branch" "$repository_url" "$install_dir" || display_error_and_exit "Failed to clone the repository."
fi
cd "$install_dir" || display_error_and_exit "Failed to change directory."
echo -e "${GREEN}Step 2: Installing requirements...${RESET}"
pip install -r requirements.txt || display_error_and_exit "Failed to install requirements."
echo -e "${GREEN}Step 3: Preparing ...${RESET}"
logs_dir="$install_dir/Logs"
receiptions_dir="$install_dir/UserBot/Receiptions"
create_directory_if_not_exists() {
if [ ! -d "$1" ]; then
echo "Creating directory $1"
mkdir -p "$1"
fi
}
create_directory_if_not_exists "$logs_dir"
create_directory_if_not_exists "$receiptions_dir"
chmod +x "$install_dir/restart.sh"
chmod +x "$install_dir/update.sh"
echo -e "${GREEN}Step 4: Running config.py to generate config.json...${RESET}"
python3 config.py || display_error_and_exit "Failed to run config.py."
echo -e "${GREEN}Step 5: Running the bot in the background...${RESET}"
nohup python3 hiddifyTelegramBot.py >>$install_dir/bot.log 2>&1 &
echo -e "${GREEN}Step 6: Adding cron jobs...${RESET}"
add_cron_job_if_not_exists() {
local cron_job="$1"
local current_crontab
# Normalize the cron job formatting (remove extra spaces)
cron_job=$(echo "$cron_job" | sed -e 's/^[ \t]*//' -e 's/[ \t]*$//')
# Check if the cron job already exists in the current user's crontab
current_crontab=$(crontab -l 2>/dev/null || true)
if [[ -z "$current_crontab" ]]; then
# No existing crontab, so add the new cron job
(echo "$cron_job") | crontab -
elif ! (echo "$current_crontab" | grep -Fq "$cron_job"); then
# Cron job doesn't exist, so append it to the crontab
(echo "$current_crontab"; echo "$cron_job") | crontab -
fi
}
# Add cron job for reboot
add_cron_job_if_not_exists "@reboot cd $install_dir && ./restart.sh"
# Add cron job to run every 6 hours
add_cron_job_if_not_exists "0 */6 * * * cd $install_dir && python3 crontab.py --backup"
# Add cron job to run at 12:00 PM daily
add_cron_job_if_not_exists "0 12 * * * cd $install_dir && python3 crontab.py --reminder"
echo -e "${GREEN}Waiting for a few seconds...${RESET}"
sleep 5
if pgrep -f "python3 hiddifyTelegramBot.py" >/dev/null; then
echo -e "${GREEN}The bot has been started successfully.${RESET}"
echo -e "${GREEN}Send [/start] in Telegram bot.${RESET}"
else
display_error_and_exit "Failed to start the bot. Please check for errors and try again."
fi
================================================
FILE: requirements.txt
================================================
psutil==5.9.4
pyTelegramBotAPI==4.12.0
requests==2.30.0
termcolor==2.3.0
qrcode==7.4.2
pytz==2023.3.post1
================================================
FILE: restart.sh
================================================
#!/bin/bash
# Define text colors
GREEN='\033[0;32m'
RED='\033[0;31m'
RESET='\033[0m' # Reset text color
install_dir="/opt/Hiddify-Telegram-Bot"
# Function to display error messages and exit
function display_error_and_exit() {
echo -e "${RED}Error: $1${RESET}"
exit 1
}
# Check if Python 3 is installed
if ! command -v python3 &>/dev/null; then
display_error_and_exit "Python 3 is required. Please install it and try again."
fi
# Stop the bot gracefully using SIGTERM (signal 15)
echo -e "${GREEN}Stopping the bot gracefully...${RESET}"
pkill -15 -f hiddifyTelegramBot.py
# Wait for a few seconds to allow the bot to terminate
echo "Please wait for 5 seconds ..."
sleep 5
# Start the bot and redirect output to a log file
echo -e "${GREEN}Starting the bot...${RESET}"
> $install_dir/bot.log
nohup python3 /opt/Hiddify-Telegram-Bot/hiddifyTelegramBot.py >> /opt/Hiddify-Telegram-Bot/bot.log 2>&1 &
echo -e "${GREEN}Bot has been restarted.${RESET}"
================================================
FILE: uninstall.sh
================================================
#!/bin/bash
# Define text colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
RESET='\033[0m' # Reset text color
HIDY_BOT_ID="@HidyBotGroup"
INSTALL_DIR="/opt/Hiddify-Telegram-Bot"
# Function to display error messages and exit
function display_error_and_exit() {
echo -e "${RED}Error: $1${RESET}"
echo -e "${YELLOW}${HIDY_BOT_ID}${RESET}"
exit 1
}
echo -e "${GREEN}Uninstalling the Hiddify-Telegram-Bot...${RESET}"
# Check if the installation directory exists
if [ -d "$INSTALL_DIR" ]; then
# Stop the running bot if it's still running
if pgrep -f "python3 hiddifyTelegramBot.py" >/dev/null; then
echo -e "${GREEN}Stopping the bot...${RESET}"
pkill -9 -f "hiddifyTelegramBot.py"
fi
# Remove cron jobs
echo -e "${GREEN}Removing cron jobs...${RESET}"
crontab -l | grep -v "$INSTALL_DIR" | crontab -
# Remove the installation directory
echo -e "${GREEN}Removing the installation directory...${RESET}"
rm -rf "$INSTALL_DIR"
echo -e "${GREEN}Uninstallation complete.${RESET}"
else
display_error_and_exit "The installation directory does not exist. Nothing to uninstall."
fi
================================================
FILE: update.py
================================================
import json
import sqlite3
import argparse
import logging
import os
USERS_DB_LOC = os.path.join(os.getcwd(), "Database", "hidyBot.db")
LOG_LOC = os.path.join(os.getcwd(), "Logs", "update.log")
logging.basicConfig(handlers=[logging.FileHandler(filename=LOG_LOC,
encoding='utf-8', mode='w')],
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.DEBUG)
def version():
parser = argparse.ArgumentParser(description='Update script')
# parser.add_argument("--update-v4-v5", action="store_true", help="Update database from version 4 to 5")
parser.add_argument('--current-version', type=str, help='Current version')
parser.add_argument('--target-version', type=str, help='Target version')
args = parser.parse_args()
return args
def is_version_less(version1, version2):
v1_parts = list(map(int, version1.split('.')))
v2_parts = list(map(int, version2.split('.')))
for part1, part2 in zip(v1_parts, v2_parts):
if part1 < part2:
return True
elif part1 > part2:
return False
# If both versions are identical up to the available parts
return False
conn = sqlite3.connect(USERS_DB_LOC)
def drop_columns_from_table(table_name, columns_to_drop):
try:
cur = conn.cursor()
# Create a list of column names to keep
columns_to_keep = [col for col in cur.execute(f"PRAGMA table_info({table_name});")]
columns_to_keep = [col[1] for col in columns_to_keep if col[1] not in columns_to_drop]
# Create a new table without the columns to be dropped
columns_to_keep_str = ', '.join(columns_to_keep)
cur.execute(f"CREATE TABLE new_{table_name} AS SELECT {columns_to_keep_str} FROM {table_name};")
# Drop the original table
cur.execute(f"DROP TABLE {table_name};")
# Rename the new table to the original table name
cur.execute(f"ALTER TABLE new_{table_name} RENAME TO {table_name};")
# Commit the changes to the database
conn.commit()
return True
except sqlite3.Error as e:
# Handle any database errors that may occur
logging.error("Database error: %s" % e)
return False
# main_version = __version__.split(".")[0]
# print("main_version", main_version)
# logging.info("main_version %s" % main_version)
def update_v4_v5():
print("Updating database from version v4 to v5")
logging.info("Updating database from version 4 to 5")
with sqlite3.connect(USERS_DB_LOC) as conn:
logging.info("Updating database from version 4 to 5")
print("Updating database from version 4 to 5")
# Changes in orders table
try:
cur = conn.cursor()
cur.execute("DELETE FROM orders WHERE approved = 0")
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
try:
cur = conn.cursor()
cur.execute("DELETE FROM orders WHERE approved IS NULL")
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
drop_columns_from_table('orders', ['payment_image', 'payment_method', 'approved'])
try:
cur = conn.cursor()
cur.execute("DROP TABLE owner_info")
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
# Drop settings table
try:
cur = conn.cursor()
cur.execute("DROP TABLE settings")
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
# Add test_subscription bool default 0 to users table
try:
cur = conn.cursor()
cur.execute("ALTER TABLE users ADD COLUMN test_subscription BOOLEAN DEFAULT 0")
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
# image path to basename
# move config.json to db
CONF_LOC = os.path.join(os.getcwd(), "config.json")
if os.path.exists(CONF_LOC):
with open(CONF_LOC, "r") as f:
config = json.load(f)
try:
# if str_config is not exists, create it
cur = conn.cursor()
cur.execute("CREATE TABLE IF NOT EXISTS str_config (key TEXT PRIMARY KEY, value TEXT)")
admin_ids = config["admin_id"]
admin_ids = json.dumps(admin_ids)
cur.execute("INSERT OR REPLACE INTO str_config VALUES (?, ?)", ("bot_admin_id", admin_ids))
cur.execute("INSERT OR REPLACE INTO str_config VALUES (?, ?)", ("bot_token_admin", config["token"]))
cur.execute("INSERT OR REPLACE INTO str_config VALUES (?, ?)",
("bot_token_client", config["client_token"]))
cur.execute("INSERT OR REPLACE INTO str_config VALUES (?, ?)", ("bot_lang", config["lang"]))
conn.commit()
# if servers is not exists, create it
cur.execute(
"CREATE TABLE IF NOT EXISTS servers (id INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT NOT NULL, title TEXT, description TEXT,default_server BOOLEAN NOT NULL DEFAULT 0)")
server_url = config["url"]
cur.execute("INSERT INTO servers VALUES (?,?,?,?,?)", (None, server_url, None, None,True))
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
os.remove(CONF_LOC)
def update_v5_1_0_to_v5_5_0():
print("Updating database from version v5.1.0 to v5.5.0")
logging.info("Updating database from version v5.1.0 to v5.5.0")
with sqlite3.connect(USERS_DB_LOC) as conn:
# add server_id to plans table
try:
cur = conn.cursor()
cur.execute("ALTER TABLE plans ADD COLUMN server_id INTEGER")
cur.execute("UPDATE plans SET server_id = 1")
# set foreign key FOREIGN KEY (server_id) REFERENCES server (id)
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
# add server_id to order_subscriptions table
try:
cur = conn.cursor()
cur.execute("ALTER TABLE order_subscriptions ADD COLUMN server_id INTEGER")
cur.execute("UPDATE order_subscriptions SET server_id = 1")
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
# add server_id to non_order_subscriptions table
try:
# check if server_id is exists
cur = conn.cursor()
cur.execute("ALTER TABLE non_order_subscriptions ADD COLUMN server_id INTEGER")
cur.execute("UPDATE non_order_subscriptions SET server_id = 1")
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
# add user_limit, status to servers table
try:
cur = conn.cursor()
cur.execute("ALTER TABLE servers ADD COLUMN user_limit INTEGER")
cur.execute("ALTER TABLE servers ADD COLUMN status BOOLEAN DEFAULT 1")
cur.execute("UPDATE servers SET user_limit = 2000")
cur.execute("UPDATE servers SET title = Main Server")
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
# add full_name,username to users table
try:
cur = conn.cursor()
cur.execute("ALTER TABLE users ADD COLUMN full_name TEXT NULL")
cur.execute("ALTER TABLE users ADD COLUMN username TEXT NULL")
conn.commit()
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
# remove user_name from payments table
drop_columns_from_table('payments', ['user_name'])
def update_v5_9_5_to_v6_1_0():
print("Updating database from version v5.9.5 to v6.1.0")
logging.info("Updating database from version v5.9.5 to v6.1.0")
with sqlite3.connect(USERS_DB_LOC) as conn:
# add server_id to plans table
try:
cur = conn.cursor()
# add banned column to users table
cur.execute("ALTER TABLE users ADD COLUMN banned BOOLEAN DEFAULT 0")
cur.execute("UPDATE users SET banned = 0")
except sqlite3.Error as e:
logging.error("Database error: %s" % e)
print("SQLite error:", e)
def update_by_version(current_version, target_version):
if is_version_less(current_version, target_version):
print("Updating started...")
logging.info("Updating started...")
# if current_version is less than 5, update to 5.0.0
if is_version_less(current_version, "5.0.0"):
update_v4_v5()
if is_version_less(current_version, "5.5.0"):
update_v5_1_0_to_v5_5_0()
if is_version_less(current_version, "6.1.0"):
update_v5_9_5_to_v6_1_0()
if is_version_less(current_version, "6.1.1"):
update_v5_9_5_to_v6_1_0()
else:
print("No update is needed")
logging.info("No update is needed")
if __name__ == "__main__":
args = version()
if args.current_version and args.target_version:
current_version = args.current_version
target_version = args.target_version
if current_version.find("-pre"):
current_version = current_version.split("-pre")[0]
if target_version.find("-pre"):
target_version = target_version.split("-pre")[0]
print(f"current-version: {current_version} -> target-version: {target_version}")
logging.info(f"current-version: {current_version} -> target-version: {target_version}")
update_by_version(current_version, target_version)
else:
logging.info("No update is needed")
print("No update is needed")
================================================
FILE: update.sh
================================================
#!/bin/bash
# shellcheck disable=SC2034
target_version="6.1.5"
# Define text colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[0;33m'
RESET='\033[0m' # Reset text color
install_dir="/opt/Hiddify-Telegram-Bot"
# Function to display colored messages
function display_message() {
echo -e "$1"
}
# Function to gracefully stop the bot
function stop_bot() {
display_message "${GREEN}Stopping the bot gracefully...${RESET}"
pkill -15 -f hiddifyTelegramBot.py
}
add_cron_job_if_not_exists() {
local cron_job="$1"
local current_crontab
# Normalize the cron job formatting (remove extra spaces)
cron_job=$(echo "$cron_job" | sed -e 's/^[ \t]*//' -e 's/[ \t]*$//')
# Check if the cron job already exists in the current user's crontab
current_crontab=$(crontab -l 2>/dev/null || true)
if [[ -z "$current_crontab" ]]; then
# No existing crontab, so add the new cron job
(echo "$cron_job") | crontab -
elif ! (echo "$current_crontab" | grep -Fq "$cron_job"); then
# Cron job doesn't exist, so append it to the crontab
(echo "$current_crontab"; echo "$cron_job") | crontab -
fi
}
# Function to reinstall the bot
function reinstall_bot() {
display_message "${YELLOW}This version is deprecated, and you need to reinstall the bot.${RESET}"
# Ask for confirmation
read -r -p "Do you want to reinstall the bot? [y/N] " response
case "$response" in
[yY][eE][sS]|[yY])
display_message "Reinstalling the bot..."
# Change to the installation directory
cd /opt || {
display_message "${RED}Failed to change directory to /opt.${RESET}"
exit 1
}
# Remove the old bot
rm -rf /opt/Hiddify-Telegram-Bot
# Run the installation script
bash -c "$(curl -Lfo- https://raw.githubusercontent.com/B3H1Z/Hiddify-Telegram-Bot/main/install.sh)"
display_message "${GREEN}Bot has been reinstalled.${RESET}"
;;
*)
display_message "Bot has not been reinstalled."
;;
esac
}
# current_version_first_part=$(echo "current_version" | cut -d '.' -f 1)
# target_version_first_part=$(echo "target_version" | cut -d '.' -f 1)
# if [ "$current_version_first_part" = "4" ] && [ "$target_version_first_part" = "5" ]; then
# echo "Version is 4, running update.py to update to version 5."
# python3 /opt/Hiddify-Telegram-Bot/update.py --update-v4-v5
# echo "Update.py has been run."
# else
# echo "Version is not 4."
# fi
branch="main"
if [ "$0" == "--pre-release" ]; then
branch="pre-release"
fi
echo "Selected branch: $branch"
# Function to update and restart the bot
function update_bot() {
display_message "${GREEN}Updating the bot...${RESET}"
git stash
if git pull origin "$branch"; then
pip install -r requirements.txt || display_error_and_exit "Failed to install requirements."
nohup python3 hiddifyTelegramBot.py >>bot.log 2>&1 &
display_message "${GREEN}Bot has been updated and restarted.${RESET}"
else
if git pull --rebase origin "$branch"; then
pip install -r requirements.txt || display_error_and_exit "Failed to install requirements."
> $install_dir/bot.log
nohup python3 hiddifyTelegramBot.py >>bot.log 2>&1 &
display_message "${GREEN}Bot has been updated and restarted.${RESET}"
else
display_message "${RED}Failed to update the bot. Check the Git repository for errors.${RESET}"
exit 1
fi
display_message "${RED}Failed to update the bot. Check the Git repository for errors.${RESET}"
exit 1
fi
}
# get backup of Database/hidyBot.db
function get_backup() {
display_message "${GREEN}Getting backup of Database/hidyBot.db...${RESET}"
if cp /opt/Hiddify-Telegram-Bot/Database/hidyBot.db /opt/Hiddify-Telegram-Bot/Database/hidyBot.db.bak; then
display_message "${GREEN}Backup of Database/hidyBot.db has been taken.${RESET}"
else
display_message "${RED}Failed to get backup of Database/hidyBot.db.${RESET}"
fi
}
# Stop the bot gracefully before proceeding
stop_bot
# Wait for a few seconds
display_message "Please wait for 5 seconds ..."
sleep 5
# If version.py does not exist, offer to reinstall the bot; otherwise, update it
if [ ! -f /opt/Hiddify-Telegram-Bot/version.py ]; then
reinstall_bot
else
current_version=$(python3 /opt/Hiddify-Telegram-Bot/version.py --version)
get_backup
update_bot
# Add cron job for reboot
add_cron_job_if_not_exists "@reboot cd $install_dir && ./restart.sh"
# Add cron job to run every 6 hours
add_cron_job_if_not_exists "0 */6 * * * cd $install_dir && python3 crontab.py --backup"
# Add cron job to run at 12:00 PM daily
add_cron_job_if_not_exists "0 12 * * * cd $install_dir && python3 crontab.py --reminder"
echo -e "${YELLOW}Current version: $current_version${RESET}"
echo -e "${YELLOW}Target version: $target_version${RESET}"
if python3 /opt/Hiddify-Telegram-Bot/update.py --current-version "$current_version" --target-version "$target_version"; then
echo "update.py has been run."
else
echo "update.py has not been run."
exit 1
fi
fi
================================================
FILE: version.py
================================================
import argparse
# Define the version number
__version__ = "6.1.5"
def version():
parser = argparse.ArgumentParser()
parser.add_argument("--version", action="version", version=f"{__version__}")
args = parser.parse_args()
return args
def is_version_less(version1, version2):
v1_parts = list(map(int, version1.split('.')))
v2_parts = list(map(int, version2.split('.')))
for part1, part2 in zip(v1_parts, v2_parts):
if part1 < part2:
return True
elif part1 > part2:
return False
# If both versions are identical up to the available parts
return False
if __name__ == "__main__":
version()