gitscope
https://dev.kronoz.win/r/marzneshin.git
app/telegram/handlers/admin.py · v0.2.0
Source
1 a47eb4c Dawsh 2y ago import io
2 a47eb4c Dawsh 2y ago import math
3 a47eb4c Dawsh 2y ago import re
4 a47eb4c Dawsh 2y ago import random
5 a47eb4c Dawsh 2y ago import string
6 a47eb4c Dawsh 2y ago import os
7 a47eb4c Dawsh 2y ago from datetime import datetime
8 a47eb4c Dawsh 2y ago
9 a47eb4c Dawsh 2y ago import qrcode
10 a47eb4c Dawsh 2y ago import sqlalchemy
11 a47eb4c Dawsh 2y ago from dateutil.relativedelta import relativedelta
12 a47eb4c Dawsh 2y ago from telebot import types
13 a47eb4c Dawsh 2y ago from telebot.util import user_link
14 a47eb4c Dawsh 2y ago from telebot.asyncio_handler_backends import State, StatesGroup
15 a47eb4c Dawsh 2y ago
16 a47eb4c Dawsh 2y ago from app.db import GetDB, crud
17 a47eb4c Dawsh 2y ago from app.models.user import (UserCreate, UserModify, UserResponse, UserStatus,
18 a47eb4c Dawsh 2y ago UserStatusModify)
19 a47eb4c Dawsh 2y ago from app.models.proxy import ProxyTypes
20 a47eb4c Dawsh 2y ago from app.telegram import bot
21 9bfa731 Dawsh 2y ago from app.telegram.utils.custom_filters import (query_equals,
22 9bfa731 Dawsh 2y ago query_startswith)
23 a47eb4c Dawsh 2y ago from app.telegram.utils.keyboard import BotKeyboard
24 a47eb4c Dawsh 2y ago from app.utils.store import MemoryStorage
25 a47eb4c Dawsh 2y ago from app.utils.system import cpu_usage, memory_usage, readable_size
26 a47eb4c Dawsh 2y ago
27 a47eb4c Dawsh 2y ago try:
28 a47eb4c Dawsh 2y ago from app.utils.system import realtime_bandwith as realtime_bandwidth
29 a47eb4c Dawsh 2y ago except ImportError:
30 a47eb4c Dawsh 2y ago from app.utils.system import realtime_bandwidth
31 a47eb4c Dawsh 2y ago
32 a47eb4c Dawsh 2y ago from config import TELEGRAM_LOGGER_CHANNEL_ID, TELEGRAM_DEFAULT_VLESS_FLOW
33 a47eb4c Dawsh 2y ago
34 a47eb4c Dawsh 2y ago mem_store = MemoryStorage()
35 a47eb4c Dawsh 2y ago
36 a47eb4c Dawsh 2y ago class botStates(StatesGroup):
37 a47eb4c Dawsh 2y ago start = State()
38 a47eb4c Dawsh 2y ago add_data = State() # statesgroup should contain states
39 a47eb4c Dawsh 2y ago add_time = State()
40 a47eb4c Dawsh 2y ago edit_user_data_limit = State()
41 a47eb4c Dawsh 2y ago edit_user_expire = State()
42 a47eb4c Dawsh 2y ago edit_note = State()
43 9bfa731 Dawsh 2y ago # add_user_from_template = State()
44 a47eb4c Dawsh 2y ago add_user_username = State()
45 a47eb4c Dawsh 2y ago add_user_data_limit = State()
46 a47eb4c Dawsh 2y ago add_user_expire = State()
47 a47eb4c Dawsh 2y ago
48 a47eb4c Dawsh 2y ago
49 a47eb4c Dawsh 2y ago def get_system_info():
50 a47eb4c Dawsh 2y ago mem = memory_usage()
51 a47eb4c Dawsh 2y ago cpu = cpu_usage()
52 a47eb4c Dawsh 2y ago with GetDB() as db:
53 a47eb4c Dawsh 2y ago bandwidth = crud.get_system_usage(db)
54 a47eb4c Dawsh 2y ago total_users = crud.get_users_count(db)
55 a47eb4c Dawsh 2y ago users_active = crud.get_users_count(db, UserStatus.active)
56 a47eb4c Dawsh 2y ago return """\
57 a47eb4c Dawsh 2y ago 🎛 *CPU Cores*: `{cpu_cores}`
58 a47eb4c Dawsh 2y ago 🖥 *CPU Usage*: `{cpu_percent}%`
59 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖
60 a47eb4c Dawsh 2y ago 📊 *Total Memory*: `{total_memory}`
61 a47eb4c Dawsh 2y ago 📈 *In Use Memory*: `{used_memory}`
62 a47eb4c Dawsh 2y ago 📉 *Free Memory*: `{free_memory}`
63 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖
64 a47eb4c Dawsh 2y ago ⬇️ *Download Usage*: `{down_bandwidth}`
65 a47eb4c Dawsh 2y ago ⬆️ *Upload Usage*: `{up_bandwidth}`
66 a47eb4c Dawsh 2y ago ↕️ *Total Usage*: `{total_bandwidth}`
67 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖
68 a47eb4c Dawsh 2y ago 👥 *Total Users*: `{total_users}`
69 a47eb4c Dawsh 2y ago 🟢 *Active Users*: `{active_users}`
70 a47eb4c Dawsh 2y ago 🔴 *Deactivate Users*: `{deactivate_users}`
71 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖
72 a47eb4c Dawsh 2y ago ⏫ *Upload Speed*: `{up_speed}`
73 a47eb4c Dawsh 2y ago ⏬ *Download Speed*: `{down_speed}`
74 a47eb4c Dawsh 2y ago """.format(
75 a47eb4c Dawsh 2y ago cpu_cores=cpu.cores,
76 a47eb4c Dawsh 2y ago cpu_percent=cpu.percent,
77 a47eb4c Dawsh 2y ago total_memory=readable_size(mem.total),
78 a47eb4c Dawsh 2y ago used_memory=readable_size(mem.used),
79 a47eb4c Dawsh 2y ago free_memory=readable_size(mem.free),
80 a47eb4c Dawsh 2y ago total_bandwidth=readable_size(bandwidth.uplink + bandwidth.downlink),
81 a47eb4c Dawsh 2y ago up_bandwidth=readable_size(bandwidth.uplink),
82 a47eb4c Dawsh 2y ago down_bandwidth=readable_size(bandwidth.downlink),
83 a47eb4c Dawsh 2y ago total_users=total_users,
84 a47eb4c Dawsh 2y ago active_users=users_active,
85 a47eb4c Dawsh 2y ago deactivate_users=total_users - users_active,
86 a47eb4c Dawsh 2y ago up_speed=readable_size(realtime_bandwidth().outgoing_bytes),
87 a47eb4c Dawsh 2y ago down_speed=readable_size(realtime_bandwidth().incoming_bytes)
88 a47eb4c Dawsh 2y ago )
89 a47eb4c Dawsh 2y ago
90 a47eb4c Dawsh 2y ago
91 a47eb4c Dawsh 2y ago def schedule_delete_message(chat_id, *message_ids: int) -> None:
92 a47eb4c Dawsh 2y ago messages: list[int] = mem_store.get(f"{chat_id}:messages_to_delete", [])
93 a47eb4c Dawsh 2y ago for mid in message_ids:
94 a47eb4c Dawsh 2y ago messages.append(mid)
95 a47eb4c Dawsh 2y ago mem_store.set(f"{chat_id}:messages_to_delete", messages)
96 a47eb4c Dawsh 2y ago
97 a47eb4c Dawsh 2y ago
98 a47eb4c Dawsh 2y ago async def cleanup_messages(chat_id: int) -> None:
99 a47eb4c Dawsh 2y ago messages: list[int] = mem_store.get(f"{chat_id}:messages_to_delete", [])
100 a47eb4c Dawsh 2y ago for message_id in messages:
101 a47eb4c Dawsh 2y ago try: await bot.delete_message(chat_id, message_id)
102 a47eb4c Dawsh 2y ago except: pass
103 a47eb4c Dawsh 2y ago mem_store.set(f"{chat_id}:messages_to_delete", [])
104 a47eb4c Dawsh 2y ago
105 a47eb4c Dawsh 2y ago
106 a47eb4c Dawsh 2y ago @bot.message_handler(commands=['start', 'help'], is_admin=True)
107 a47eb4c Dawsh 2y ago async def help_command(message: types.Message):
108 a47eb4c Dawsh 2y ago await cleanup_messages(message.chat.id)
109 a47eb4c Dawsh 2y ago # bot.clear_step_handler_by_chat_id(message.chat.id)
110 a47eb4c Dawsh 2y ago await bot.delete_state(message.from_user.id, message.chat.id)
111 a47eb4c Dawsh 2y ago return await bot.reply_to(message, """
112 a47eb4c Dawsh 2y ago {user_link} Welcome to Marzban Telegram-Bot Admin Panel.
113 a47eb4c Dawsh 2y ago Here you can manage your users and proxies.
114 a47eb4c Dawsh 2y ago To get started, use the buttons below.
115 a47eb4c Dawsh 2y ago """.format(
116 a47eb4c Dawsh 2y ago user_link=user_link(message.from_user)
117 a47eb4c Dawsh 2y ago ), parse_mode="html", reply_markup=BotKeyboard.main_menu())
118 a47eb4c Dawsh 2y ago
119 a47eb4c Dawsh 2y ago
120 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals('system'), is_admin=True)
121 a47eb4c Dawsh 2y ago async def system_command(call: types.CallbackQuery):
122 a47eb4c Dawsh 2y ago return await bot.edit_message_text(
123 a47eb4c Dawsh 2y ago get_system_info(),
124 a47eb4c Dawsh 2y ago call.message.chat.id,
125 a47eb4c Dawsh 2y ago call.message.message_id,
126 a47eb4c Dawsh 2y ago parse_mode="MarkdownV2",
127 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.main_menu()
128 a47eb4c Dawsh 2y ago )
129 a47eb4c Dawsh 2y ago
130 a47eb4c Dawsh 2y ago
131 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals('restart'), is_admin=True)
132 a47eb4c Dawsh 2y ago async def restart_command(call: types.CallbackQuery):
133 a47eb4c Dawsh 2y ago await bot.edit_message_text(
134 a47eb4c Dawsh 2y ago '⚠️ Are you sure? This will restart Xray core.',
135 a47eb4c Dawsh 2y ago call.message.chat.id,
136 a47eb4c Dawsh 2y ago call.message.message_id,
137 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.confirm_action(action='do_restart')
138 a47eb4c Dawsh 2y ago )
139 a47eb4c Dawsh 2y ago
140 a47eb4c Dawsh 2y ago
141 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('delete:'), is_admin=True)
142 a47eb4c Dawsh 2y ago async def delete_user_command(call: types.CallbackQuery):
143 a47eb4c Dawsh 2y ago username = call.data.split(':')[1]
144 a47eb4c Dawsh 2y ago await bot.edit_message_text(
145 a47eb4c Dawsh 2y ago f'⚠️ Are you sure? This will delete user `{username}`.',
146 a47eb4c Dawsh 2y ago call.message.chat.id,
147 a47eb4c Dawsh 2y ago call.message.message_id,
148 a47eb4c Dawsh 2y ago parse_mode="markdown",
149 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.confirm_action(
150 9bfa731 Dawsh 2y ago action='do_delete', username=username)
151 a47eb4c Dawsh 2y ago )
152 a47eb4c Dawsh 2y ago
153 a47eb4c Dawsh 2y ago
154 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("suspend:"), is_admin=True)
155 a47eb4c Dawsh 2y ago async def suspend_user_command(call: types.CallbackQuery):
156 a47eb4c Dawsh 2y ago username = call.data.split(":")[1]
157 a47eb4c Dawsh 2y ago await bot.edit_message_text(
158 a47eb4c Dawsh 2y ago f"⚠️ Are you sure? This will suspend user `{username}`.",
159 a47eb4c Dawsh 2y ago call.message.chat.id,
160 a47eb4c Dawsh 2y ago call.message.message_id,
161 a47eb4c Dawsh 2y ago parse_mode="markdown",
162 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.confirm_action(
163 9bfa731 Dawsh 2y ago action="do_suspend", username=username),
164 a47eb4c Dawsh 2y ago )
165 a47eb4c Dawsh 2y ago
166 a47eb4c Dawsh 2y ago
167 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("activate:"), is_admin=True)
168 a47eb4c Dawsh 2y ago async def activate_user_command(call: types.CallbackQuery):
169 a47eb4c Dawsh 2y ago username = call.data.split(":")[1]
170 a47eb4c Dawsh 2y ago await bot.edit_message_text(
171 a47eb4c Dawsh 2y ago f"⚠️ Are you sure? This will activate user `{username}`.",
172 a47eb4c Dawsh 2y ago call.message.chat.id,
173 a47eb4c Dawsh 2y ago call.message.message_id,
174 a47eb4c Dawsh 2y ago parse_mode="markdown",
175 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.confirm_action(
176 9bfa731 Dawsh 2y ago action="do_activate", username=username),
177 a47eb4c Dawsh 2y ago )
178 a47eb4c Dawsh 2y ago
179 a47eb4c Dawsh 2y ago
180 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("reset_usage:"), is_admin=True)
181 a47eb4c Dawsh 2y ago async def reset_usage_user_command(call: types.CallbackQuery):
182 a47eb4c Dawsh 2y ago username = call.data.split(":")[1]
183 a47eb4c Dawsh 2y ago await bot.edit_message_text(
184 a47eb4c Dawsh 2y ago f"⚠️ Are you sure? This will Reset Usage of user `{username}`.",
185 a47eb4c Dawsh 2y ago call.message.chat.id,
186 a47eb4c Dawsh 2y ago call.message.message_id,
187 a47eb4c Dawsh 2y ago parse_mode="markdown",
188 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.confirm_action(
189 9bfa731 Dawsh 2y ago action="do_reset_usage", username=username),
190 a47eb4c Dawsh 2y ago )
191 a47eb4c Dawsh 2y ago
192 a47eb4c Dawsh 2y ago
193 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals('edit_all'), is_admin=True)
194 a47eb4c Dawsh 2y ago async def edit_all_command(call: types.CallbackQuery):
195 a47eb4c Dawsh 2y ago with GetDB() as db:
196 a47eb4c Dawsh 2y ago total_users = crud.get_users_count(db)
197 a47eb4c Dawsh 2y ago active_users = crud.get_users_count(db, UserStatus.active)
198 a47eb4c Dawsh 2y ago disabled_users = crud.get_users_count(db, UserStatus.disabled)
199 a47eb4c Dawsh 2y ago expired_users = crud.get_users_count(db, UserStatus.expired)
200 a47eb4c Dawsh 2y ago limited_users = crud.get_users_count(db, UserStatus.limited)
201 a47eb4c Dawsh 2y ago text = f'''
202 a47eb4c Dawsh 2y ago 👥 *Total Users*: `{total_users}`
203 a47eb4c Dawsh 2y ago ✅ *Active Users*: `{active_users}`
204 a47eb4c Dawsh 2y ago ❌ *Disabled Users*: `{disabled_users}`
205 a47eb4c Dawsh 2y ago 🕰 *Expired Users*: `{expired_users}`
206 a47eb4c Dawsh 2y ago 🪫 *Limited Users*: `{limited_users}`'''
207 a47eb4c Dawsh 2y ago return await bot.edit_message_text(
208 a47eb4c Dawsh 2y ago text,
209 a47eb4c Dawsh 2y ago call.message.chat.id,
210 a47eb4c Dawsh 2y ago call.message.message_id,
211 a47eb4c Dawsh 2y ago parse_mode="markdown",
212 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.edit_all_menu()
213 a47eb4c Dawsh 2y ago )
214 a47eb4c Dawsh 2y ago
215 a47eb4c Dawsh 2y ago
216 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals('delete_expired'), is_admin=True)
217 a47eb4c Dawsh 2y ago async def delete_expired_command(call: types.CallbackQuery):
218 a47eb4c Dawsh 2y ago await bot.edit_message_text(
219 a47eb4c Dawsh 2y ago f"⚠️ Are you sure? This will *DELETE All Expired Users*‼️",
220 a47eb4c Dawsh 2y ago call.message.chat.id,
221 a47eb4c Dawsh 2y ago call.message.message_id,
222 a47eb4c Dawsh 2y ago parse_mode="markdown",
223 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.confirm_action(action="do_delete_expired"))
224 a47eb4c Dawsh 2y ago
225 a47eb4c Dawsh 2y ago
226 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals('delete_limited'), is_admin=True)
227 a47eb4c Dawsh 2y ago async def delete_limited_command(call: types.CallbackQuery):
228 a47eb4c Dawsh 2y ago await bot.edit_message_text(
229 a47eb4c Dawsh 2y ago f"⚠️ Are you sure? This will *DELETE All Limited Users*‼️",
230 a47eb4c Dawsh 2y ago call.message.chat.id,
231 a47eb4c Dawsh 2y ago call.message.message_id,
232 a47eb4c Dawsh 2y ago parse_mode="markdown",
233 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.confirm_action(action="do_delete_limited"))
234 a47eb4c Dawsh 2y ago
235 a47eb4c Dawsh 2y ago
236 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals('add_data'), is_admin=True)
237 a47eb4c Dawsh 2y ago async def add_data_command(call: types.CallbackQuery):
238 a47eb4c Dawsh 2y ago msg = await bot.edit_message_text(
239 a47eb4c Dawsh 2y ago f"🔋 Enter Data Limit to increase or decrease (GB):",
240 a47eb4c Dawsh 2y ago call.message.chat.id,
241 a47eb4c Dawsh 2y ago call.message.message_id,
242 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.inline_cancel_action())
243 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, call.message.id)
244 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, msg.id)
245 a47eb4c Dawsh 2y ago # return bot.register_next_step_handler(call.message, add_data_step)
246 a47eb4c Dawsh 2y ago await bot.set_state(call.from_user.id, botStates.add_data, call.message.chat.id)
247 a47eb4c Dawsh 2y ago
248 a47eb4c Dawsh 2y ago
249 a47eb4c Dawsh 2y ago @bot.message_handler(state=botStates.add_data)
250 a47eb4c Dawsh 2y ago async def add_data_step(message):
251 a47eb4c Dawsh 2y ago try:
252 a47eb4c Dawsh 2y ago data_limit = float(message.text)
253 a47eb4c Dawsh 2y ago if not data_limit:
254 a47eb4c Dawsh 2y ago raise ValueError
255 a47eb4c Dawsh 2y ago except ValueError:
256 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Data limit must be a number and not zero.')
257 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.message_id)
258 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, add_data_step)
259 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.message_id)
260 a47eb4c Dawsh 2y ago msg = await bot.send_message(
261 a47eb4c Dawsh 2y ago message.chat.id,
262 a47eb4c Dawsh 2y ago f"⚠️ Are you sure? this will change Data limit of all users according to <b>"
263 a47eb4c Dawsh 2y ago f"{'+' if data_limit > 0 else '-'}{readable_size(abs(data_limit *1024*1024*1024))}</b>",
264 a47eb4c Dawsh 2y ago parse_mode="html",
265 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.confirm_action('do_add_data', data_limit))
266 a47eb4c Dawsh 2y ago await bot.delete_state(message.from_user.id, message.chat.id)
267 a47eb4c Dawsh 2y ago await cleanup_messages(message.chat.id)
268 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, msg.id)
269 a47eb4c Dawsh 2y ago
270 a47eb4c Dawsh 2y ago
271 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals('add_time'), is_admin=True)
272 a47eb4c Dawsh 2y ago async def add_time_command(call: types.CallbackQuery):
273 a47eb4c Dawsh 2y ago msg = await bot.edit_message_text(
274 a47eb4c Dawsh 2y ago f"📅 Enter Days to increase or decrease expiry:",
275 a47eb4c Dawsh 2y ago call.message.chat.id,
276 a47eb4c Dawsh 2y ago call.message.message_id,
277 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.inline_cancel_action())
278 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, call.message.id)
279 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, msg.id)
280 a47eb4c Dawsh 2y ago # return bot.register_next_step_handler(call.message, add_time_step)
281 a47eb4c Dawsh 2y ago await bot.set_state(call.from_user.id, botStates.add_time, call.message.chat.id)
282 a47eb4c Dawsh 2y ago
283 a47eb4c Dawsh 2y ago
284 a47eb4c Dawsh 2y ago @bot.message_handler(state=botStates.add_time)
285 a47eb4c Dawsh 2y ago async def add_time_step(message):
286 a47eb4c Dawsh 2y ago try:
287 a47eb4c Dawsh 2y ago days = int(message.text)
288 a47eb4c Dawsh 2y ago if not days:
289 a47eb4c Dawsh 2y ago raise ValueError
290 a47eb4c Dawsh 2y ago except ValueError:
291 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Days must be as a number and not zero.')
292 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.message_id)
293 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, add_time_step)
294 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.message_id)
295 a47eb4c Dawsh 2y ago msg = await bot.send_message(
296 a47eb4c Dawsh 2y ago message.chat.id,
297 a47eb4c Dawsh 2y ago f"⚠️ Are you sure? this will change Expiry Time of all users according to <b>{days} Days</b>",
298 a47eb4c Dawsh 2y ago parse_mode="html",
299 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.confirm_action('do_add_time', days))
300 a47eb4c Dawsh 2y ago await cleanup_messages(message.chat.id)
301 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, msg.id)
302 a47eb4c Dawsh 2y ago
303 a47eb4c Dawsh 2y ago
304 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("inbound"), is_admin=True)
305 a47eb4c Dawsh 2y ago async def inbound_command(call: types.CallbackQuery):
306 a47eb4c Dawsh 2y ago await bot.edit_message_text(
307 a47eb4c Dawsh 2y ago f"Select inbound to *{call.data[8:].title()}* from all users",
308 a47eb4c Dawsh 2y ago call.message.chat.id,
309 a47eb4c Dawsh 2y ago call.message.message_id,
310 a47eb4c Dawsh 2y ago parse_mode="markdown",
311 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.inbounds_menu(call.data, xray.config.inbounds_by_tag))
312 a47eb4c Dawsh 2y ago
313 a47eb4c Dawsh 2y ago
314 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("confirm_inbound"), is_admin=True)
315 a47eb4c Dawsh 2y ago async def delete_expired_confirm_command(call: types.CallbackQuery):
316 a47eb4c Dawsh 2y ago await bot.edit_message_text(
317 a47eb4c Dawsh 2y ago f"⚠️ Are you sure? This will *{call.data[16:].replace(':', ' ')} for All Users*‼️",
318 a47eb4c Dawsh 2y ago call.message.chat.id,
319 a47eb4c Dawsh 2y ago call.message.message_id,
320 a47eb4c Dawsh 2y ago parse_mode="markdown",
321 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.confirm_action(action=call.data[8:]))
322 a47eb4c Dawsh 2y ago
323 a47eb4c Dawsh 2y ago
324 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("edit:"), is_admin=True)
325 a47eb4c Dawsh 2y ago async def edit_command(call: types.CallbackQuery):
326 a47eb4c Dawsh 2y ago # bot.clear_step_handler_by_chat_id(call.message.chat.id)
327 a47eb4c Dawsh 2y ago await bot.delete_state(call.from_user.id, call.message.chat.id)
328 a47eb4c Dawsh 2y ago username = call.data.split(":")[1]
329 a47eb4c Dawsh 2y ago with GetDB() as db:
330 a47eb4c Dawsh 2y ago db_user = crud.get_user(db, username)
331 a47eb4c Dawsh 2y ago if not db_user:
332 a47eb4c Dawsh 2y ago return await bot.answer_callback_query(
333 a47eb4c Dawsh 2y ago call.id,
334 a47eb4c Dawsh 2y ago '❌ User not found.',
335 a47eb4c Dawsh 2y ago show_alert=True
336 a47eb4c Dawsh 2y ago )
337 9bfa731 Dawsh 2y ago services = crud.get_services(db)
338 a47eb4c Dawsh 2y ago user = UserResponse.model_validate(db_user)
339 a47eb4c Dawsh 2y ago mem_store.set(f'{call.message.chat.id}:username', username)
340 a47eb4c Dawsh 2y ago mem_store.set(f'{call.message.chat.id}:data_limit', db_user.data_limit)
341 a47eb4c Dawsh 2y ago mem_store.set(f'{call.message.chat.id}:expire_date', datetime.fromtimestamp(db_user.expire) if db_user.expire else None)
342 9bfa731 Dawsh 2y ago mem_store.set(f'{call.message.chat.id}:services', [s.id for s in db_user.services])
343 a47eb4c Dawsh 2y ago await bot.edit_message_text(
344 a47eb4c Dawsh 2y ago f"📝 Editing user `{username}`",
345 a47eb4c Dawsh 2y ago call.message.chat.id,
346 a47eb4c Dawsh 2y ago call.message.message_id,
347 a47eb4c Dawsh 2y ago parse_mode="markdown",
348 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.select_services(
349 9bfa731 Dawsh 2y ago services,
350 9bfa731 Dawsh 2y ago [s.id for s in user.services],
351 a47eb4c Dawsh 2y ago "edit",
352 a47eb4c Dawsh 2y ago username=username,
353 a47eb4c Dawsh 2y ago data_limit=db_user.data_limit,
354 a47eb4c Dawsh 2y ago expire_date=mem_store.get(f"{call.message.chat.id}:expire_date"),
355 a47eb4c Dawsh 2y ago )
356 a47eb4c Dawsh 2y ago )
357 a47eb4c Dawsh 2y ago
358 a47eb4c Dawsh 2y ago
359 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals('help_edit'), is_admin=True)
360 a47eb4c Dawsh 2y ago async def help_edit_command(call: types.CallbackQuery):
361 a47eb4c Dawsh 2y ago await bot.answer_callback_query(
362 a47eb4c Dawsh 2y ago call.id,
363 a47eb4c Dawsh 2y ago text="Press the (✏️ Edit) button to edit",
364 a47eb4c Dawsh 2y ago show_alert=True
365 a47eb4c Dawsh 2y ago )
366 a47eb4c Dawsh 2y ago
367 a47eb4c Dawsh 2y ago
368 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals('cancel'), is_admin=True)
369 a47eb4c Dawsh 2y ago async def cancel_command(call: types.CallbackQuery):
370 a47eb4c Dawsh 2y ago # bot.clear_step_handler_by_chat_id(call.message.chat.id)
371 a47eb4c Dawsh 2y ago await bot.delete_state(call.from_user.id, call.message.chat.id)
372 a47eb4c Dawsh 2y ago return await bot.edit_message_text(
373 a47eb4c Dawsh 2y ago get_system_info(),
374 a47eb4c Dawsh 2y ago call.message.chat.id,
375 a47eb4c Dawsh 2y ago call.message.message_id,
376 a47eb4c Dawsh 2y ago parse_mode="MarkdownV2",
377 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.main_menu()
378 a47eb4c Dawsh 2y ago )
379 a47eb4c Dawsh 2y ago
380 a47eb4c Dawsh 2y ago
381 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('edit_user:'), is_admin=True)
382 a47eb4c Dawsh 2y ago async def edit_user_command(call: types.CallbackQuery):
383 a47eb4c Dawsh 2y ago _, username, action = call.data.split(":")
384 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, call.message.id)
385 a47eb4c Dawsh 2y ago await cleanup_messages(call.message.chat.id)
386 a47eb4c Dawsh 2y ago if action == "data":
387 a47eb4c Dawsh 2y ago msg = await bot.send_message(
388 a47eb4c Dawsh 2y ago call.message.chat.id,
389 a47eb4c Dawsh 2y ago '⬆️ Enter Data Limit (GB):\n⚠️ Send 0 for unlimited.',
390 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.inline_cancel_action(f'user:{username}')
391 a47eb4c Dawsh 2y ago )
392 a47eb4c Dawsh 2y ago mem_store.set(f"{call.message.chat.id}:edit_msg_text", call.message.text)
393 a47eb4c Dawsh 2y ago await bot.delete_state(call.from_user.id, call.message.chat.id)
394 a47eb4c Dawsh 2y ago await bot.set_state(call.from_user.id, botStates.edit_user_data_limit, call.message.chat.id)
395 a47eb4c Dawsh 2y ago async with bot.retrieve_data(call.from_user.id, call.message.chat.id) as data:
396 a47eb4c Dawsh 2y ago data["username"] = username
397 a47eb4c Dawsh 2y ago #bot.clear_step_handler_by_chat_id(call.message.chat.id)
398 a47eb4c Dawsh 2y ago #bot.register_next_step_handler(
399 a47eb4c Dawsh 2y ago # call.message, edit_user_data_limit_step, username)
400 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, msg.message_id)
401 a47eb4c Dawsh 2y ago elif action == "expire":
402 a47eb4c Dawsh 2y ago msg = await bot.send_message(
403 a47eb4c Dawsh 2y ago call.message.chat.id,
404 a47eb4c Dawsh 2y ago '⬆️ Enter Expire Date (YYYY-MM-DD)\nOr You Can Use Regex Symbol: ^[0-9]{1,3}(M|D) :\n⚠️ Send 0 for never expire.',
405 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.inline_cancel_action(f'user:{username}'))
406 a47eb4c Dawsh 2y ago mem_store.set(f"{call.message.chat.id}:edit_msg_text", call.message.text)
407 a47eb4c Dawsh 2y ago # bot.clear_step_handler_by_chat_id(call.message.chat.id)
408 a47eb4c Dawsh 2y ago await bot.set_state(call.from_user.id, botStates.edit_user_expire, call.message.chat.id)
409 a47eb4c Dawsh 2y ago async with bot.retrieve_data(call.from_user.id, call.message.chat.id) as data:
410 a47eb4c Dawsh 2y ago data["username"] = username
411 a47eb4c Dawsh 2y ago #bot.register_next_step_handler(
412 a47eb4c Dawsh 2y ago # call.message, edit_user_expire_step, username=username)
413 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, msg.message_id)
414 a47eb4c Dawsh 2y ago
415 a47eb4c Dawsh 2y ago
416 a47eb4c Dawsh 2y ago @bot.message_handler(state=botStates.edit_user_data_limit)
417 a47eb4c Dawsh 2y ago async def edit_user_data_limit_step(message: types.Message):
418 a47eb4c Dawsh 2y ago try:
419 a47eb4c Dawsh 2y ago if float(message.text) < 0:
420 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Data limit must be greater or equal to 0.')
421 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.message_id)
422 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, edit_user_data_limit_step, username=username)
423 a47eb4c Dawsh 2y ago data_limit = float(message.text) * 1024**3
424 a47eb4c Dawsh 2y ago except ValueError:
425 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Data limit must be a number.')
426 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.message_id)
427 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, edit_user_data_limit_step, username=username)
428 a47eb4c Dawsh 2y ago mem_store.set(f'{message.chat.id}:data_limit', data_limit)
429 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.message_id)
430 a47eb4c Dawsh 2y ago text = mem_store.get(f"{message.chat.id}:edit_msg_text")
431 a47eb4c Dawsh 2y ago mem_store.delete(f"{message.chat.id}:edit_msg_text")
432 a47eb4c Dawsh 2y ago async with bot.retrieve_data(call.from_user.id, call.message.chat.id) as data:
433 a47eb4c Dawsh 2y ago username = data["username"]
434 a47eb4c Dawsh 2y ago del data["username"]
435 a47eb4c Dawsh 2y ago await bot.send_message(
436 a47eb4c Dawsh 2y ago message.chat.id,
437 a47eb4c Dawsh 2y ago text or f"📝 Editing user <code>{username}</code>",
438 a47eb4c Dawsh 2y ago parse_mode="html",
439 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.select_protocols(
440 a47eb4c Dawsh 2y ago mem_store.get(f'{message.chat.id}:protocols'), "edit",
441 a47eb4c Dawsh 2y ago username=username, data_limit=data_limit, expire_date=mem_store.get(f'{message.chat.id}:expire_date')))
442 a47eb4c Dawsh 2y ago await cleanup_messages(message.chat.id)
443 a47eb4c Dawsh 2y ago
444 a47eb4c Dawsh 2y ago
445 a47eb4c Dawsh 2y ago @bot.message_handler(state=botStates.edit_user_expire)
446 a47eb4c Dawsh 2y ago async def edit_user_expire_step(message: types.Message):
447 a47eb4c Dawsh 2y ago try:
448 a47eb4c Dawsh 2y ago now = datetime.now()
449 a47eb4c Dawsh 2y ago today = datetime(
450 a47eb4c Dawsh 2y ago year=now.year,
451 a47eb4c Dawsh 2y ago month=now.month,
452 a47eb4c Dawsh 2y ago day=now.day,
453 a47eb4c Dawsh 2y ago hour=23,
454 a47eb4c Dawsh 2y ago minute=59,
455 a47eb4c Dawsh 2y ago second=59
456 a47eb4c Dawsh 2y ago )
457 a47eb4c Dawsh 2y ago if re.match(r'^[0-9]{1,3}(M|m|D|d)$', message.text):
458 a47eb4c Dawsh 2y ago expire_date = today
459 a47eb4c Dawsh 2y ago number_pattern = r'^[0-9]{1,3}'
460 a47eb4c Dawsh 2y ago number = int(re.findall(number_pattern, message.text)[0])
461 a47eb4c Dawsh 2y ago symbol_pattern = r'(M|m|D|d)$'
462 a47eb4c Dawsh 2y ago symbol = re.findall(symbol_pattern, message.text)[0].upper()
463 a47eb4c Dawsh 2y ago if symbol == 'M':
464 a47eb4c Dawsh 2y ago expire_date = today + relativedelta(months=number)
465 a47eb4c Dawsh 2y ago elif symbol == 'D':
466 a47eb4c Dawsh 2y ago expire_date = today + relativedelta(days=number)
467 a47eb4c Dawsh 2y ago elif message.text != '0':
468 a47eb4c Dawsh 2y ago expire_date = datetime.strptime(message.text, "%Y-%m-%d")
469 a47eb4c Dawsh 2y ago else:
470 a47eb4c Dawsh 2y ago expire_date = None
471 a47eb4c Dawsh 2y ago if expire_date and expire_date < today:
472 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Expire date must be greater than today.')
473 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.message_id)
474 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, edit_user_expire_step, username=username)
475 a47eb4c Dawsh 2y ago except ValueError:
476 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Expire date must be in YYYY-MM-DD format.\nOr You Can Use Regex Symbol: ^[0-9]{1,3}(M|D)')
477 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.message_id)
478 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, edit_user_expire_step, username=username)
479 a47eb4c Dawsh 2y ago
480 a47eb4c Dawsh 2y ago mem_store.set(f'{message.chat.id}:expire_date', expire_date)
481 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.message_id)
482 a47eb4c Dawsh 2y ago text = mem_store.get(f"{message.chat.id}:edit_msg_text")
483 a47eb4c Dawsh 2y ago mem_store.delete(f"{message.chat.id}:edit_msg_text")
484 a47eb4c Dawsh 2y ago async with bot.retrieve_data(call.from_user.id, call.message.chat.id) as data:
485 a47eb4c Dawsh 2y ago username = data["username"]
486 a47eb4c Dawsh 2y ago del data["username"]
487 a47eb4c Dawsh 2y ago await bot.send_message(
488 a47eb4c Dawsh 2y ago message.chat.id,
489 a47eb4c Dawsh 2y ago text or f"📝 Editing user <code>{username}</code>",
490 a47eb4c Dawsh 2y ago parse_mode="html",
491 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.select_protocols(
492 a47eb4c Dawsh 2y ago mem_store.get(f'{message.chat.id}:protocols'), "edit",
493 a47eb4c Dawsh 2y ago username=username, data_limit=mem_store.get(f'{message.chat.id}:data_limit'), expire_date=expire_date))
494 a47eb4c Dawsh 2y ago await cleanup_messages(message.chat.id)
495 a47eb4c Dawsh 2y ago
496 a47eb4c Dawsh 2y ago
497 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('users:'), is_admin=True)
498 a47eb4c Dawsh 2y ago async def users_command(call: types.CallbackQuery):
499 a47eb4c Dawsh 2y ago page = int(call.data.split(':')[1]) if len(call.data.split(':')) > 1 else 1
500 a47eb4c Dawsh 2y ago with GetDB() as db:
501 a47eb4c Dawsh 2y ago total_pages = math.ceil(crud.get_users_count(db) / 10)
502 a47eb4c Dawsh 2y ago users = crud.get_users(db, offset=(page - 1) * 10, limit=10, sort=[crud.UsersSortingOptions["-created_at"]])
503 a47eb4c Dawsh 2y ago text = """👥 Users: (Page {page}/{total_pages})
504 a47eb4c Dawsh 2y ago ✅ Active
505 a47eb4c Dawsh 2y ago ❌ Disabled
506 a47eb4c Dawsh 2y ago 🕰 Expired
507 a47eb4c Dawsh 2y ago 🪫 Limited""".format(page=page, total_pages=total_pages)
508 a47eb4c Dawsh 2y ago
509 a47eb4c Dawsh 2y ago await bot.edit_message_text(
510 a47eb4c Dawsh 2y ago text,
511 a47eb4c Dawsh 2y ago call.message.chat.id,
512 a47eb4c Dawsh 2y ago call.message.message_id,
513 a47eb4c Dawsh 2y ago parse_mode="HTML",
514 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.user_list(
515 a47eb4c Dawsh 2y ago users, page, total_pages=total_pages)
516 a47eb4c Dawsh 2y ago )
517 a47eb4c Dawsh 2y ago
518 a47eb4c Dawsh 2y ago
519 a47eb4c Dawsh 2y ago def get_user_info_text(
520 a47eb4c Dawsh 2y ago status: str, username: str, sub_url: str, data_limit: int = None,
521 a47eb4c Dawsh 2y ago usage: int = None, expire: int = None, note: str = None) -> str:
522 a47eb4c Dawsh 2y ago statuses = {
523 a47eb4c Dawsh 2y ago 'active': '✅',
524 a47eb4c Dawsh 2y ago 'expired': '🕰',
525 a47eb4c Dawsh 2y ago 'limited': '🪫',
526 a47eb4c Dawsh 2y ago 'disabled': '❌'}
527 a47eb4c Dawsh 2y ago text = f"""\
528 a47eb4c Dawsh 2y ago ┌─{statuses[status]} <b>Status:</b> <code>{status.title()}</code>
529 a47eb4c Dawsh 2y ago │ └─<b>Username:</b> <code>{username}</code>
530 a47eb4c Dawsh 2y ago │
531 a47eb4c Dawsh 2y ago ├─🔋 <b>Data limit:</b> <code>{readable_size(data_limit) if data_limit else 'Unlimited'}</code>
532 a47eb4c Dawsh 2y ago │ └─<b>Data Used:</b> <code>{readable_size(usage) if usage else "-"}</code>
533 a47eb4c Dawsh 2y ago │
534 a47eb4c Dawsh 2y ago ├─📅 <b>Expiry Date:</b> <code>{datetime.fromtimestamp(expire).date() if expire else 'Never'}</code>
535 a47eb4c Dawsh 2y ago │ └─<b>Days left:</b> <code>{(datetime.fromtimestamp(expire or 0) - datetime.now()).days if expire else '-'}</code>
536 a47eb4c Dawsh 2y ago │
537 a47eb4c Dawsh 2y ago """
538 a47eb4c Dawsh 2y ago if note:
539 a47eb4c Dawsh 2y ago text += f'├─📝 <b>Note:</b> <code>{note}</code>\n│\n'
540 a47eb4c Dawsh 2y ago text += f'└─🚀 <b><a href="{sub_url}">Subscription</a>:</b> <code>{sub_url}</code>'
541 a47eb4c Dawsh 2y ago return text
542 a47eb4c Dawsh 2y ago
543 a47eb4c Dawsh 2y ago
544 a47eb4c Dawsh 2y ago
545 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('edit_note:'), is_admin=True)
546 a47eb4c Dawsh 2y ago async def edit_note_command(call: types.CallbackQuery):
547 a47eb4c Dawsh 2y ago username = call.data.split(':')[1]
548 a47eb4c Dawsh 2y ago with GetDB() as db:
549 a47eb4c Dawsh 2y ago db_user = crud.get_user(db, username)
550 a47eb4c Dawsh 2y ago if not db_user:
551 a47eb4c Dawsh 2y ago return await bot.answer_callback_query(call.id, '❌ User not found.', show_alert=True)
552 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, call.message.id)
553 a47eb4c Dawsh 2y ago await cleanup_messages(call.message.chat.id)
554 a47eb4c Dawsh 2y ago msg = await bot.send_message(
555 a47eb4c Dawsh 2y ago call.message.chat.id,
556 a47eb4c Dawsh 2y ago f'<b>📝 Current Note:</b> <code>{db_user.note}</code>\n\nSend new Note for <code>{username}</code>',
557 a47eb4c Dawsh 2y ago parse_mode="HTML",
558 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.inline_cancel_action(f'user:{username}'))
559 a47eb4c Dawsh 2y ago mem_store.set(f'{call.message.chat.id}:username', username)
560 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, msg.id)
561 a47eb4c Dawsh 2y ago await bot.set_state(call.from_user.id, botStates.edit_note, call.message.chat.id)
562 a47eb4c Dawsh 2y ago # bot.register_next_step_handler(msg, edit_note_step)
563 a47eb4c Dawsh 2y ago
564 a47eb4c Dawsh 2y ago @bot.message_handler(state=botStates.edit_note)
565 a47eb4c Dawsh 2y ago async def edit_note_step(message: types.Message):
566 a47eb4c Dawsh 2y ago note = message.text or ''
567 a47eb4c Dawsh 2y ago if len(note) > 500:
568 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Note can not be more than 500 characters.')
569 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.id)
570 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
571 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, edit_note_step)
572 a47eb4c Dawsh 2y ago username = mem_store.get(f'{message.chat.id}:username')
573 a47eb4c Dawsh 2y ago if not username:
574 a47eb4c Dawsh 2y ago await cleanup_messages(message.chat.id)
575 a47eb4c Dawsh 2y ago await bot.reply_to(message, '❌ Something went wrong!\n restart bot /start')
576 a47eb4c Dawsh 2y ago with GetDB() as db:
577 a47eb4c Dawsh 2y ago db_user = crud.get_user(db, username)
578 a47eb4c Dawsh 2y ago last_note = db_user.note
579 9bfa731 Dawsh 2y ago db_user = crud.update_user(db, db_user, UserModify(username=username, note=note))
580 a47eb4c Dawsh 2y ago user = UserResponse.model_validate(db_user)
581 a47eb4c Dawsh 2y ago text = get_user_info_text(
582 a47eb4c Dawsh 2y ago status=user.status,
583 a47eb4c Dawsh 2y ago username=user.username,
584 a47eb4c Dawsh 2y ago sub_url=user.subscription_url,
585 a47eb4c Dawsh 2y ago expire=user.expire,
586 a47eb4c Dawsh 2y ago data_limit=user.data_limit,
587 a47eb4c Dawsh 2y ago usage=user.used_traffic,
588 a47eb4c Dawsh 2y ago note=user.note)
589 a47eb4c Dawsh 2y ago await bot.reply_to(message, text, parse_mode="html", reply_markup=BotKeyboard.user_menu(user_info={
590 a47eb4c Dawsh 2y ago 'status': user.status,
591 a47eb4c Dawsh 2y ago 'username': user.username}, note=True))
592 a47eb4c Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
593 a47eb4c Dawsh 2y ago text = f'''\
594 a47eb4c Dawsh 2y ago 📝 <b>#Edit_Note #From_Bot</b>
595 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
596 a47eb4c Dawsh 2y ago <b>Username :</b> <code>{username}</code>
597 a47eb4c Dawsh 2y ago <b>Last Note :</b> <code>{last_note}</code>
598 a47eb4c Dawsh 2y ago <b>New Note :</b> <code>{note}</code>
599 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
600 a47eb4c Dawsh 2y ago <b>By :</b> <a href="tg://user?id={message.chat.id}">{message.from_user.full_name}</a>'''
601 a47eb4c Dawsh 2y ago try:
602 a47eb4c Dawsh 2y ago await bot.send_message(TELEGRAM_LOGGER_CHANNEL_ID, text, 'HTML')
603 a47eb4c Dawsh 2y ago except:
604 a47eb4c Dawsh 2y ago pass
605 a47eb4c Dawsh 2y ago
606 a47eb4c Dawsh 2y ago
607 a47eb4c Dawsh 2y ago
608 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('user:'), is_admin=True)
609 a47eb4c Dawsh 2y ago async def user_command(call: types.CallbackQuery):
610 a47eb4c Dawsh 2y ago await bot.delete_state(call.from_user.id, call.message.chat.id)
611 a47eb4c Dawsh 2y ago # bot.clear_step_handler_by_chat_id(call.message.chat.id)
612 a47eb4c Dawsh 2y ago username = call.data.split(':')[1]
613 a47eb4c Dawsh 2y ago page = int(call.data.split(':')[2]) if len(call.data.split(':')) > 2 else 1
614 a47eb4c Dawsh 2y ago with GetDB() as db:
615 a47eb4c Dawsh 2y ago db_user = crud.get_user(db, username)
616 a47eb4c Dawsh 2y ago if not db_user:
617 a47eb4c Dawsh 2y ago return await bot.answer_callback_query(
618 a47eb4c Dawsh 2y ago call.id,
619 a47eb4c Dawsh 2y ago '❌ User not found.',
620 a47eb4c Dawsh 2y ago show_alert=True
621 a47eb4c Dawsh 2y ago )
622 a47eb4c Dawsh 2y ago user = UserResponse.model_validate(db_user)
623 a47eb4c Dawsh 2y ago text = get_user_info_text(
624 a47eb4c Dawsh 2y ago status=user.status, username=username, sub_url=user.subscription_url,
625 a47eb4c Dawsh 2y ago data_limit=user.data_limit, usage=user.used_traffic, expire=user.expire, note=user.note)
626 a47eb4c Dawsh 2y ago await bot.edit_message_text(
627 a47eb4c Dawsh 2y ago text,
628 a47eb4c Dawsh 2y ago call.message.chat.id, call.message.message_id, parse_mode="HTML",
629 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.user_menu(
630 a47eb4c Dawsh 2y ago {'username': user.username, 'status': user.status},
631 a47eb4c Dawsh 2y ago page=page, note=True))
632 a47eb4c Dawsh 2y ago
633 a47eb4c Dawsh 2y ago
634 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("revoke_sub:"), is_admin=True)
635 a47eb4c Dawsh 2y ago async def revoke_sub_command(call: types.CallbackQuery):
636 a47eb4c Dawsh 2y ago username = call.data.split(":")[1]
637 a47eb4c Dawsh 2y ago await bot.edit_message_text(
638 a47eb4c Dawsh 2y ago f"⚠️ Are you sure? This will *Revoke Subscription* link for `{username}`‼️",
639 a47eb4c Dawsh 2y ago call.message.chat.id,
640 a47eb4c Dawsh 2y ago call.message.message_id,
641 a47eb4c Dawsh 2y ago parse_mode="markdown",
642 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.confirm_action(action="do_revoke", username=username))
643 a47eb4c Dawsh 2y ago
644 a47eb4c Dawsh 2y ago
645 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("links:"), is_admin=True)
646 a47eb4c Dawsh 2y ago async def links_command(call: types.CallbackQuery):
647 a47eb4c Dawsh 2y ago username = call.data.split(":")[1]
648 a47eb4c Dawsh 2y ago
649 a47eb4c Dawsh 2y ago with GetDB() as db:
650 a47eb4c Dawsh 2y ago db_user = crud.get_user(db, username)
651 a47eb4c Dawsh 2y ago if not db_user:
652 a47eb4c Dawsh 2y ago return await bot.answer_callback_query(call.id, "User not found!", show_alert=True)
653 a47eb4c Dawsh 2y ago
654 a47eb4c Dawsh 2y ago user = UserResponse.model_validate(db_user)
655 a47eb4c Dawsh 2y ago
656 a47eb4c Dawsh 2y ago text = f"<code>{user.subscription_url}</code>\n\n\n"
657 a47eb4c Dawsh 2y ago for link in user.links:
658 a47eb4c Dawsh 2y ago text += f"<code>{link}</code>\n\n"
659 a47eb4c Dawsh 2y ago
660 a47eb4c Dawsh 2y ago await bot.edit_message_text(
661 a47eb4c Dawsh 2y ago text,
662 a47eb4c Dawsh 2y ago call.message.chat.id,
663 a47eb4c Dawsh 2y ago call.message.message_id,
664 a47eb4c Dawsh 2y ago parse_mode="HTML",
665 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.show_links(username)
666 a47eb4c Dawsh 2y ago )
667 a47eb4c Dawsh 2y ago
668 a47eb4c Dawsh 2y ago
669 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("genqr:"), is_admin=True)
670 a47eb4c Dawsh 2y ago async def genqr_command(call: types.CallbackQuery):
671 a47eb4c Dawsh 2y ago username = call.data.split(":")[1]
672 a47eb4c Dawsh 2y ago
673 a47eb4c Dawsh 2y ago with GetDB() as db:
674 a47eb4c Dawsh 2y ago db_user = crud.get_user(db, username)
675 a47eb4c Dawsh 2y ago if not db_user:
676 a47eb4c Dawsh 2y ago return await bot.answer_callback_query(call.id, "User not found!", show_alert=True)
677 a47eb4c Dawsh 2y ago
678 a47eb4c Dawsh 2y ago user = UserResponse.model_validate(db_user)
679 a47eb4c Dawsh 2y ago
680 a47eb4c Dawsh 2y ago await bot.answer_callback_query(call.id, "Generating QR code...")
681 a47eb4c Dawsh 2y ago
682 a47eb4c Dawsh 2y ago for link in user.links:
683 a47eb4c Dawsh 2y ago f = io.BytesIO()
684 a47eb4c Dawsh 2y ago qr = qrcode.QRCode(border=6)
685 a47eb4c Dawsh 2y ago qr.add_data(link)
686 a47eb4c Dawsh 2y ago qr.make_image().save(f)
687 a47eb4c Dawsh 2y ago f.seek(0)
688 a47eb4c Dawsh 2y ago await bot.send_photo(
689 a47eb4c Dawsh 2y ago call.message.chat.id,
690 a47eb4c Dawsh 2y ago photo=f,
691 a47eb4c Dawsh 2y ago caption=f"<code>{link}</code>",
692 a47eb4c Dawsh 2y ago parse_mode="HTML"
693 a47eb4c Dawsh 2y ago )
694 a47eb4c Dawsh 2y ago with io.BytesIO() as f:
695 a47eb4c Dawsh 2y ago qr = qrcode.QRCode(border=6)
696 a47eb4c Dawsh 2y ago qr.add_data(user.subscription_url)
697 a47eb4c Dawsh 2y ago qr.make_image().save(f)
698 a47eb4c Dawsh 2y ago f.seek(0)
699 a47eb4c Dawsh 2y ago await bot.send_photo(
700 a47eb4c Dawsh 2y ago call.message.chat.id,
701 a47eb4c Dawsh 2y ago photo=f,
702 a47eb4c Dawsh 2y ago caption=get_user_info_text(
703 a47eb4c Dawsh 2y ago status=user.status,
704 a47eb4c Dawsh 2y ago username=user.username,
705 a47eb4c Dawsh 2y ago sub_url=user.subscription_url,
706 a47eb4c Dawsh 2y ago data_limit=user.data_limit,
707 a47eb4c Dawsh 2y ago usage=user.used_traffic,
708 a47eb4c Dawsh 2y ago expire=user.expire
709 a47eb4c Dawsh 2y ago ),
710 a47eb4c Dawsh 2y ago parse_mode="HTML",
711 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.subscription_page(user.subscription_url)
712 a47eb4c Dawsh 2y ago )
713 a47eb4c Dawsh 2y ago try:
714 a47eb4c Dawsh 2y ago await bot.delete_message(call.message.chat.id, call.message.message_id)
715 a47eb4c Dawsh 2y ago except:
716 a47eb4c Dawsh 2y ago pass
717 a47eb4c Dawsh 2y ago
718 a47eb4c Dawsh 2y ago text = f"<code>{user.subscription_url}</code>\n\n\n"
719 a47eb4c Dawsh 2y ago for link in user.links:
720 a47eb4c Dawsh 2y ago text += f"<code>{link}</code>\n\n"
721 a47eb4c Dawsh 2y ago
722 a47eb4c Dawsh 2y ago await bot.send_message(
723 a47eb4c Dawsh 2y ago call.message.chat.id,
724 a47eb4c Dawsh 2y ago text,
725 a47eb4c Dawsh 2y ago "HTML",
726 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.show_links(username)
727 a47eb4c Dawsh 2y ago )
728 a47eb4c Dawsh 2y ago
729 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('random'), is_admin=True)
730 a47eb4c Dawsh 2y ago async def random_username(call: types.CallbackQuery):
731 a47eb4c Dawsh 2y ago # bot.clear_step_handler_by_chat_id(call.message.chat.id)
732 a47eb4c Dawsh 2y ago await bot.delete_state(call.from_user.id, call.message.chat.id)
733 a47eb4c Dawsh 2y ago template_id = int(call.data.split(":")[1] or 0)
734 a47eb4c Dawsh 2y ago mem_store.delete(f'{call.message.chat.id}:template_id')
735 a47eb4c Dawsh 2y ago
736 a47eb4c Dawsh 2y ago characters = string.ascii_letters + string.digits
737 a47eb4c Dawsh 2y ago username = random.choice(characters) + ''.join(random.choices(characters, k=4)) + '_' + ''.join(random.choices(characters, k=4))
738 a47eb4c Dawsh 2y ago
739 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, call.message.id)
740 a47eb4c Dawsh 2y ago await cleanup_messages(call.message.chat.id)
741 a47eb4c Dawsh 2y ago
742 9bfa731 Dawsh 2y ago msg = await bot.send_message(call.message.chat.id,
743 9bfa731 Dawsh 2y ago '⬆️ Enter Data Limit (GB):\n⚠️ Send 0 for unlimited.',
744 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.inline_cancel_action())
745 9bfa731 Dawsh 2y ago schedule_delete_message(call.message.chat.id, msg.id)
746 a47eb4c Dawsh 2y ago await bot.set_state(call.from_user.id, botStates.add_user_data_limit, call.message.chat.id)
747 a47eb4c Dawsh 2y ago async with bot.retrieve_data(call.from_user.id, call.message.chat.id) as data:
748 9bfa731 Dawsh 2y ago data["username"] = username
749 9bfa731 Dawsh 2y ago return
750 a47eb4c Dawsh 2y ago
751 a47eb4c Dawsh 2y ago
752 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals('add_user'), is_admin=True)
753 a47eb4c Dawsh 2y ago async def add_user_command(call: types.CallbackQuery):
754 a47eb4c Dawsh 2y ago try:
755 a47eb4c Dawsh 2y ago await bot.delete_message(call.message.chat.id, call.message.message_id)
756 a47eb4c Dawsh 2y ago except: # noqa
757 a47eb4c Dawsh 2y ago pass
758 a47eb4c Dawsh 2y ago username_msg = await bot.send_message(
759 a47eb4c Dawsh 2y ago call.message.chat.id,
760 a47eb4c Dawsh 2y ago '👤 Enter username:\n⚠️Username only can be 3 to 32 characters and contain a-z, A-Z 0-9, and underscores in '
761 a47eb4c Dawsh 2y ago 'between.',
762 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.random_username())
763 a47eb4c Dawsh 2y ago schedule_delete_message(call.message.chat.id, username_msg.id)
764 a47eb4c Dawsh 2y ago await bot.set_state(call.from_user.id, botStates.add_user_username, call.message.chat.id)
765 a47eb4c Dawsh 2y ago # bot.register_next_step_handler(username_msg, add_user_username_step)
766 a47eb4c Dawsh 2y ago
767 a47eb4c Dawsh 2y ago @bot.message_handler(state=botStates.add_user_username)
768 a47eb4c Dawsh 2y ago async def add_user_username_step(message: types.Message):
769 a47eb4c Dawsh 2y ago username = message.text
770 a47eb4c Dawsh 2y ago if not username:
771 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Username can not be empty.')
772 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.id)
773 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
774 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, add_user_username_step)
775 a47eb4c Dawsh 2y ago if not re.match(r'^(?!.*__)(?!.*_$)\w{2,31}[a-zA-Z\d]$', username):
776 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id,
777 a47eb4c Dawsh 2y ago '❌ Username only can be 3 to 32 characters and contain a-z, A-Z, 0-9, and underscores in between.')
778 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.id)
779 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
780 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, add_user_username_step)
781 a47eb4c Dawsh 2y ago with GetDB() as db:
782 a47eb4c Dawsh 2y ago if crud.get_user(db, username):
783 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Username already exists.')
784 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.id)
785 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
786 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, add_user_username_step)
787 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
788 a47eb4c Dawsh 2y ago await cleanup_messages(message.chat.id)
789 a47eb4c Dawsh 2y ago msg = await bot.send_message(message.chat.id,
790 a47eb4c Dawsh 2y ago '⬆️ Enter Data Limit (GB):\n⚠️ Send 0 for unlimited.',
791 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.inline_cancel_action())
792 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, msg.id)
793 a47eb4c Dawsh 2y ago await bot.set_state(message.from_user.id, botStates.add_user_data_limit, message.chat.id)
794 a47eb4c Dawsh 2y ago async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
795 a47eb4c Dawsh 2y ago data["username"] = username
796 a47eb4c Dawsh 2y ago # bot.register_next_step_handler(msg, add_user_data_limit_step, username=username)
797 a47eb4c Dawsh 2y ago
798 a47eb4c Dawsh 2y ago
799 a47eb4c Dawsh 2y ago @bot.message_handler(state=botStates.add_user_data_limit)
800 a47eb4c Dawsh 2y ago async def add_user_data_limit_step(message: types.Message):
801 a47eb4c Dawsh 2y ago try:
802 a47eb4c Dawsh 2y ago if float(message.text) < 0:
803 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Data limit must be greater or equal to 0.')
804 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.id)
805 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
806 a47eb4c Dawsh 2y ago return #bot.register_next_step_handler(wait_msg, add_user_data_limit_step, username=username)
807 a47eb4c Dawsh 2y ago data_limit = float(message.text) * 1024 * 1024 * 1024
808 a47eb4c Dawsh 2y ago except ValueError:
809 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Data limit must be a number.')
810 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.id)
811 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
812 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, add_user_data_limit_step, username=username)
813 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
814 a47eb4c Dawsh 2y ago await cleanup_messages(message.chat.id)
815 a47eb4c Dawsh 2y ago msg = await bot.send_message(message.chat.id,
816 a47eb4c Dawsh 2y ago '⬆️ Enter Expire Date (YYYY-MM-DD)\nOr You Can Use Regex Symbol: ^[0-9]{1,3}(M|D) :\n⚠️ Send 0 for never expire.',
817 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.inline_cancel_action())
818 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, msg.id)
819 a47eb4c Dawsh 2y ago await bot.set_state(message.from_user.id, botStates.add_user_expire, message.chat.id)
820 a47eb4c Dawsh 2y ago async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
821 a47eb4c Dawsh 2y ago data["data_limit"] = data_limit
822 a47eb4c Dawsh 2y ago
823 a47eb4c Dawsh 2y ago # bot.register_next_step_handler(msg, add_user_expire_step, username=username, data_limit=data_limit)
824 a47eb4c Dawsh 2y ago
825 a47eb4c Dawsh 2y ago @bot.message_handler(state=botStates.add_user_expire)
826 a47eb4c Dawsh 2y ago async def add_user_expire_step(message: types.Message):
827 a47eb4c Dawsh 2y ago try:
828 a47eb4c Dawsh 2y ago now = datetime.now()
829 a47eb4c Dawsh 2y ago today = datetime(
830 a47eb4c Dawsh 2y ago year=now.year,
831 a47eb4c Dawsh 2y ago month=now.month,
832 a47eb4c Dawsh 2y ago day=now.day,
833 a47eb4c Dawsh 2y ago hour=23,
834 a47eb4c Dawsh 2y ago minute=59,
835 a47eb4c Dawsh 2y ago second=59
836 a47eb4c Dawsh 2y ago )
837 a47eb4c Dawsh 2y ago if re.match(r'^[0-9]{1,3}(M|m|D|d)$', message.text):
838 a47eb4c Dawsh 2y ago expire_date = today
839 a47eb4c Dawsh 2y ago number_pattern = r'^[0-9]{1,3}'
840 a47eb4c Dawsh 2y ago number = int(re.findall(number_pattern, message.text)[0])
841 a47eb4c Dawsh 2y ago symbol_pattern = r'(M|m|D|d)$'
842 a47eb4c Dawsh 2y ago symbol = re.findall(symbol_pattern, message.text)[0].upper()
843 a47eb4c Dawsh 2y ago if symbol == 'M':
844 a47eb4c Dawsh 2y ago expire_date = today + relativedelta(months=number)
845 a47eb4c Dawsh 2y ago elif symbol == 'D':
846 a47eb4c Dawsh 2y ago expire_date = today + relativedelta(days=number)
847 a47eb4c Dawsh 2y ago elif message.text != '0':
848 a47eb4c Dawsh 2y ago expire_date = datetime.strptime(message.text, "%Y-%m-%d")
849 a47eb4c Dawsh 2y ago else:
850 a47eb4c Dawsh 2y ago expire_date = None
851 a47eb4c Dawsh 2y ago if expire_date and expire_date < today:
852 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id, '❌ Expire date must be greater than today.')
853 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.id)
854 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
855 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, add_user_expire_step, username=username, data_limit=data_limit)
856 a47eb4c Dawsh 2y ago except ValueError:
857 a47eb4c Dawsh 2y ago wait_msg = await bot.send_message(message.chat.id,
858 a47eb4c Dawsh 2y ago '❌ Expire date must be in YYYY-MM-DD format.\nOr You Can Use Regex Symbol: ^[0-9]{1,3}(M|D)')
859 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, wait_msg.id)
860 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
861 a47eb4c Dawsh 2y ago return # bot.register_next_step_handler(wait_msg, add_user_expire_step, username=username, data_limit=data_limit)
862 a47eb4c Dawsh 2y ago async with bot.retrieve_data(message.from_user.id, message.chat.id) as data:
863 a47eb4c Dawsh 2y ago username, data_limit = data["username"], data["data_limit"]
864 a47eb4c Dawsh 2y ago mem_store.set(f'{message.chat.id}:username', username)
865 a47eb4c Dawsh 2y ago mem_store.set(f'{message.chat.id}:data_limit', data_limit)
866 a47eb4c Dawsh 2y ago mem_store.set(f'{message.chat.id}:expire_date', expire_date)
867 a47eb4c Dawsh 2y ago
868 9bfa731 Dawsh 2y ago with GetDB() as db:
869 9bfa731 Dawsh 2y ago services = crud.get_services(db)
870 a47eb4c Dawsh 2y ago schedule_delete_message(message.chat.id, message.id)
871 a47eb4c Dawsh 2y ago await cleanup_messages(message.chat.id)
872 a47eb4c Dawsh 2y ago await bot.send_message(
873 a47eb4c Dawsh 2y ago message.chat.id,
874 9bfa731 Dawsh 2y ago 'Select Services:\nUsernames: {}\nData Limit: {}\nExpiry Date {}'.format(
875 a47eb4c Dawsh 2y ago mem_store.get(f'{message.chat.id}:username'),
876 a47eb4c Dawsh 2y ago readable_size(mem_store.get(f'{message.chat.id}:data_limit'))
877 a47eb4c Dawsh 2y ago if mem_store.get(f'{message.chat.id}:data_limit') else "Unlimited",
878 a47eb4c Dawsh 2y ago mem_store.get(f'{message.chat.id}:expire_date').strftime("%Y-%m-%d")
879 a47eb4c Dawsh 2y ago if mem_store.get(f'{message.chat.id}:expire_date') else 'Never'
880 a47eb4c Dawsh 2y ago ),
881 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.select_services(services, [], action="create")
882 a47eb4c Dawsh 2y ago )
883 a47eb4c Dawsh 2y ago
884 a47eb4c Dawsh 2y ago
885 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('switch_service:'), is_admin=True)
886 9bfa731 Dawsh 2y ago async def switch_service(call: types.CallbackQuery):
887 a47eb4c Dawsh 2y ago if not (username := mem_store.get(f'{call.message.chat.id}:username')):
888 a47eb4c Dawsh 2y ago return await bot.answer_callback_query(call.id, '❌ No user selected.', show_alert=True)
889 9bfa731 Dawsh 2y ago selected_services: List[int] = mem_store.get(f'{call.message.chat.id}:services', [])
890 9bfa731 Dawsh 2y ago _, service, action = call.data.split(':')
891 9bfa731 Dawsh 2y ago service = int(service)
892 a47eb4c Dawsh 2y ago
893 9bfa731 Dawsh 2y ago with GetDB() as db:
894 9bfa731 Dawsh 2y ago services = crud.get_services(db)
895 9bfa731 Dawsh 2y ago if service in selected_services:
896 9bfa731 Dawsh 2y ago selected_services.remove(service)
897 a47eb4c Dawsh 2y ago else:
898 9bfa731 Dawsh 2y ago selected_services.append(service)
899 9bfa731 Dawsh 2y ago
900 9bfa731 Dawsh 2y ago mem_store.set(f'{call.message.chat.id}:services', selected_services)
901 a47eb4c Dawsh 2y ago
902 9bfa731 Dawsh 2y ago if action in ["edit"]:
903 a47eb4c Dawsh 2y ago return await bot.edit_message_text(
904 a47eb4c Dawsh 2y ago call.message.text,
905 a47eb4c Dawsh 2y ago call.message.chat.id,
906 a47eb4c Dawsh 2y ago call.message.message_id,
907 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.select_services(
908 9bfa731 Dawsh 2y ago services,
909 9bfa731 Dawsh 2y ago selected_services,
910 a47eb4c Dawsh 2y ago "edit",
911 a47eb4c Dawsh 2y ago username=username,
912 a47eb4c Dawsh 2y ago data_limit=mem_store.get(f"{call.message.chat.id}:data_limit"),
913 a47eb4c Dawsh 2y ago expire_date=mem_store.get(f"{call.message.chat.id}:expire_date"))
914 a47eb4c Dawsh 2y ago )
915 a47eb4c Dawsh 2y ago await bot.edit_message_text(
916 a47eb4c Dawsh 2y ago call.message.text,
917 a47eb4c Dawsh 2y ago call.message.chat.id,
918 a47eb4c Dawsh 2y ago call.message.message_id,
919 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.select_services(services, selected_services, "create")
920 a47eb4c Dawsh 2y ago )
921 a47eb4c Dawsh 2y ago
922 a47eb4c Dawsh 2y ago
923 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('confirm:'), is_admin=True)
924 a47eb4c Dawsh 2y ago async def confirm_user_command(call: types.CallbackQuery):
925 a47eb4c Dawsh 2y ago data = call.data.split(':')[1]
926 a47eb4c Dawsh 2y ago chat_id = call.from_user.id
927 a47eb4c Dawsh 2y ago full_name = call.from_user.full_name
928 a47eb4c Dawsh 2y ago now = datetime.now()
929 a47eb4c Dawsh 2y ago today = datetime(
930 a47eb4c Dawsh 2y ago year=now.year,
931 a47eb4c Dawsh 2y ago month=now.month,
932 a47eb4c Dawsh 2y ago day=now.day,
933 a47eb4c Dawsh 2y ago hour=23,
934 a47eb4c Dawsh 2y ago minute=59,
935 a47eb4c Dawsh 2y ago second=59)
936 a47eb4c Dawsh 2y ago
937 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("do_delete"), is_admin=True)
938 9bfa731 Dawsh 2y ago async def delete_user(call: types.CallbackQuery):
939 9bfa731 Dawsh 2y ago username = call.data.split(':')[1]
940 9bfa731 Dawsh 2y ago with GetDB() as db:
941 9bfa731 Dawsh 2y ago db_user = crud.get_user(db, username)
942 9bfa731 Dawsh 2y ago crud.remove_user(db, db_user)
943 9bfa731 Dawsh 2y ago await xray.operations.remove_user(db_user)
944 9bfa731 Dawsh 2y ago
945 9bfa731 Dawsh 2y ago await bot.edit_message_text(
946 9bfa731 Dawsh 2y ago '✅ User deleted.',
947 9bfa731 Dawsh 2y ago call.message.chat.id,
948 9bfa731 Dawsh 2y ago call.message.message_id,
949 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.main_menu()
950 9bfa731 Dawsh 2y ago )
951 9bfa731 Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
952 9bfa731 Dawsh 2y ago text = f'''\
953 a47eb4c Dawsh 2y ago 🗑 <b>#Deleted #From_Bot</b>
954 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
955 a47eb4c Dawsh 2y ago <b>Username :</b> <code>{db_user.username}</code>
956 a47eb4c Dawsh 2y ago <b>Traffic Limit :</b> <code>{readable_size(db_user.data_limit) if db_user.data_limit else "Unlimited"}</code>
957 a47eb4c Dawsh 2y ago <b>Expire Date :</b> <code>\
958 a47eb4c Dawsh 2y ago {datetime.fromtimestamp(db_user.expire).strftime('%H:%M:%S %Y-%m-%d') if db_user.expire else "Never"}</code>
959 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
960 9bfa731 Dawsh 2y ago <b>By :</b> <a href="tg://user?id={call.from_user.id}">{call.from_user.full_name}</a>'''
961 9bfa731 Dawsh 2y ago try:
962 9bfa731 Dawsh 2y ago await bot.send_message(TELEGRAM_LOGGER_CHANNEL_ID, text, 'HTML')
963 9bfa731 Dawsh 2y ago except:
964 9bfa731 Dawsh 2y ago pass
965 9bfa731 Dawsh 2y ago
966 9bfa731 Dawsh 2y ago
967 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("do_suspend"), is_admin=True)
968 9bfa731 Dawsh 2y ago async def disable_user(call: types.CallbackQuery):
969 9bfa731 Dawsh 2y ago username = call.data.split(":")[1]
970 9bfa731 Dawsh 2y ago with GetDB() as db:
971 9bfa731 Dawsh 2y ago db_user = crud.get_user(db, username)
972 9bfa731 Dawsh 2y ago crud.update_user(db, db_user, UserModify(
973 9bfa731 Dawsh 2y ago username=username,
974 9bfa731 Dawsh 2y ago status=UserStatusModify.disabled))
975 9bfa731 Dawsh 2y ago await xray.operations.remove_user(db_user)
976 9bfa731 Dawsh 2y ago user = UserResponse.model_validate(db_user)
977 9bfa731 Dawsh 2y ago await bot.edit_message_text(
978 9bfa731 Dawsh 2y ago get_user_info_text(
979 9bfa731 Dawsh 2y ago status='disabled',
980 9bfa731 Dawsh 2y ago username=username,
981 9bfa731 Dawsh 2y ago sub_url=user.subscription_url,
982 9bfa731 Dawsh 2y ago data_limit=db_user.data_limit,
983 9bfa731 Dawsh 2y ago usage=db_user.used_traffic,
984 9bfa731 Dawsh 2y ago expire=db_user.expire,
985 9bfa731 Dawsh 2y ago note=user.note
986 9bfa731 Dawsh 2y ago ),
987 9bfa731 Dawsh 2y ago call.message.chat.id,
988 9bfa731 Dawsh 2y ago call.message.message_id,
989 9bfa731 Dawsh 2y ago parse_mode='HTML',
990 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.user_menu(user_info={
991 9bfa731 Dawsh 2y ago 'status': 'disabled',
992 9bfa731 Dawsh 2y ago 'username': db_user.username
993 9bfa731 Dawsh 2y ago }, note=True))
994 9bfa731 Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
995 9bfa731 Dawsh 2y ago text = f'''\
996 a47eb4c Dawsh 2y ago ❌ <b>#Disabled #From_Bot</b>
997 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
998 a47eb4c Dawsh 2y ago <b>Username</b> : <code>{username}</code>
999 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1000 9bfa731 Dawsh 2y ago <b>By :</b> <a href="tg://user?id={call.from_user.id}">{call.from_user.full_name}</a>'''
1001 9bfa731 Dawsh 2y ago try:
1002 9bfa731 Dawsh 2y ago await bot.send_message(TELEGRAM_LOGGER_CHANNEL_ID, text, 'HTML')
1003 9bfa731 Dawsh 2y ago except:
1004 9bfa731 Dawsh 2y ago pass
1005 9bfa731 Dawsh 2y ago
1006 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("do_activate"), is_admin=True)
1007 9bfa731 Dawsh 2y ago async def activate_user(call: types.CallbackQuery):
1008 9bfa731 Dawsh 2y ago username = call.data.split(":")[1]
1009 9bfa731 Dawsh 2y ago with GetDB() as db:
1010 9bfa731 Dawsh 2y ago db_user = crud.get_user(db, username)
1011 9bfa731 Dawsh 2y ago crud.update_user(db, db_user, UserModify(
1012 9bfa731 Dawsh 2y ago username=username,
1013 9bfa731 Dawsh 2y ago status=UserStatusModify.active))
1014 9bfa731 Dawsh 2y ago await xray.operations.add_user(db_user)
1015 9bfa731 Dawsh 2y ago user = UserResponse.model_validate(db_user)
1016 9bfa731 Dawsh 2y ago await bot.edit_message_text(
1017 9bfa731 Dawsh 2y ago get_user_info_text(
1018 9bfa731 Dawsh 2y ago status='active',
1019 9bfa731 Dawsh 2y ago username=username,
1020 9bfa731 Dawsh 2y ago sub_url=user.subscription_url,
1021 9bfa731 Dawsh 2y ago data_limit=db_user.data_limit,
1022 9bfa731 Dawsh 2y ago usage=db_user.used_traffic,
1023 9bfa731 Dawsh 2y ago expire=db_user.expire,
1024 9bfa731 Dawsh 2y ago note=user.note
1025 9bfa731 Dawsh 2y ago ),
1026 9bfa731 Dawsh 2y ago call.message.chat.id,
1027 9bfa731 Dawsh 2y ago call.message.message_id,
1028 9bfa731 Dawsh 2y ago parse_mode='HTML',
1029 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.user_menu(user_info={
1030 9bfa731 Dawsh 2y ago 'status': 'active',
1031 9bfa731 Dawsh 2y ago 'username': db_user.username
1032 9bfa731 Dawsh 2y ago }, note=True))
1033 9bfa731 Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
1034 9bfa731 Dawsh 2y ago text = f'''\
1035 a47eb4c Dawsh 2y ago ✅ <b>#Activated #From_Bot</b>
1036 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1037 a47eb4c Dawsh 2y ago <b>Username</b> : <code>{username}</code>
1038 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1039 9bfa731 Dawsh 2y ago <b>By :</b> <a href="tg://user?id={call.from_user.id}">{call.from_user.full_name}</a>'''
1040 9bfa731 Dawsh 2y ago try:
1041 9bfa731 Dawsh 2y ago await bot.send_message(TELEGRAM_LOGGER_CHANNEL_ID, text, 'HTML')
1042 9bfa731 Dawsh 2y ago except:
1043 9bfa731 Dawsh 2y ago pass
1044 9bfa731 Dawsh 2y ago
1045 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("do_reset_usage"), is_admin=True)
1046 9bfa731 Dawsh 2y ago async def reset_all_usages(call: types.CallbackQuery):
1047 9bfa731 Dawsh 2y ago username = call.data.split(":")[1]
1048 9bfa731 Dawsh 2y ago with GetDB() as db:
1049 9bfa731 Dawsh 2y ago db_user = crud.get_user(db, username)
1050 9bfa731 Dawsh 2y ago crud.reset_user_data_usage(db, db_user)
1051 9bfa731 Dawsh 2y ago user = UserResponse.model_validate(db_user)
1052 9bfa731 Dawsh 2y ago await bot.edit_message_text(
1053 9bfa731 Dawsh 2y ago get_user_info_text(
1054 9bfa731 Dawsh 2y ago status=user.status,
1055 9bfa731 Dawsh 2y ago username=username,
1056 9bfa731 Dawsh 2y ago sub_url=user.subscription_url,
1057 9bfa731 Dawsh 2y ago data_limit=user.data_limit,
1058 9bfa731 Dawsh 2y ago usage=user.used_traffic,
1059 9bfa731 Dawsh 2y ago expire=user.expire,
1060 9bfa731 Dawsh 2y ago note=user.note
1061 9bfa731 Dawsh 2y ago ),
1062 9bfa731 Dawsh 2y ago call.message.chat.id,
1063 9bfa731 Dawsh 2y ago call.message.message_id,
1064 9bfa731 Dawsh 2y ago parse_mode='HTML',
1065 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.user_menu(user_info={
1066 9bfa731 Dawsh 2y ago 'status': user.status,
1067 9bfa731 Dawsh 2y ago 'username': user.username
1068 9bfa731 Dawsh 2y ago }, note=True))
1069 9bfa731 Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
1070 9bfa731 Dawsh 2y ago text = f'''\
1071 9bfa731 Dawsh 2y ago 🔁 <b>#Reset_usage #From_Bot</b>
1072 9bfa731 Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1073 a47eb4c Dawsh 2y ago <b>Username</b> : <code>{username}</code>
1074 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1075 9bfa731 Dawsh 2y ago <b>By :</b> <a href="tg://user?id={call.from_user.id}">{call.from_user.full_name}</a>'''
1076 9bfa731 Dawsh 2y ago try:
1077 9bfa731 Dawsh 2y ago await bot.send_message(TELEGRAM_LOGGER_CHANNEL_ID, text, 'HTML')
1078 9bfa731 Dawsh 2y ago except:
1079 9bfa731 Dawsh 2y ago pass
1080 9bfa731 Dawsh 2y ago
1081 9bfa731 Dawsh 2y ago
1082 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals("do_restart"), is_admin=True)
1083 9bfa731 Dawsh 2y ago async def restart_xray(call: types.CallbackQuery):
1084 9bfa731 Dawsh 2y ago m = await bot.edit_message_text(
1085 9bfa731 Dawsh 2y ago '🔄 Restarting XRay core...', call.message.chat.id, call.message.message_id)
1086 9bfa731 Dawsh 2y ago await xray.core.restart(xray.config.include_db_users())
1087 9bfa731 Dawsh 2y ago for node_id, node in list(xray.nodes.items()):
1088 9bfa731 Dawsh 2y ago if await node.is_healthy():
1089 9bfa731 Dawsh 2y ago await xray.operations.restart_node(node_id, xray.config.include_db_users())
1090 9bfa731 Dawsh 2y ago await bot.edit_message_text(
1091 9bfa731 Dawsh 2y ago '✅ XRay core restarted successfully.',
1092 9bfa731 Dawsh 2y ago m.chat.id, m.message_id,
1093 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.main_menu()
1094 9bfa731 Dawsh 2y ago )
1095 9bfa731 Dawsh 2y ago
1096 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_equals("edit_user_done"), is_admin=True)
1097 9bfa731 Dawsh 2y ago async def edit_user(call: types.CallbackQuery):
1098 9bfa731 Dawsh 2y ago if (username := mem_store.get(f'{call.message.chat.id}:username')) is None:
1099 9bfa731 Dawsh 2y ago try:
1100 9bfa731 Dawsh 2y ago await bot.delete_message(call.message.chat.id,
1101 9bfa731 Dawsh 2y ago call.message.message_id)
1102 9bfa731 Dawsh 2y ago except Exception:
1103 9bfa731 Dawsh 2y ago pass
1104 9bfa731 Dawsh 2y ago return await bot.send_message(
1105 9bfa731 Dawsh 2y ago call.message.chat.id,
1106 9bfa731 Dawsh 2y ago '❌ Bot reload detected. Please start over.',
1107 a47eb4c Dawsh 2y ago reply_markup=BotKeyboard.main_menu()
1108 a47eb4c Dawsh 2y ago )
1109 a47eb4c Dawsh 2y ago
1110 9bfa731 Dawsh 2y ago if not mem_store.get(f'{call.message.chat.id}:services'):
1111 9bfa731 Dawsh 2y ago return await bot.answer_callback_query(
1112 9bfa731 Dawsh 2y ago call.id,
1113 9bfa731 Dawsh 2y ago '❌ No Service selected.',
1114 9bfa731 Dawsh 2y ago show_alert=True
1115 9bfa731 Dawsh 2y ago )
1116 a47eb4c Dawsh 2y ago
1117 9bfa731 Dawsh 2y ago #inbounds: dict[str, list[str]] = {
1118 9bfa731 Dawsh 2y ago # k: v for k, v in mem_store.get(f'{call.message.chat.id}:protocols').items() if v}
1119 9bfa731 Dawsh 2y ago services: List[int] = mem_store.get(f"{call.message.chat.id}:services")
1120 a47eb4c Dawsh 2y ago
1121 9bfa731 Dawsh 2y ago with GetDB() as db:
1122 9bfa731 Dawsh 2y ago db_user = crud.get_user(db, username)
1123 9bfa731 Dawsh 2y ago if not db_user:
1124 9bfa731 Dawsh 2y ago return await bot.answer_callback_query(call.id, text=f"User not found!", show_alert=True)
1125 a47eb4c Dawsh 2y ago
1126 9bfa731 Dawsh 2y ago # proxies = {p.type.value: p.settings for p in db_user.proxies}
1127 a47eb4c Dawsh 2y ago
1128 9bfa731 Dawsh 2y ago """for protocol in xray.config.inbounds_by_protocol:
1129 9bfa731 Dawsh 2y ago if protocol in inbounds and protocol not in db_user.inbounds:
1130 9bfa731 Dawsh 2y ago proxies.update({protocol: {'flow': TELEGRAM_DEFAULT_VLESS_FLOW} if
1131 9bfa731 Dawsh 2y ago TELEGRAM_DEFAULT_VLESS_FLOW and protocol == ProxyTypes.VLESS else {}})
1132 9bfa731 Dawsh 2y ago elif protocol in db_user.inbounds and protocol not in inbounds:
1133 9bfa731 Dawsh 2y ago del proxies[protocol]"""
1134 a47eb4c Dawsh 2y ago
1135 9bfa731 Dawsh 2y ago modify = UserModify(
1136 9bfa731 Dawsh 2y ago username=username,
1137 9bfa731 Dawsh 2y ago # status=db_user.status,
1138 9bfa731 Dawsh 2y ago expire=int(mem_store.get(f'{call.message.chat.id}:expire_date').timestamp())
1139 9bfa731 Dawsh 2y ago if mem_store.get(f'{call.message.chat.id}:expire_date') else 0,
1140 9bfa731 Dawsh 2y ago data_limit=mem_store.get(f"{call.message.chat.id}:data_limit"),
1141 9bfa731 Dawsh 2y ago services=services)
1142 9bfa731 Dawsh 2y ago last_user = UserResponse.model_validate(db_user)
1143 9bfa731 Dawsh 2y ago db_user = crud.update_user(db, db_user, modify)
1144 a47eb4c Dawsh 2y ago
1145 9bfa731 Dawsh 2y ago user = UserResponse.model_validate(db_user)
1146 a47eb4c Dawsh 2y ago
1147 9bfa731 Dawsh 2y ago if user.status == UserStatus.active:
1148 9bfa731 Dawsh 2y ago await xray.operations.update_user(db_user)
1149 9bfa731 Dawsh 2y ago else:
1150 9bfa731 Dawsh 2y ago await xray.operations.remove_user(db_user)
1151 a47eb4c Dawsh 2y ago
1152 9bfa731 Dawsh 2y ago await bot.answer_callback_query(call.id, "✅ User updated successfully.")
1153 a47eb4c Dawsh 2y ago
1154 9bfa731 Dawsh 2y ago text = get_user_info_text(
1155 9bfa731 Dawsh 2y ago status=user.status,
1156 9bfa731 Dawsh 2y ago username=user.username,
1157 9bfa731 Dawsh 2y ago sub_url=user.subscription_url,
1158 9bfa731 Dawsh 2y ago data_limit=user.data_limit,
1159 9bfa731 Dawsh 2y ago usage=user.used_traffic,
1160 9bfa731 Dawsh 2y ago expire=user.expire,
1161 9bfa731 Dawsh 2y ago note=user.note
1162 9bfa731 Dawsh 2y ago )
1163 9bfa731 Dawsh 2y ago await bot.edit_message_text(
1164 9bfa731 Dawsh 2y ago text,
1165 9bfa731 Dawsh 2y ago call.message.chat.id,
1166 9bfa731 Dawsh 2y ago call.message.message_id,
1167 9bfa731 Dawsh 2y ago parse_mode="HTML",
1168 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.user_menu({
1169 9bfa731 Dawsh 2y ago 'username': db_user.username,
1170 9bfa731 Dawsh 2y ago 'status': db_user.status},
1171 9bfa731 Dawsh 2y ago note=True)
1172 9bfa731 Dawsh 2y ago )
1173 9bfa731 Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
1174 9bfa731 Dawsh 2y ago tag = f'\n➖➖➖➖➖➖➖➖➖ \n<b>By :</b> <a href="tg://user?id={call.from_user.id}">{call.from_user.full_name}</a>'
1175 9bfa731 Dawsh 2y ago if last_user.data_limit != user.data_limit:
1176 9bfa731 Dawsh 2y ago text = f'''\
1177 a47eb4c Dawsh 2y ago 📶 <b>#Traffic_Change #From_Bot</b>
1178 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1179 a47eb4c Dawsh 2y ago <b>Username :</b> <code>{user.username}</code>
1180 a47eb4c Dawsh 2y ago <b>Last Traffic Limit :</b> <code>{readable_size(last_user.data_limit) if last_user.data_limit else "Unlimited"}</code>
1181 a47eb4c Dawsh 2y ago <b>New Traffic Limit :</b> <code>{readable_size(user.data_limit) if user.data_limit else "Unlimited"}</code>{tag}'''
1182 9bfa731 Dawsh 2y ago try:
1183 9bfa731 Dawsh 2y ago await bot.send_message(TELEGRAM_LOGGER_CHANNEL_ID, text, 'HTML')
1184 9bfa731 Dawsh 2y ago except:
1185 9bfa731 Dawsh 2y ago pass
1186 9bfa731 Dawsh 2y ago if last_user.expire != user.expire:
1187 9bfa731 Dawsh 2y ago text = f'''\
1188 a47eb4c Dawsh 2y ago 📅 <b>#Expiry_Change #From_Bot</b>
1189 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1190 a47eb4c Dawsh 2y ago <b>Username :</b> <code>{user.username}</code>
1191 a47eb4c Dawsh 2y ago <b>Last Expire Date :</b> <code>\
1192 a47eb4c Dawsh 2y ago {datetime.fromtimestamp(last_user.expire).strftime('%H:%M:%S %Y-%m-%d') if last_user.expire else "Never"}</code>
1193 a47eb4c Dawsh 2y ago <b>New Expire Date :</b> <code>\
1194 a47eb4c Dawsh 2y ago {datetime.fromtimestamp(user.expire).strftime('%H:%M:%S %Y-%m-%d') if user.expire else "Never"}</code>{tag}'''
1195 9bfa731 Dawsh 2y ago try:
1196 9bfa731 Dawsh 2y ago await bot.send_message(TELEGRAM_LOGGER_CHANNEL_ID, text, 'HTML')
1197 9bfa731 Dawsh 2y ago except:
1198 9bfa731 Dawsh 2y ago pass
1199 9bfa731 Dawsh 2y ago if list(last_user.inbounds.values())[0] != list(user.inbounds.values())[0]:
1200 9bfa731 Dawsh 2y ago text = f'''\
1201 a47eb4c Dawsh 2y ago ⚙️ <b>#Inbounds_Change #From_Bot</b>
1202 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1203 a47eb4c Dawsh 2y ago <b>Username :</b> <code>{user.username}</code>
1204 a47eb4c Dawsh 2y ago <b>Last Proxies :</b> <code>{", ".join(list(last_user.inbounds.values())[0])}</code>
1205 a47eb4c Dawsh 2y ago <b>New Proxies :</b> <code>{", ".join(list(user.inbounds.values())[0])}</code>{tag}'''
1206 a47eb4c Dawsh 2y ago try:
1207 9bfa731 Dawsh 2y ago await bot.send_message(TELEGRAM_LOGGER_CHANNEL_ID, text, 'HTML')
1208 9bfa731 Dawsh 2y ago except:
1209 a47eb4c Dawsh 2y ago pass
1210 a47eb4c Dawsh 2y ago
1211 a47eb4c Dawsh 2y ago
1212 a47eb4c Dawsh 2y ago
1213 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith("add_user_done"), is_admin=True)
1214 9bfa731 Dawsh 2y ago async def delete_limpired(call: types.CallbackQuery):
1215 9bfa731 Dawsh 2y ago if mem_store.get(f'{call.message.chat.id}:username') is None:
1216 a47eb4c Dawsh 2y ago try:
1217 9bfa731 Dawsh 2y ago await bot.delete_message(call.message.chat.id,
1218 9bfa731 Dawsh 2y ago call.message.message_id)
1219 9bfa731 Dawsh 2y ago except Exception:
1220 9bfa731 Dawsh 2y ago pass
1221 9bfa731 Dawsh 2y ago return await bot.send_message(
1222 9bfa731 Dawsh 2y ago call.message.chat.id,
1223 9bfa731 Dawsh 2y ago '❌ Bot reload detected. Please start over.',
1224 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.main_menu()
1225 9bfa731 Dawsh 2y ago )
1226 a47eb4c Dawsh 2y ago
1227 9bfa731 Dawsh 2y ago if not mem_store.get(f'{call.message.chat.id}:services'):
1228 9bfa731 Dawsh 2y ago return await bot.answer_callback_query(
1229 9bfa731 Dawsh 2y ago call.id,
1230 9bfa731 Dawsh 2y ago '❌ No services selected.',
1231 9bfa731 Dawsh 2y ago show_alert=True
1232 9bfa731 Dawsh 2y ago )
1233 a47eb4c Dawsh 2y ago
1234 9bfa731 Dawsh 2y ago services: List[int] = mem_store.get(f'{call.message.chat.id}:services', [])
1235 9bfa731 Dawsh 2y ago
1236 9bfa731 Dawsh 2y ago new_user = UserCreate(
1237 9bfa731 Dawsh 2y ago username=mem_store.get(f'{call.message.chat.id}:username'),
1238 9bfa731 Dawsh 2y ago expire=int(mem_store.get(f'{call.message.chat.id}:expire_date').timestamp())
1239 9bfa731 Dawsh 2y ago if mem_store.get(f'{call.message.chat.id}:expire_date') else None,
1240 9bfa731 Dawsh 2y ago data_limit=mem_store.get(f'{call.message.chat.id}:data_limit')
1241 9bfa731 Dawsh 2y ago if mem_store.get(f'{call.message.chat.id}:data_limit') else None,
1242 9bfa731 Dawsh 2y ago services=services)
1243 9bfa731 Dawsh 2y ago try:
1244 9bfa731 Dawsh 2y ago with GetDB() as db:
1245 9bfa731 Dawsh 2y ago db_user = crud.create_user(db, new_user)
1246 9bfa731 Dawsh 2y ago services = db_user.services
1247 9bfa731 Dawsh 2y ago user = UserResponse.model_validate(db_user)
1248 9bfa731 Dawsh 2y ago except sqlalchemy.exc.IntegrityError:
1249 9bfa731 Dawsh 2y ago db.rollback()
1250 9bfa731 Dawsh 2y ago return await bot.answer_callback_query(
1251 9bfa731 Dawsh 2y ago call.id,
1252 9bfa731 Dawsh 2y ago '❌ Username already exists.',
1253 9bfa731 Dawsh 2y ago show_alert=True
1254 a47eb4c Dawsh 2y ago )
1255 a47eb4c Dawsh 2y ago
1256 9bfa731 Dawsh 2y ago await xray.operations.add_user(db_user)
1257 9bfa731 Dawsh 2y ago
1258 9bfa731 Dawsh 2y ago text = get_user_info_text(
1259 9bfa731 Dawsh 2y ago status=user.status,
1260 9bfa731 Dawsh 2y ago username=user.username,
1261 9bfa731 Dawsh 2y ago sub_url=user.subscription_url,
1262 9bfa731 Dawsh 2y ago data_limit=user.data_limit,
1263 9bfa731 Dawsh 2y ago usage=user.used_traffic,
1264 9bfa731 Dawsh 2y ago expire=user.expire,
1265 9bfa731 Dawsh 2y ago note=user.note
1266 9bfa731 Dawsh 2y ago )
1267 9bfa731 Dawsh 2y ago await bot.edit_message_text(
1268 9bfa731 Dawsh 2y ago text,
1269 9bfa731 Dawsh 2y ago call.message.chat.id,
1270 9bfa731 Dawsh 2y ago call.message.message_id,
1271 9bfa731 Dawsh 2y ago parse_mode="HTML",
1272 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.user_menu(user_info={'status': user.status, 'username': user.username}, note=True))
1273 9bfa731 Dawsh 2y ago
1274 9bfa731 Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
1275 9bfa731 Dawsh 2y ago text = f'''\
1276 a47eb4c Dawsh 2y ago 🆕 <b>#Created #From_Bot</b>
1277 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1278 a47eb4c Dawsh 2y ago <b>Username :</b> <code>{user.username}</code>
1279 a47eb4c Dawsh 2y ago <b>Traffic Limit :</b> <code>{readable_size(user.data_limit) if user.data_limit else "Unlimited"}</code>
1280 a47eb4c Dawsh 2y ago <b>Expire Date :</b> <code>\
1281 a47eb4c Dawsh 2y ago {datetime.fromtimestamp(user.expire).strftime('%H:%M:%S %Y-%m-%d') if user.expire else "Never"}</code>
1282 9bfa731 Dawsh 2y ago <b>Services :</b> <code>{"" if not services else ", ".join([s.name for s in services])}</code>
1283 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1284 9bfa731 Dawsh 2y ago <b>By :</b> <a href="tg://user?id={call.from_user.id}">{call.from_user.full_name}</a>'''
1285 9bfa731 Dawsh 2y ago try:
1286 9bfa731 Dawsh 2y ago await bot.send_message(TELEGRAM_LOGGER_CHANNEL_ID, text, 'HTML')
1287 9bfa731 Dawsh 2y ago except:
1288 9bfa731 Dawsh 2y ago pass
1289 a47eb4c Dawsh 2y ago
1290 9bfa731 Dawsh 2y ago
1291 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith(['do_delete_expired', 'do_delete_limited']), is_admin=True)
1292 9bfa731 Dawsh 2y ago async def delete_limpired(call: types.CallbackQuery):
1293 9bfa731 Dawsh 2y ago await bot.edit_message_text(
1294 9bfa731 Dawsh 2y ago '⏳ <b>In Progress...</b>',
1295 9bfa731 Dawsh 2y ago call.message.chat.id,
1296 9bfa731 Dawsh 2y ago call.message.message_id,
1297 9bfa731 Dawsh 2y ago parse_mode="HTML")
1298 9bfa731 Dawsh 2y ago with GetDB() as db:
1299 9bfa731 Dawsh 2y ago depleted_users = crud.get_users(
1300 9bfa731 Dawsh 2y ago db, status=[UserStatus.limited if data == 'delete_limited' else UserStatus.expired])
1301 9bfa731 Dawsh 2y ago file_name = f'{data[8:]}_users_{int(now.timestamp()*1000)}.txt'
1302 9bfa731 Dawsh 2y ago with open(file_name, 'w') as f:
1303 9bfa731 Dawsh 2y ago f.write('USERNAME\tEXIPRY\tUSAGE/LIMIT\tSTATUS\n')
1304 9bfa731 Dawsh 2y ago deleted = 0
1305 9bfa731 Dawsh 2y ago for user in depleted_users:
1306 9bfa731 Dawsh 2y ago try:
1307 9bfa731 Dawsh 2y ago crud.remove_user(db, user)
1308 9bfa731 Dawsh 2y ago await xray.operations.remove_user(user)
1309 9bfa731 Dawsh 2y ago deleted +=1
1310 9bfa731 Dawsh 2y ago f.write(\
1311 a47eb4c Dawsh 2y ago f'{user.username}\
1312 a47eb4c Dawsh 2y ago \t{datetime.fromtimestamp(user.expire) if user.expire else "never"}\
1313 a47eb4c Dawsh 2y ago \t{readable_size(user.used_traffic) if user.used_traffic else 0}\
1314 a47eb4c Dawsh 2y ago /{readable_size(user.data_limit) if user.data_limit else "Unlimited"}\
1315 a47eb4c Dawsh 2y ago \t{user.status}\n')
1316 9bfa731 Dawsh 2y ago except:
1317 9bfa731 Dawsh 2y ago db.rollback()
1318 9bfa731 Dawsh 2y ago await bot.edit_message_text(
1319 9bfa731 Dawsh 2y ago f'✅ <code>{deleted}</code>/<code>{len(depleted_users)}</code> <b>{data[7:].title()} Users Deleted</b>',
1320 9bfa731 Dawsh 2y ago call.message.chat.id,
1321 9bfa731 Dawsh 2y ago call.message.message_id,
1322 9bfa731 Dawsh 2y ago parse_mode="HTML",
1323 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.main_menu())
1324 9bfa731 Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
1325 9bfa731 Dawsh 2y ago text = f'''\
1326 a47eb4c Dawsh 2y ago 🗑 <b>#Delete #{data[7:].title()} #From_Bot</b>
1327 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1328 a47eb4c Dawsh 2y ago <b>Count:</b> <code>{deleted}</code>
1329 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1330 9bfa731 Dawsh 2y ago <b>By :</b> <a href="tg://user?id={call.from_user.id}">{call.from_user.full_name}</a>'''
1331 9bfa731 Dawsh 2y ago try:
1332 9bfa731 Dawsh 2y ago await bot.send_document(TELEGRAM_LOGGER_CHANNEL_ID, open(file_name, 'rb'), caption=text, parse_mode='HTML')
1333 9bfa731 Dawsh 2y ago os.remove(file_name)
1334 9bfa731 Dawsh 2y ago except:
1335 9bfa731 Dawsh 2y ago pass
1336 9bfa731 Dawsh 2y ago
1337 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('do_add_data:'), is_admin=True)
1338 9bfa731 Dawsh 2y ago async def add_data_to_all(call: types.CallbackQuery):
1339 9bfa731 Dawsh 2y ago schedule_delete_message(
1340 9bfa731 Dawsh 2y ago call.message.chat.id,
1341 9bfa731 Dawsh 2y ago (await bot.send_message(chat_id, '⏳ <b>In Progress...</b>', 'HTML')).id)
1342 9bfa731 Dawsh 2y ago data_limit = float(call.data.split(":")[1]) * 1024 * 1024 * 1024
1343 9bfa731 Dawsh 2y ago with GetDB() as db:
1344 9bfa731 Dawsh 2y ago users = crud.get_users(db)
1345 9bfa731 Dawsh 2y ago counter = 0
1346 9bfa731 Dawsh 2y ago file_name = f'new_data_limit_users_{int(now.timestamp()*1000)}.txt'
1347 9bfa731 Dawsh 2y ago with open(file_name, 'w') as f:
1348 9bfa731 Dawsh 2y ago f.write('USERNAME\tEXIPRY\tUSAGE/LIMIT\tSTATUS\n')
1349 9bfa731 Dawsh 2y ago for user in users:
1350 a47eb4c Dawsh 2y ago try:
1351 9bfa731 Dawsh 2y ago if user.data_limit and user.status not in [UserStatus.limited, UserStatus.expired]:
1352 9bfa731 Dawsh 2y ago user = crud.update_user(db, user, UserModify(username=user.username, data_limit=(user.data_limit + data_limit)))
1353 9bfa731 Dawsh 2y ago counter += 1
1354 9bfa731 Dawsh 2y ago f.write(
1355 9bfa731 Dawsh 2y ago f'{user.username}\
1356 a47eb4c Dawsh 2y ago \t{datetime.fromtimestamp(user.expire) if user.expire else "never"}\
1357 a47eb4c Dawsh 2y ago \t{readable_size(user.used_traffic) if user.used_traffic else 0}\
1358 a47eb4c Dawsh 2y ago /{readable_size(user.data_limit) if user.data_limit else "Unlimited"}\
1359 a47eb4c Dawsh 2y ago \t{user.status}\n')
1360 9bfa731 Dawsh 2y ago except:
1361 9bfa731 Dawsh 2y ago db.rollback()
1362 9bfa731 Dawsh 2y ago await cleanup_messages(chat_id)
1363 9bfa731 Dawsh 2y ago await bot.send_message(
1364 9bfa731 Dawsh 2y ago chat_id,
1365 9bfa731 Dawsh 2y ago f'✅ <b>{counter}/{len(users)} Users</b> Data Limit according to <code>{"+" if data_limit > 0 else "-"}{readable_size(abs(data_limit))}</code>',
1366 9bfa731 Dawsh 2y ago 'HTML',
1367 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.main_menu())
1368 9bfa731 Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
1369 9bfa731 Dawsh 2y ago text = f'''\
1370 a47eb4c Dawsh 2y ago 📶 <b>#Traffic_Change #From_Bot</b>
1371 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1372 a47eb4c Dawsh 2y ago <b>According to:</b> <code>{"+" if data_limit > 0 else "-"}{readable_size(abs(data_limit))}</code>
1373 a47eb4c Dawsh 2y ago <b>Count:</b> <code>{counter}</code>
1374 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1375 9bfa731 Dawsh 2y ago <b>By :</b> <a href="tg://user?id={call.from_user.id}">{call.from_user.full_name}</a>'''
1376 9bfa731 Dawsh 2y ago try:
1377 9bfa731 Dawsh 2y ago await bot.send_document(TELEGRAM_LOGGER_CHANNEL_ID, open(file_name, 'rb'), caption=text, parse_mode='HTML')
1378 9bfa731 Dawsh 2y ago os.remove(file_name)
1379 9bfa731 Dawsh 2y ago except:
1380 9bfa731 Dawsh 2y ago pass
1381 a47eb4c Dawsh 2y ago
1382 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('do_add_time:'), is_admin=True)
1383 9bfa731 Dawsh 2y ago async def add_time_to_all(call: types.CallbackQuery):
1384 9bfa731 Dawsh 2y ago schedule_delete_message(
1385 9bfa731 Dawsh 2y ago call.message.chat.id,
1386 9bfa731 Dawsh 2y ago (await bot.send_message(chat_id, '⏳ <b>In Progress...</b>', 'HTML')).id)
1387 9bfa731 Dawsh 2y ago days = int(call.data.split(":")[1])
1388 9bfa731 Dawsh 2y ago with GetDB() as db:
1389 9bfa731 Dawsh 2y ago users = crud.get_users(db)
1390 9bfa731 Dawsh 2y ago counter = 0
1391 9bfa731 Dawsh 2y ago file_name = f'new_expiry_users_{int(now.timestamp()*1000)}.txt'
1392 9bfa731 Dawsh 2y ago with open(file_name, 'w') as f:
1393 9bfa731 Dawsh 2y ago f.write('USERNAME\tEXIPRY\tUSAGE/LIMIT\tSTATUS\n')
1394 9bfa731 Dawsh 2y ago for user in users:
1395 9bfa731 Dawsh 2y ago try:
1396 9bfa731 Dawsh 2y ago if user.expire and user.status not in [UserStatus.limited, UserStatus.expired]:
1397 9bfa731 Dawsh 2y ago user = crud.update_user(
1398 9bfa731 Dawsh 2y ago db, user,
1399 9bfa731 Dawsh 2y ago UserModify(
1400 9bfa731 Dawsh 2y ago username=user.username,
1401 9bfa731 Dawsh 2y ago expire=int(
1402 9bfa731 Dawsh 2y ago (datetime.fromtimestamp(user.expire) + relativedelta(days=days)).timestamp())))
1403 9bfa731 Dawsh 2y ago counter += 1
1404 9bfa731 Dawsh 2y ago f.write(
1405 9bfa731 Dawsh 2y ago f'{user.username}\
1406 a47eb4c Dawsh 2y ago \t{datetime.fromtimestamp(user.expire) if user.expire else "never"}\
1407 a47eb4c Dawsh 2y ago \t{readable_size(user.used_traffic) if user.used_traffic else 0}\
1408 a47eb4c Dawsh 2y ago /{readable_size(user.data_limit) if user.data_limit else "Unlimited"}\
1409 a47eb4c Dawsh 2y ago \t{user.status}\n')
1410 9bfa731 Dawsh 2y ago except:
1411 9bfa731 Dawsh 2y ago db.rollback()
1412 9bfa731 Dawsh 2y ago await cleanup_messages(chat_id)
1413 9bfa731 Dawsh 2y ago await bot.send_message(
1414 9bfa731 Dawsh 2y ago chat_id,
1415 9bfa731 Dawsh 2y ago f'✅ <b>{counter}/{len(users)} Users</b> Expiry Changes according to {days} Days',
1416 9bfa731 Dawsh 2y ago 'HTML',
1417 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.main_menu())
1418 9bfa731 Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
1419 9bfa731 Dawsh 2y ago text = f'''\
1420 a47eb4c Dawsh 2y ago 📅 <b>#Expiry_Change #From_Bot</b>
1421 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1422 a47eb4c Dawsh 2y ago <b>According to:</b> <code>{days} Days</code>
1423 a47eb4c Dawsh 2y ago <b>Count:</b> <code>{counter}</code>
1424 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1425 9bfa731 Dawsh 2y ago <b>By :</b> <a href="tg://user?id={call.from_user.id}">{call.from_user.full_name}</a>'''
1426 9bfa731 Dawsh 2y ago try:
1427 9bfa731 Dawsh 2y ago await bot.send_document(TELEGRAM_LOGGER_CHANNEL_ID, open(file_name, 'rb'), caption=text, parse_mode='HTML')
1428 9bfa731 Dawsh 2y ago os.remove(file_name)
1429 9bfa731 Dawsh 2y ago except:
1430 9bfa731 Dawsh 2y ago pass
1431 9bfa731 Dawsh 2y ago
1432 9bfa731 Dawsh 2y ago @bot.callback_query_handler(query_startswith('do_revoke:'), is_admin=True)
1433 9bfa731 Dawsh 2y ago async def revoke_sub(call: types.CallbackQuery):
1434 9bfa731 Dawsh 2y ago username = call.data.split(":")[1]
1435 9bfa731 Dawsh 2y ago with GetDB() as db:
1436 9bfa731 Dawsh 2y ago db_user = crud.get_user(db, username)
1437 9bfa731 Dawsh 2y ago if not db_user:
1438 9bfa731 Dawsh 2y ago return await bot.answer_callback_query(call.id, text=f"User not found!", show_alert=True)
1439 9bfa731 Dawsh 2y ago db_user = crud.revoke_user_sub(db, db_user)
1440 9bfa731 Dawsh 2y ago user = UserResponse.model_validate(db_user)
1441 9bfa731 Dawsh 2y ago text = get_user_info_text(
1442 9bfa731 Dawsh 2y ago status=user.status,
1443 9bfa731 Dawsh 2y ago username=user.username,
1444 9bfa731 Dawsh 2y ago sub_url=user.subscription_url,
1445 9bfa731 Dawsh 2y ago expire=user.expire,
1446 9bfa731 Dawsh 2y ago data_limit=user.data_limit,
1447 9bfa731 Dawsh 2y ago usage=user.used_traffic,
1448 9bfa731 Dawsh 2y ago note=user.note)
1449 9bfa731 Dawsh 2y ago await bot.edit_message_text(
1450 9bfa731 Dawsh 2y ago f'✅ Subscription Successfully Revoked!\n\n{text}',
1451 a47eb4c Dawsh 2y ago call.message.chat.id,
1452 a47eb4c Dawsh 2y ago call.message.message_id,
1453 9bfa731 Dawsh 2y ago parse_mode="HTML",
1454 9bfa731 Dawsh 2y ago reply_markup=BotKeyboard.user_menu(user_info={'status': user.status, 'username': user.username}, note=True))
1455 a47eb4c Dawsh 2y ago
1456 9bfa731 Dawsh 2y ago if TELEGRAM_LOGGER_CHANNEL_ID:
1457 9bfa731 Dawsh 2y ago text = f'''\
1458 a47eb4c Dawsh 2y ago 🚫 <b>#Revoke_sub #From_Bot</b>
1459 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1460 a47eb4c Dawsh 2y ago <b>Username:</b> <code>{username}</code>
1461 a47eb4c Dawsh 2y ago ➖➖➖➖➖➖➖➖➖
1462 9bfa731 Dawsh 2y ago <b>By :</b> <a href="tg://user?id={call.from_user.id}">{call.from_user.full_name}</a>'''
1463 9bfa731 Dawsh 2y ago try:
1464 9bfa731 Dawsh 2y ago await bot.send_message(TELEGRAM_LOGGER_CHANNEL_ID, text, 'HTML')
1465 9bfa731 Dawsh 2y ago except:
1466 9bfa731 Dawsh 2y ago pass
1467 a47eb4c Dawsh 2y ago
1468 a47eb4c Dawsh 2y ago
1469 a47eb4c Dawsh 2y ago @bot.message_handler(func=lambda message: True, is_admin=True)
1470 a47eb4c Dawsh 2y ago async def search(message: types.Message):
1471 a47eb4c Dawsh 2y ago with GetDB() as db:
1472 a47eb4c Dawsh 2y ago db_user = crud.get_user(db, message.text)
1473 a47eb4c Dawsh 2y ago if not db_user:
1474 a47eb4c Dawsh 2y ago return await bot.reply_to(message, '❌ User not found.')
1475 a47eb4c Dawsh 2y ago user = UserResponse.model_validate(db_user)
1476 a47eb4c Dawsh 2y ago text = get_user_info_text(
1477 a47eb4c Dawsh 2y ago status=user.status,
1478 a47eb4c Dawsh 2y ago username=user.username,
1479 a47eb4c Dawsh 2y ago sub_url=user.subscription_url,
1480 a47eb4c Dawsh 2y ago expire=user.expire,
1481 a47eb4c Dawsh 2y ago data_limit=user.data_limit,
1482 a47eb4c Dawsh 2y ago usage=user.used_traffic,
1483 a47eb4c Dawsh 2y ago note=user.note)
1484 a47eb4c Dawsh 2y ago return await bot.reply_to(message, text, parse_mode="html", reply_markup=BotKeyboard.user_menu(user_info={
1485 a47eb4c Dawsh 2y ago 'status': user.status,
1486 a47eb4c Dawsh 2y ago 'username': user.username
1487 a47eb4c Dawsh 2y ago }, note=True))