from datetime import datetime as dt from itertools import islice from typing import Literal, Dict, List from telebot import types # noqa from app.utils.system import readable_size def chunk_dict(data: dict, size: int = 2): it = iter(data) for i in range(0, len(data), size): yield {k: data[k] for k in islice(it, size)} class BotKeyboard: @staticmethod def main_menu(): keyboard = types.InlineKeyboardMarkup() keyboard.add( types.InlineKeyboardButton(text='🔁 System Info', callback_data='system'), types.InlineKeyboardButton(text='♻️ Restart Xray', callback_data='restart')) keyboard.add( types.InlineKeyboardButton(text='👥 Users', callback_data='users:1'), types.InlineKeyboardButton(text='✏️ Edit All Users', callback_data='edit_all')) #keyboard.add( # types.InlineKeyboardButton(text='➕ Create User From Template', callback_data='template_add_user')) keyboard.add( types.InlineKeyboardButton(text='➕ Create User', callback_data='add_user')) return keyboard @staticmethod def edit_all_menu(): keyboard = types.InlineKeyboardMarkup() keyboard.add( types.InlineKeyboardButton(text='🗑 Delete Expired', callback_data='delete_expired'), types.InlineKeyboardButton(text='🗑 Delete Limited', callback_data='delete_limited')) keyboard.add( types.InlineKeyboardButton(text='🔋 Data (➕|➖)', callback_data='add_data'), types.InlineKeyboardButton(text='📅 Time (➕|➖)', callback_data='add_time')) #keyboard.add( # types.InlineKeyboardButton(text='➕ Add Inbound', callback_data='inbound_add'), # types.InlineKeyboardButton(text='➖ Remove Inbound', callback_data='inbound_remove')) keyboard.add(types.InlineKeyboardButton(text='🔙 Back', callback_data='cancel')) return keyboard #@staticmethod #def inbounds_menu(action, inbounds): # keyboard = types.InlineKeyboardMarkup() # for inbound in inbounds: # keyboard.add(types.InlineKeyboardButton(text=inbound, callback_data=f'confirm_{action}:{inbound}')) # keyboard.add(types.InlineKeyboardButton(text='🔙 Back', callback_data='cancel')) # return keyboard @staticmethod def random_username(template_id: str = ''): keyboard = types.InlineKeyboardMarkup() keyboard.add(types.InlineKeyboardButton( text='🔡 Random Username', callback_data=f'random:{template_id}')) keyboard.add(types.InlineKeyboardButton( text='🔙 Cancel', callback_data='cancel')) return keyboard @staticmethod def user_menu(user_info, with_back: bool = True, page: int = 1, note: bool = False): keyboard = types.InlineKeyboardMarkup() keyboard.add( types.InlineKeyboardButton( text='❌ Disable' if user_info['status'] == 'active' else '✅ Activate', callback_data=f"{'suspend' if user_info['status'] == 'active' else 'activate'}:{user_info['username']}" ), types.InlineKeyboardButton( text='🗑 Delete', callback_data=f"delete:{user_info['username']}" ), ) if note: keyboard.add( types.InlineKeyboardButton( text='🚫 Revoke Sub', callback_data=f"revoke_sub:{user_info['username']}"), types.InlineKeyboardButton( text='✏️ Edit', callback_data=f"edit:{user_info['username']}")) keyboard.add( types.InlineKeyboardButton( text='📝 Edit Note', callback_data=f"edit_note:{user_info['username']}"), types.InlineKeyboardButton( text='📡 Links', callback_data=f"links:{user_info['username']}")) else: keyboard.add( types.InlineKeyboardButton( text='📡 Links', callback_data=f"links:{user_info['username']}"), types.InlineKeyboardButton( text='✏️ Edit', callback_data=f"edit:{user_info['username']}")) keyboard.add( types.InlineKeyboardButton( text='🔁 Reset usage', callback_data=f"reset_usage:{user_info['username']}" ), types.InlineKeyboardButton( text='🔋 Charge', callback_data=f"charge:{user_info['username']}" ) ) if with_back: keyboard.add( types.InlineKeyboardButton( text='🔙 Back', callback_data=f'users:{page}' ) ) return keyboard @staticmethod def show_links(username: str): keyboard = types.InlineKeyboardMarkup() keyboard.add( types.InlineKeyboardButton( text="🖼 QR code", callback_data=f'genqr:{username}' ) ) keyboard.add( types.InlineKeyboardButton( text='🔙 Back', callback_data=f'user:{username}' ) ) return keyboard @staticmethod def subscription_page(sub_url: str): keyboard = types.InlineKeyboardMarkup() if sub_url[:4] == 'http': keyboard.add(types.InlineKeyboardButton( text='🚀 Subscription Page', url=sub_url)) return keyboard @staticmethod def confirm_action(action: str, username: str = None): keyboard = types.InlineKeyboardMarkup() keyboard.add( types.InlineKeyboardButton( text='Yes', callback_data=f"{action}:{username}" ), types.InlineKeyboardButton( text='No', callback_data=f"cancel" ) ) return keyboard @staticmethod def inline_cancel_action(callback_data: str = "cancel"): keyboard = types.InlineKeyboardMarkup() keyboard.add( types.InlineKeyboardButton( text="🔙 Cancel", callback_data=callback_data ) ) return keyboard @staticmethod def user_list(users: list, page: int, total_pages: int): keyboard = types.InlineKeyboardMarkup() if len(users) >= 2: users = [p for p in users] users = [users[i:i + 2] for i in range(0, len(users), 2)] else: users = [users] for user in users: row = [] for p in user: status = { 'active': '✅', 'expired': '🕰', 'limited': '📵', 'disabled': '❌' } row.append(types.InlineKeyboardButton( text=f"{p.username} ({status[p.status]})", callback_data=f'user:{p.username}:{page}' )) keyboard.row(*row) # if there is more than one page if total_pages > 1: if page > 1: keyboard.add( types.InlineKeyboardButton( text="⬅️ Previous", callback_data=f'users:{page - 1}' ) ) if page < total_pages: keyboard.add( types.InlineKeyboardButton( text="➡️ Next", callback_data=f'users:{page + 1}' ) ) keyboard.add( types.InlineKeyboardButton( text='🔙 Back', callback_data='cancel' ) ) return keyboard @staticmethod def select_services(services, selected_services: List[int], action: Literal["edit", "create"], username: str = None, data_limit: float = None, expire_date: dt = None): keyboard = types.InlineKeyboardMarkup() if action == "edit": keyboard.add( types.InlineKeyboardButton( text="⚠️ Data Limit:", callback_data=f"help_edit" ) ) keyboard.add( types.InlineKeyboardButton( text=f"{readable_size(data_limit) if data_limit else 'Unlimited'}", callback_data=f"help_edit" ), types.InlineKeyboardButton( text="✏️ Edit", callback_data=f"edit_user:{username}:data" ) ) keyboard.add( types.InlineKeyboardButton( text="📅 Expire Date:", callback_data=f"help_edit" ) ) keyboard.add( types.InlineKeyboardButton( text=f"{expire_date.strftime('%Y-%m-%d') if expire_date else 'Never'}", callback_data=f"help_edit" ), types.InlineKeyboardButton( text="✏️ Edit", callback_data=f"edit_user:{username}:expire" ) ) for s in services: keyboard.add( types.InlineKeyboardButton( text=f"🌐 {s.name} {'✅' if s.id in selected_services else '❌'}", callback_data=f"switch_service:{s.id}:{action}" ) ) keyboard.add( types.InlineKeyboardButton( text='Done', callback_data='edit_user_done' if action == "edit" else 'add_user_done' ) ) keyboard.add( types.InlineKeyboardButton( text='Cancel', callback_data=f'user:{username}' if action == "edit" else 'cancel' ) ) return keyboard