66import logging
77from datetime import datetime
88
9- from telegram import Update , InlineKeyboardButton , InlineKeyboardMarkup
9+ from telegram import InlineKeyboardButton , InlineKeyboardMarkup , Update
1010from telegram .ext import ContextTypes
1111
12- from utils .auth import admin_required
1312from config_manager import (
14- get_config_manager ,
1513 UserRole ,
14+ get_config_manager ,
1615)
16+ from utils .auth import admin_required
1717from utils .telegram_formatters import escape_markdown_v2
1818
1919logger = logging .getLogger (__name__ )
@@ -60,6 +60,7 @@ def _format_timestamp(ts: float) -> str:
6060async def admin_command (update : Update , context : ContextTypes .DEFAULT_TYPE ) -> None :
6161 """Handle /admin command - show admin panel."""
6262 from handlers import clear_all_input_states
63+
6364 clear_all_input_states (context )
6465
6566 cm = get_config_manager ()
@@ -74,14 +75,14 @@ async def admin_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> N
7475 )
7576
7677 await update .message .reply_text (
77- message ,
78- parse_mode = "MarkdownV2" ,
79- reply_markup = _get_admin_menu_keyboard ()
78+ message , parse_mode = "MarkdownV2" , reply_markup = _get_admin_menu_keyboard ()
8079 )
8180
8281
8382@admin_required
84- async def admin_callback_handler (update : Update , context : ContextTypes .DEFAULT_TYPE ) -> None :
83+ async def admin_callback_handler (
84+ update : Update , context : ContextTypes .DEFAULT_TYPE
85+ ) -> None :
8586 """Handle admin panel callbacks."""
8687 query = update .callback_query
8788
@@ -137,9 +138,7 @@ async def _show_admin_menu(query, context: ContextTypes.DEFAULT_TYPE) -> None:
137138 )
138139
139140 await query .edit_message_text (
140- message ,
141- parse_mode = "MarkdownV2" ,
142- reply_markup = _get_admin_menu_keyboard ()
141+ message , parse_mode = "MarkdownV2" , reply_markup = _get_admin_menu_keyboard ()
143142 )
144143
145144
@@ -149,40 +148,41 @@ async def _show_pending_users(query, context: ContextTypes.DEFAULT_TYPE) -> None
149148 pending = cm .get_pending_users ()
150149
151150 if not pending :
152- message = (
153- "👥 *Pending Requests*\n \n "
154- "No pending access requests\\ ."
155- )
151+ message = "👥 *Pending Requests*\n \n " "No pending access requests\\ ."
156152 keyboard = [[InlineKeyboardButton ("🔙 Back" , callback_data = "admin:back" )]]
157153 await query .edit_message_text (
158154 message ,
159155 parse_mode = "MarkdownV2" ,
160- reply_markup = InlineKeyboardMarkup (keyboard )
156+ reply_markup = InlineKeyboardMarkup (keyboard ),
161157 )
162158 return
163159
164160 message = f"👥 *Pending Requests* \\ ({ len (pending )} \\ )\n \n "
165161
166162 keyboard = []
167163 for user in pending :
168- user_id = user [' user_id' ]
169- username = user .get (' username' ) or ' N/A'
170- created = _format_timestamp (user .get (' created_at' , 0 ))
164+ user_id = user [" user_id" ]
165+ username = user .get (" username" ) or " N/A"
166+ created = _format_timestamp (user .get (" created_at" , 0 ))
171167
172168 message += f"• `{ user_id } ` \\ (@{ escape_markdown_v2 (username )} \\ )\n "
173169 message += f" Requested: { escape_markdown_v2 (created )} \n \n "
174170
175- keyboard .append ([
176- InlineKeyboardButton (f"✓ Approve { user_id } " , callback_data = f"admin:approve_{ user_id } " ),
177- InlineKeyboardButton (f"✕ Reject" , callback_data = f"admin:reject_{ user_id } " ),
178- ])
171+ keyboard .append (
172+ [
173+ InlineKeyboardButton (
174+ f"✓ Approve { user_id } " , callback_data = f"admin:approve_{ user_id } "
175+ ),
176+ InlineKeyboardButton (
177+ f"✕ Reject" , callback_data = f"admin:reject_{ user_id } "
178+ ),
179+ ]
180+ )
179181
180182 keyboard .append ([InlineKeyboardButton ("🔙 Back" , callback_data = "admin:back" )])
181183
182184 await query .edit_message_text (
183- message ,
184- parse_mode = "MarkdownV2" ,
185- reply_markup = InlineKeyboardMarkup (keyboard )
185+ message , parse_mode = "MarkdownV2" , reply_markup = InlineKeyboardMarkup (keyboard )
186186 )
187187
188188
@@ -197,20 +197,25 @@ async def _show_all_users(query, context: ContextTypes.DEFAULT_TYPE) -> None:
197197 await query .edit_message_text (
198198 message ,
199199 parse_mode = "MarkdownV2" ,
200- reply_markup = InlineKeyboardMarkup (keyboard )
200+ reply_markup = InlineKeyboardMarkup (keyboard ),
201201 )
202202 return
203203
204204 # Group by role
205205 by_role = {}
206206 for user in users :
207- role = user .get (' role' , ' unknown' )
207+ role = user .get (" role" , " unknown" )
208208 by_role .setdefault (role , []).append (user )
209209
210210 message = f"📋 *All Users* \\ ({ len (users )} \\ )\n \n "
211211
212212 # Show in order: admin, user, pending, blocked
213- role_order = [UserRole .ADMIN .value , UserRole .USER .value , UserRole .PENDING .value , UserRole .BLOCKED .value ]
213+ role_order = [
214+ UserRole .ADMIN .value ,
215+ UserRole .USER .value ,
216+ UserRole .PENDING .value ,
217+ UserRole .BLOCKED .value ,
218+ ]
214219
215220 keyboard = []
216221 for role in role_order :
@@ -222,16 +227,18 @@ async def _show_all_users(query, context: ContextTypes.DEFAULT_TYPE) -> None:
222227 message += f"*{ badge } { role .title ()} * \\ ({ len (role_users )} \\ )\n "
223228
224229 for user in role_users [:5 ]: # Limit to 5 per role in message
225- user_id = user [' user_id' ]
226- username = user .get (' username' ) or ' N/A'
230+ user_id = user [" user_id" ]
231+ username = user .get (" username" ) or " N/A"
227232 message += f" • `{ user_id } ` @{ escape_markdown_v2 (username )} \n "
228233
229- keyboard .append ([
230- InlineKeyboardButton (
231- f"{ badge } { user_id } (@{ username [:10 ]} )" ,
232- callback_data = f"admin:user_{ user_id } "
233- )
234- ])
234+ keyboard .append (
235+ [
236+ InlineKeyboardButton (
237+ f"{ badge } { user_id } (@{ username [:10 ]} )" ,
238+ callback_data = f"admin:user_{ user_id } " ,
239+ )
240+ ]
241+ )
235242
236243 if len (role_users ) > 5 :
237244 message += f" _\\ .\\ .\\ . and { len (role_users ) - 5 } more_\n "
@@ -241,13 +248,13 @@ async def _show_all_users(query, context: ContextTypes.DEFAULT_TYPE) -> None:
241248 keyboard .append ([InlineKeyboardButton ("🔙 Back" , callback_data = "admin:back" )])
242249
243250 await query .edit_message_text (
244- message ,
245- parse_mode = "MarkdownV2" ,
246- reply_markup = InlineKeyboardMarkup (keyboard )
251+ message , parse_mode = "MarkdownV2" , reply_markup = InlineKeyboardMarkup (keyboard )
247252 )
248253
249254
250- async def _show_user_details (query , context : ContextTypes .DEFAULT_TYPE , user_id : int ) -> None :
255+ async def _show_user_details (
256+ query , context : ContextTypes .DEFAULT_TYPE , user_id : int
257+ ) -> None :
251258 """Show details for a specific user."""
252259 cm = get_config_manager ()
253260 user = cm .get_user (user_id )
@@ -256,12 +263,12 @@ async def _show_user_details(query, context: ContextTypes.DEFAULT_TYPE, user_id:
256263 await query .answer ("User not found" , show_alert = True )
257264 return
258265
259- role = user .get (' role' , ' unknown' )
260- username = user .get (' username' ) or ' N/A'
261- created = _format_timestamp (user .get (' created_at' , 0 ))
262- approved_at = _format_timestamp (user .get (' approved_at' ))
263- approved_by = user .get (' approved_by' )
264- notes = user .get (' notes' ) or ' None'
266+ role = user .get (" role" , " unknown" )
267+ username = user .get (" username" ) or " N/A"
268+ created = _format_timestamp (user .get (" created_at" , 0 ))
269+ approved_at = _format_timestamp (user .get (" approved_at" ))
270+ approved_by = user .get (" approved_by" )
271+ notes = user .get (" notes" ) or " None"
265272
266273 badge = _format_user_role_badge (role )
267274
@@ -277,7 +284,7 @@ async def _show_user_details(query, context: ContextTypes.DEFAULT_TYPE, user_id:
277284 message += f"*Approved:* { escape_markdown_v2 (approved_at )} \n "
278285 if approved_by :
279286 message += f"*Approved By:* `{ approved_by } `\n "
280- if notes != ' None' :
287+ if notes != " None" :
281288 message += f"*Notes:* { escape_markdown_v2 (notes )} \n "
282289
283290 # Show servers owned by user
@@ -301,29 +308,45 @@ async def _show_user_details(query, context: ContextTypes.DEFAULT_TYPE, user_id:
301308 admin_id = cm .admin_id
302309
303310 if role == UserRole .PENDING .value :
304- keyboard .append ([
305- InlineKeyboardButton ("✓ Approve" , callback_data = f"admin:approve_{ user_id } " ),
306- InlineKeyboardButton ("✕ Reject" , callback_data = f"admin:reject_{ user_id } " ),
307- ])
311+ keyboard .append (
312+ [
313+ InlineKeyboardButton (
314+ "✓ Approve" , callback_data = f"admin:approve_{ user_id } "
315+ ),
316+ InlineKeyboardButton (
317+ "✕ Reject" , callback_data = f"admin:reject_{ user_id } "
318+ ),
319+ ]
320+ )
308321 elif role == UserRole .BLOCKED .value :
309- keyboard .append ([
310- InlineKeyboardButton ("🔓 Unblock" , callback_data = f"admin:unblock_{ user_id } " ),
311- ])
322+ keyboard .append (
323+ [
324+ InlineKeyboardButton (
325+ "🔓 Unblock" , callback_data = f"admin:unblock_{ user_id } "
326+ ),
327+ ]
328+ )
312329 elif role == UserRole .USER .value and user_id != admin_id :
313- keyboard .append ([
314- InlineKeyboardButton ("🚫 Block" , callback_data = f"admin:block_{ user_id } " ),
315- ])
330+ keyboard .append (
331+ [
332+ InlineKeyboardButton (
333+ "🚫 Block" , callback_data = f"admin:block_{ user_id } "
334+ ),
335+ ]
336+ )
316337
317- keyboard .append ([InlineKeyboardButton ("🔙 Back to Users" , callback_data = "admin:users" )])
338+ keyboard .append (
339+ [InlineKeyboardButton ("🔙 Back to Users" , callback_data = "admin:users" )]
340+ )
318341
319342 await query .edit_message_text (
320- message ,
321- parse_mode = "MarkdownV2" ,
322- reply_markup = InlineKeyboardMarkup (keyboard )
343+ message , parse_mode = "MarkdownV2" , reply_markup = InlineKeyboardMarkup (keyboard )
323344 )
324345
325346
326- async def _approve_user (query , context : ContextTypes .DEFAULT_TYPE , user_id : int ) -> None :
347+ async def _approve_user (
348+ query , context : ContextTypes .DEFAULT_TYPE , user_id : int
349+ ) -> None :
327350 """Approve a pending user."""
328351 cm = get_config_manager ()
329352 admin_id = query .from_user .id
@@ -338,7 +361,7 @@ async def _approve_user(query, context: ContextTypes.DEFAULT_TYPE, user_id: int)
338361 "Your access request has been approved\\ .\n "
339362 "Use /start to begin\\ ."
340363 ),
341- parse_mode = "MarkdownV2"
364+ parse_mode = "MarkdownV2" ,
342365 )
343366 except Exception as e :
344367 logger .warning (f"Failed to notify user { user_id } of approval: { e } " )
@@ -379,7 +402,9 @@ async def _block_user(query, context: ContextTypes.DEFAULT_TYPE, user_id: int) -
379402 await _show_user_details (query , context , user_id )
380403
381404
382- async def _unblock_user (query , context : ContextTypes .DEFAULT_TYPE , user_id : int ) -> None :
405+ async def _unblock_user (
406+ query , context : ContextTypes .DEFAULT_TYPE , user_id : int
407+ ) -> None :
383408 """Unblock a user."""
384409 cm = get_config_manager ()
385410 admin_id = query .from_user .id
@@ -404,21 +429,21 @@ async def _show_audit_log(query, context: ContextTypes.DEFAULT_TYPE) -> None:
404429 await query .edit_message_text (
405430 message ,
406431 parse_mode = "MarkdownV2" ,
407- reply_markup = InlineKeyboardMarkup (keyboard )
432+ reply_markup = InlineKeyboardMarkup (keyboard ),
408433 )
409434 return
410435
411436 message = "📜 *Audit Log* \\ (Recent 10\\ )\n \n "
412437
413438 for entry in entries :
414- ts = _format_timestamp (entry .get (' timestamp' , 0 ))
415- action = entry .get (' action' , ' unknown' )
416- actor = entry .get (' actor_id' , 0 )
417- target_type = entry .get (' target_type' , '' )
418- target_id = entry .get (' target_id' , '' )
439+ ts = _format_timestamp (entry .get (" timestamp" , 0 ))
440+ action = entry .get (" action" , " unknown" )
441+ actor = entry .get (" actor_id" , 0 )
442+ target_type = entry .get (" target_type" , "" )
443+ target_id = entry .get (" target_id" , "" )
419444
420445 # Format action nicely
421- action_display = action .replace ('_' , ' ' ).title ()
446+ action_display = action .replace ("_" , " " ).title ()
422447
423448 message += f"• *{ escape_markdown_v2 (ts )} *\n "
424449 message += f" { escape_markdown_v2 (action_display )} \n "
@@ -427,9 +452,7 @@ async def _show_audit_log(query, context: ContextTypes.DEFAULT_TYPE) -> None:
427452 keyboard = [[InlineKeyboardButton ("🔙 Back" , callback_data = "admin:back" )]]
428453
429454 await query .edit_message_text (
430- message ,
431- parse_mode = "MarkdownV2" ,
432- reply_markup = InlineKeyboardMarkup (keyboard )
455+ message , parse_mode = "MarkdownV2" , reply_markup = InlineKeyboardMarkup (keyboard )
433456 )
434457
435458
@@ -444,7 +467,7 @@ async def _show_stats(query, context: ContextTypes.DEFAULT_TYPE) -> None:
444467 # Count by role
445468 role_counts = {}
446469 for user in users :
447- role = user .get (' role' , ' unknown' )
470+ role = user .get (" role" , " unknown" )
448471 role_counts [role ] = role_counts .get (role , 0 ) + 1
449472
450473 # Count servers by owner
@@ -471,14 +494,12 @@ async def _show_stats(query, context: ContextTypes.DEFAULT_TYPE) -> None:
471494 keyboard = [[InlineKeyboardButton ("🔙 Back" , callback_data = "admin:back" )]]
472495
473496 await query .edit_message_text (
474- message ,
475- parse_mode = "MarkdownV2" ,
476- reply_markup = InlineKeyboardMarkup (keyboard )
497+ message , parse_mode = "MarkdownV2" , reply_markup = InlineKeyboardMarkup (keyboard )
477498 )
478499
479500
480501__all__ = [
481- ' admin_command' ,
482- ' admin_callback_handler' ,
483- ' _show_admin_menu' ,
502+ " admin_command" ,
503+ " admin_callback_handler" ,
504+ " _show_admin_menu" ,
484505]
0 commit comments