2424
2525# --- Helper ---
2626async def get_account_id_from_client (client : TelegramClient ) -> Optional [int ]:
27+ """
28+ Safely retrieves the account_id associated with a client instance.
29+
30+ Args:
31+ client (TelegramClient): The client instance.
32+
33+ Returns:
34+ Optional[int]: The account ID if available, otherwise None.
35+ """
2736 return client .current_account_id
2837
2938# --- Module Management ---
30- # ... (Placeholders remain unchanged)
39+ async def load_account_modules (account_id : int , client_instance : TelegramClient , current_help_info : Dict [str , str ]):
40+ # Placeholder
41+ pass
42+
43+ async def addmod_handler (event : events .NewMessage .Event ):
44+ await event .edit ("Команда `.addmod` в разработке." )
45+
46+ async def delmod_handler (event : events .NewMessage .Event ):
47+ await event .edit ("Команда `.delmod` в разработке." )
48+
49+ async def trustmod_handler (event : events .NewMessage .Event ):
50+ await event .edit ("Команда `.trustmod` в разработке." )
51+
52+ async def configmod_handler (event : events .NewMessage .Event ):
53+ await event .edit ("Команда `.configmod` в разработке." )
54+
55+ async def update_modules_handler (event : events .NewMessage .Event ):
56+ await event .edit ("Команда `.updatemodules` в разработке." )
3157
3258async def logs_handler (event : events .NewMessage .Event ):
33- # ... (Implementation from previous response remains unchanged)
59+ """Handles the .logs command for fetching and managing logs."""
60+ await event .edit (await event .client .get_string ("logs_processing" ))
61+
62+ try :
63+ args : List [str ] = shlex .split (event .raw_text )[1 :]
64+ except ValueError :
65+ await event .edit (await event .client .get_string ("logs_err_args" ))
66+ return
67+
68+ if not args :
69+ await event .edit (await event .client .get_string ("help_logs_usage" ), parse_mode = "markdown" )
70+ return
71+
72+ command : str = args [0 ].lower ()
73+
74+ if command == "purge" :
75+ try :
76+ async with event .client .conversation (event .chat_id , timeout = 60 ) as conv :
77+ await conv .send_message (await event .client .get_string ("logs_confirm_purge" ))
78+ response = await conv .get_response ()
79+ if response .text .lower () in ("yes" , "да" ):
80+ async with get_db () as db :
81+ deleted_count = await db_manager .purge_logs (db )
82+ await conv .send_message (await event .client .get_string ("logs_purge_success" , count = deleted_count ))
83+ else :
84+ await conv .send_message (await event .client .get_string ("logs_purge_cancelled" ))
85+ except asyncio .TimeoutError :
86+ await event .respond (await event .client .get_string ("delete_timeout" ))
87+ finally :
88+ await event .delete ()
89+ return
90+
91+ # --- Log Fetching Logic ---
92+ mode : str = "tail"
93+ limit : int = 100
94+ level : Optional [str ] = None
95+ source : Optional [str ] = None
96+
97+ if args and args [0 ].lower () in ["head" , "tail" ]:
98+ mode = args .pop (0 ).lower ()
99+
100+ if args and args [0 ].isdigit ():
101+ limit = int (args .pop (0 ))
102+
103+ for arg in args :
104+ if "=" in arg :
105+ key , value = arg .split ("=" , 1 )
106+ if key .lower () == "level" :
107+ level = value .upper ()
108+ elif key .lower () == "source" :
109+ source = value
110+
111+ async with get_db () as db :
112+ logs_list = await db_manager .get_logs_advanced (db , mode , limit , level , source )
113+
114+ if not logs_list :
115+ await event .edit (await event .client .get_string ("logs_not_found" ))
116+ return
117+
118+ log_content : str = "\n " .join (
119+ f"[{ log .timestamp .strftime ('%Y-%m-%d %H:%M:%S' )} ] [{ log .level } ] [{ log .module_name or 'System' } ] { log .message } "
120+ for log in logs_list
121+ )
122+
123+ log_file = io .BytesIO (log_content .encode ('utf-8' ))
124+ filename = f"debot_logs_{ datetime .now ().strftime ('%Y%m%d_%H%M%S' )} .log"
125+
126+ caption : str = await event .client .get_string (
127+ "logs_caption" ,
128+ mode = mode ,
129+ lines = limit ,
130+ level = level or "ANY" ,
131+ source = source or "ANY" ,
132+ found = len (logs_list )
133+ )
134+
135+ await event .delete ()
136+ await event .client .send_file (
137+ event .chat_id ,
138+ file = log_file ,
139+ caption = caption ,
140+ attributes = [DocumentAttributeFilename (filename )],
141+ parse_mode = "markdown"
142+ )
34143
35144# --- Account Management Handlers ---
36145async def list_accounts_handler (event : events .NewMessage .Event ):
@@ -114,7 +223,8 @@ async def add_account_handler(event: events.NewMessage.Event):
114223 await status_msg .edit (await event .client .get_string ("verifying_creds" ))
115224
116225 async with get_db () as db :
117- if await db_manager .get_account_by_user_id (db , user_id ):
226+ existing = await db_manager .get_account_by_user_id (db , user_id )
227+ if existing :
118228 await status_msg .edit (await event .client .get_string ("err_duplicate_session" , user_id = user_id , existing_name = existing .account_name ))
119229 return
120230
@@ -160,6 +270,58 @@ async def add_account_handler(event: events.NewMessage.Event):
160270 if os .path .exists (session_file_path ):
161271 os .remove (session_file_path )
162272
273+ async def delete_account_handler (event : events .NewMessage .Event ):
274+ account_name = event .pattern_match .group (1 )
275+ try :
276+ async with event .client .conversation (event .chat_id , timeout = 60 ) as conv :
277+ await conv .send_message (await event .client .get_string ("confirm_delete" , account_name = account_name ))
278+ confirmation = await conv .get_response ()
279+ if confirmation .text .lower () in ['да' , 'yes' ]:
280+ async with get_db () as db :
281+ success = await db_manager .delete_account (db , account_name )
282+ if success :
283+ await conv .send_message (await event .client .get_string ("delete_success" , account_name = account_name ))
284+ else :
285+ await conv .send_message (await event .client .get_string ("delete_fail" , account_name = account_name ))
286+ else :
287+ await conv .send_message (await event .client .get_string ("delete_cancelled" ))
288+ except asyncio .TimeoutError :
289+ await event .respond (await event .client .get_string ("delete_timeout" ))
290+
291+ async def toggle_account_handler (event : events .NewMessage .Event ):
292+ account_name = event .pattern_match .group (1 )
293+ async with get_db () as db :
294+ new_status = await db_manager .toggle_account_status (db , account_name )
295+
296+ if new_status is None :
297+ await event .edit (await event .client .get_string ("toggle_not_found" , account_name = account_name ))
298+ elif new_status is True :
299+ await event .edit (await event .client .get_string ("toggle_enabled" , account_name = account_name ))
300+ else :
301+ await event .edit (await event .client .get_string ("toggle_disabled" , account_name = account_name ))
302+
303+ async def set_lang_handler (event : events .NewMessage .Event ):
304+ identifier : str = event .pattern_match .group (1 )
305+ account_id = await get_account_id_from_client (event .client )
306+ if not account_id : return
307+
308+ await event .edit (await event .client .get_string ("lang_downloading" ))
309+
310+ new_lang_code , error = await translator .load_language_pack (identifier )
311+
312+ if error or not new_lang_code :
313+ await event .edit (await event .client .get_string ("lang_download_fail" , error = error ))
314+ return
315+
316+ async with get_db () as db :
317+ success = await db_manager .update_account_lang (db , account_id , new_lang_code )
318+
319+ if success :
320+ event .client .lang_code = new_lang_code
321+ await event .edit (await event .client .get_string ("lang_updated" , lang_code = new_lang_code ))
322+ else :
323+ await event .edit (await event .client .get_string ("lang_update_fail" ))
324+
163325async def help_commands_handler (event : events .NewMessage .Event ):
164326 """Handles the .help command, showing a list or extended help."""
165327 command_to_get : Optional [str ] = event .pattern_match .group (1 )
@@ -170,7 +332,6 @@ async def help_commands_handler(event: events.NewMessage.Event):
170332 if command_to_get :
171333 cmd : str = f".{ command_to_get .strip ().lower ()} "
172334
173- # 1. Search in Core Commands
174335 core_commands_ext : Dict [str , str ] = {
175336 ".ping" : "help_ext_ping" , ".restart" : "help_ext_restart" , ".listaccs" : "help_ext_listaccs" ,
176337 ".addacc" : "help_ext_addacc" , ".delacc" : "help_ext_delacc" , ".toggleacc" : "help_ext_toggleacc" ,
@@ -185,12 +346,10 @@ async def help_commands_handler(event: events.NewMessage.Event):
185346 await event .edit (help_text , parse_mode = "markdown" )
186347 return
187348
188- # 2. Search in Modules
189349 if account_id and account_id in GLOBAL_HELP_INFO :
190350 for mod_info in GLOBAL_HELP_INFO [account_id ].values ():
191351 if mod_info .ext_descriptions :
192352 for i , pattern in enumerate (mod_info .patterns ):
193- # Simple check if the user command starts with the module's command pattern
194353 if cmd .startswith (pattern .split (" " )[0 ]):
195354 await event .edit (mod_info .ext_descriptions [i ], parse_mode = "markdown" )
196355 return
@@ -201,7 +360,6 @@ async def help_commands_handler(event: events.NewMessage.Event):
201360 # --- Main Help Menu Logic ---
202361 categories : Dict [str , List [str ]] = {}
203362
204- # 1. Populate Core Commands
205363 core_commands : List [Tuple [str , str , str ]] = [
206364 ("Управление" , ".listaccs" , "help_listaccs" ), ("Управление" , ".addacc <name>" , "help_addacc" ),
207365 ("Управление" , ".delacc <name>" , "help_delacc" ), ("Управление" , ".toggleacc <name>" , "help_toggleacc" ),
@@ -218,7 +376,6 @@ async def help_commands_handler(event: events.NewMessage.Event):
218376 desc : str = await client .get_string (key )
219377 categories [category ].append (f"`{ pattern } ` - { desc } " )
220378
221- # 2. Populate Module Commands
222379 if account_id and account_id in GLOBAL_HELP_INFO :
223380 for mod_name , mod_info in GLOBAL_HELP_INFO [account_id ].items ():
224381 cat_name : str = mod_info .category .capitalize ()
@@ -228,7 +385,6 @@ async def help_commands_handler(event: events.NewMessage.Event):
228385 desc : str = mod_info .descriptions [i ]
229386 categories [cat_name ].append (f"`{ pattern } ` - { desc } " )
230387
231- # 3. Build Formatted String
232388 final_text_parts : List [str ] = [await client .get_string ("help_header" )]
233389 for i , (category , cmds ) in enumerate (categories .items ()):
234390 final_text_parts .append (f"\n ╭ **{ category } **" )
@@ -238,33 +394,8 @@ async def help_commands_handler(event: events.NewMessage.Event):
238394
239395 await event .edit ("\n " .join (final_text_parts ), parse_mode = "markdown" )
240396
241- # ... (other handlers like about, restart, ping remain mostly the same, just ensure parse_mode="markdown")
242397async def about_command_handler (event : events .NewMessage .Event ):
243398 await event .edit (await event .client .get_string ("about_text" ), parse_mode = "markdown" )
244399
245400async def restart_handler (event : events .NewMessage .Event ):
246- await event .edit (await event .client .get_string ("restarting_now" ), parse_mode = "markdown" )
247- await asyncio .sleep (1 )
248- sys .exit (0 )
249-
250- async def ping_handler (event : events .NewMessage .Event ):
251- start_time : float = time .time ()
252- await event .edit ("Pinging..." )
253-
254- api_start_time : float = time .time ()
255- await event .client (GetStateRequest ())
256- api_end_time : float = time .time ()
257-
258- end_time : float = time .time ()
259-
260- total_latency : float = (end_time - start_time ) * 1000
261- api_latency : float = (api_end_time - api_start_time ) * 1000
262- user_server_latency : float = total_latency - api_latency
263-
264- response_text = await event .client .get_string (
265- "ping_response" ,
266- user_server = f"{ user_server_latency :.2f} " ,
267- server_api = f"{ api_latency :.2f} " ,
268- total = f"{ total_latency :.2f} "
269- )
270- await event .edit (response_text , parse_mode = "markdown" )
401+ await event .edit (await event .client .get_string ("restarting_now" ), pa
0 commit comments