gitscope
← marzneshin / v0.3.0-alpha1 / app/telegram/utils/keyboard.py
https://dev.kronoz.win/r/marzneshin.git
app/telegram/utils/keyboard.py · Python
Blame Raw
  1from datetime import datetime as dt
  2from itertools import islice
  3from typing import Literal, Dict, List
  4
  5from telebot import types  # noqa
  6
  7from app.utils.system import readable_size
  8
  9
 10def chunk_dict(data: dict, size: int = 2):
 11    it = iter(data)
 12    for i in range(0, len(data), size):
 13        yield {k: data[k] for k in islice(it, size)}
 14
 15
 16class BotKeyboard:
 17
 18    @staticmethod
 19    def main_menu():
 20        keyboard = types.InlineKeyboardMarkup()
 21        keyboard.add(
 22            types.InlineKeyboardButton(text="🔁 System Info", callback_data="system"),
 23            types.InlineKeyboardButton(text="♻️ Restart Xray", callback_data="restart"),
 24        )
 25        keyboard.add(
 26            types.InlineKeyboardButton(text="👥 Users", callback_data="users:1"),
 27            types.InlineKeyboardButton(
 28                text="✏️ Edit All Users", callback_data="edit_all"
 29            ),
 30        )
 31        # keyboard.add(
 32        #    types.InlineKeyboardButton(text='➕ Create User From Template', callback_data='template_add_user'))
 33        keyboard.add(
 34            types.InlineKeyboardButton(text="➕ Create User", callback_data="add_user")
 35        )
 36        return keyboard
 37
 38    @staticmethod
 39    def edit_all_menu():
 40        keyboard = types.InlineKeyboardMarkup()
 41        keyboard.add(
 42            types.InlineKeyboardButton(
 43                text="🗑 Delete Expired", callback_data="delete_expired"
 44            ),
 45            types.InlineKeyboardButton(
 46                text="🗑 Delete Limited", callback_data="delete_limited"
 47            ),
 48        )
 49        keyboard.add(
 50            types.InlineKeyboardButton(
 51                text="🔋 Data (➕|➖)", callback_data="add_data"
 52            ),
 53            types.InlineKeyboardButton(
 54                text="📅 Time (➕|➖)", callback_data="add_time"
 55            ),
 56        )
 57        # keyboard.add(
 58        #    types.InlineKeyboardButton(text='➕ Add Inbound', callback_data='inbound_add'),
 59        #    types.InlineKeyboardButton(text='➖ Remove Inbound', callback_data='inbound_remove'))
 60        keyboard.add(types.InlineKeyboardButton(text="🔙 Back", callback_data="cancel"))
 61        return keyboard
 62
 63    # @staticmethod
 64    # def inbounds_menu(action, inbounds):
 65    #    keyboard = types.InlineKeyboardMarkup()
 66    #    for inbound in inbounds:
 67    #        keyboard.add(types.InlineKeyboardButton(text=inbound, callback_data=f'confirm_{action}:{inbound}'))
 68    #    keyboard.add(types.InlineKeyboardButton(text='🔙 Back', callback_data='cancel'))
 69    #    return keyboard
 70
 71    @staticmethod
 72    def random_username(template_id: str = ""):
 73        keyboard = types.InlineKeyboardMarkup()
 74
 75        keyboard.add(
 76            types.InlineKeyboardButton(
 77                text="🔡 Random Username", callback_data=f"random:{template_id}"
 78            )
 79        )
 80        keyboard.add(
 81            types.InlineKeyboardButton(text="🔙 Cancel", callback_data="cancel")
 82        )
 83        return keyboard
 84
 85    @staticmethod
 86    def user_menu(user_info, with_back: bool = True, page: int = 1, note: bool = False):
 87        keyboard = types.InlineKeyboardMarkup()
 88        keyboard.add(
 89            types.InlineKeyboardButton(
 90                text="❌ Disable" if user_info["status"] == "active" else "✅ Activate",
 91                callback_data=f"{'suspend' if user_info['status'] == 'active' else 'activate'}:{user_info['username']}",
 92            ),
 93            types.InlineKeyboardButton(
 94                text="🗑 Delete", callback_data=f"delete:{user_info['username']}"
 95            ),
 96        )
 97        if note:
 98            keyboard.add(
 99                types.InlineKeyboardButton(
100                    text="🚫 Revoke Sub",
101                    callback_data=f"revoke_sub:{user_info['username']}",
102                ),
103                types.InlineKeyboardButton(
104                    text="✏️ Edit", callback_data=f"edit:{user_info['username']}"
105                ),
106            )
107            keyboard.add(
108                types.InlineKeyboardButton(
109                    text="📝 Edit Note",
110                    callback_data=f"edit_note:{user_info['username']}",
111                ),
112                types.InlineKeyboardButton(
113                    text="📡 Links", callback_data=f"links:{user_info['username']}"
114                ),
115            )
116        else:
117            keyboard.add(
118                types.InlineKeyboardButton(
119                    text="📡 Links", callback_data=f"links:{user_info['username']}"
120                ),
121                types.InlineKeyboardButton(
122                    text="✏️ Edit", callback_data=f"edit:{user_info['username']}"
123                ),
124            )
125        keyboard.add(
126            types.InlineKeyboardButton(
127                text="🔁 Reset usage",
128                callback_data=f"reset_usage:{user_info['username']}",
129            ),
130            types.InlineKeyboardButton(
131                text="🔋 Charge", callback_data=f"charge:{user_info['username']}"
132            ),
133        )
134        if with_back:
135            keyboard.add(
136                types.InlineKeyboardButton(
137                    text="🔙 Back", callback_data=f"users:{page}"
138                )
139            )
140        return keyboard
141
142    @staticmethod
143    def show_links(username: str):
144        keyboard = types.InlineKeyboardMarkup()
145
146        keyboard.add(
147            types.InlineKeyboardButton(
148                text="🖼 QR code", callback_data=f"genqr:{username}"
149            )
150        )
151        keyboard.add(
152            types.InlineKeyboardButton(text="🔙 Back", callback_data=f"user:{username}")
153        )
154        return keyboard
155
156    @staticmethod
157    def subscription_page(sub_url: str):
158        keyboard = types.InlineKeyboardMarkup()
159        if sub_url[:4] == "http":
160            keyboard.add(
161                types.InlineKeyboardButton(text="🚀 Subscription Page", url=sub_url)
162            )
163        return keyboard
164
165    @staticmethod
166    def confirm_action(action: str, username: str = None):
167        keyboard = types.InlineKeyboardMarkup()
168        keyboard.add(
169            types.InlineKeyboardButton(
170                text="Yes", callback_data=f"{action}:{username}"
171            ),
172            types.InlineKeyboardButton(text="No", callback_data=f"cancel"),
173        )
174        return keyboard
175
176    @staticmethod
177    def inline_cancel_action(callback_data: str = "cancel"):
178        keyboard = types.InlineKeyboardMarkup()
179        keyboard.add(
180            types.InlineKeyboardButton(text="🔙 Cancel", callback_data=callback_data)
181        )
182        return keyboard
183
184    @staticmethod
185    def user_list(users: list, page: int, total_pages: int):
186        keyboard = types.InlineKeyboardMarkup()
187        if len(users) >= 2:
188            users = [p for p in users]
189            users = [users[i : i + 2] for i in range(0, len(users), 2)]
190        else:
191            users = [users]
192        for user in users:
193            row = []
194            for p in user:
195                status = {
196                    "active": "✅",
197                    "expired": "🕰",
198                    "limited": "📵",
199                    "disabled": "❌",
200                }
201                row.append(
202                    types.InlineKeyboardButton(
203                        text=f"{p.username} ({status[p.status]})",
204                        callback_data=f"user:{p.username}:{page}",
205                    )
206                )
207            keyboard.row(*row)
208        # if there is more than one page
209        if total_pages > 1:
210            if page > 1:
211                keyboard.add(
212                    types.InlineKeyboardButton(
213                        text="⬅️ Previous", callback_data=f"users:{page - 1}"
214                    )
215                )
216            if page < total_pages:
217                keyboard.add(
218                    types.InlineKeyboardButton(
219                        text="➡️ Next", callback_data=f"users:{page + 1}"
220                    )
221                )
222        keyboard.add(types.InlineKeyboardButton(text="🔙 Back", callback_data="cancel"))
223        return keyboard
224
225    @staticmethod
226    def select_services(
227        services,
228        selected_services: List[int],
229        action: Literal["edit", "create"],
230        username: str = None,
231        data_limit: float = None,
232        expire_date: dt = None,
233    ):
234
235        keyboard = types.InlineKeyboardMarkup()
236
237        if action == "edit":
238            keyboard.add(
239                types.InlineKeyboardButton(
240                    text="⚠️ Data Limit:", callback_data=f"help_edit"
241                )
242            )
243            keyboard.add(
244                types.InlineKeyboardButton(
245                    text=f"{readable_size(data_limit) if data_limit else 'Unlimited'}",
246                    callback_data=f"help_edit",
247                ),
248                types.InlineKeyboardButton(
249                    text="✏️ Edit", callback_data=f"edit_user:{username}:data"
250                ),
251            )
252            keyboard.add(
253                types.InlineKeyboardButton(
254                    text="📅 Expire Date:", callback_data=f"help_edit"
255                )
256            )
257            keyboard.add(
258                types.InlineKeyboardButton(
259                    text=f"{expire_date.strftime('%Y-%m-%d') if expire_date else 'Never'}",
260                    callback_data=f"help_edit",
261                ),
262                types.InlineKeyboardButton(
263                    text="✏️ Edit", callback_data=f"edit_user:{username}:expire"
264                ),
265            )
266        for s in services:
267            keyboard.add(
268                types.InlineKeyboardButton(
269                    text=f"🌐 {s.name} {'✅' if s.id in selected_services else '❌'}",
270                    callback_data=f"switch_service:{s.id}:{action}",
271                )
272            )
273        keyboard.add(
274            types.InlineKeyboardButton(
275                text="Done",
276                callback_data="edit_user_done" if action == "edit" else "add_user_done",
277            )
278        )
279        keyboard.add(
280            types.InlineKeyboardButton(
281                text="Cancel",
282                callback_data=f"user:{username}" if action == "edit" else "cancel",
283            )
284        )
285
286        return keyboard