11import asyncio
22import gc
33import logging
4- import subprocess
54import sys
6- from typing import Dict , Any , Optional , List , Set
5+ from typing import Dict , Any
76
87from apscheduler .schedulers .asyncio import AsyncIOScheduler
98from rich .console import Console
10- from telethon import events , helpers
9+ from telethon import events
1110from telethon .errors import SessionPasswordNeededError
1211from telethon .sessions import StringSession
1312from art import text2art
1413
15- from userbot import ACTIVE_CLIENTS , LOOP , GLOBAL_HELP_INFO , FAKE , TelegramClient
14+ from userbot import (
15+ ACTIVE_CLIENTS , FAKE , TelegramClient ,
16+ db_setup , manage_clients , GLOBAL_HELP_INFO
17+ )
1618from userbot .src .config import GC_INTERVAL_SECONDS
1719from userbot .src .db .session import get_db
1820import userbot .src .db_manager as db_manager
19- from userbot .src .module_parser import parse_module_metadata
2021
2122console : Console = Console ()
2223logger : logging .Logger = logging .getLogger (__name__ )
2324
2425# --- Helper Functions ---
2526async def get_account_id_from_client (client ) -> int | None :
26- """Gets the account_id associated with a client instance."""
2727 return next ((acc_id for acc_id , c in ACTIVE_CLIENTS .items () if c == client ), None )
2828
2929# --- Module Management (Placeholders) ---
3030async def load_account_modules (account_id : int , client_instance , current_help_info : Dict [str , str ]) -> None :
31- """Loads all active and trusted modules for a given account."""
3231 console .print (f"[MODULES] - Loading modules for account_id: { account_id } ..." , style = "yellow" )
33- # In a real scenario, this would populate current_help_info based on loaded modules
3432 pass
3533
36- async def delmod_handler (event : events .NewMessage .Event ):
37- """Handles unlinking a module and safely uninstalling its dependencies."""
38- await event .edit ("Команда `.delmod` в разработке." )
39-
4034# --- Account Management Handlers ---
4135async def list_accounts_handler (event : events .NewMessage .Event ):
42- """Lists all accounts in the database with their status."""
4336 await event .edit (await event .client .get_string ("verifying_creds" ))
4437 header = await event .client .get_string ("account_list_header" )
4538 response_lines = [header ]
@@ -66,7 +59,6 @@ async def list_accounts_handler(event: events.NewMessage.Event):
6659 await event .edit ("\n " .join (response_lines ), parse_mode = "html" )
6760
6861async def add_account_handler (event : events .NewMessage .Event ):
69- """Interactively adds a new account session."""
7062 account_name = event .pattern_match .group (1 )
7163
7264 try :
@@ -82,11 +74,10 @@ async def add_account_handler(event: events.NewMessage.Event):
8274 try :
8375 await temp_client .connect ()
8476 if not await temp_client .is_user_authorized ():
85- # This part is highly simplified. A real sign-in flow is more complex.
86- phone_number = await temp_client .send_code_request (api_id )
77+ phone = await temp_client .send_code_request (api_id )
8778 await conv .send_message (f"Код отправлен. Введите его:" )
8879 code = (await conv .get_response ()).text .strip ()
89- await temp_client .sign_in (password = code )
80+ await temp_client .sign_in (phone = phone . phone , code = code )
9081 except SessionPasswordNeededError :
9182 await conv .send_message (await event .client .get_string ("prompt_2fa" ))
9283 two_fa_pass_resp = await conv .get_response (); two_fa_pass = two_fa_pass_resp .text .strip ()
@@ -102,7 +93,7 @@ async def add_account_handler(event: events.NewMessage.Event):
10293 return
10394
10495 await conv .send_message (await event .client .get_string ("prompt_lang" )); lang_code = (await conv .get_response ()).text .strip () or 'ru'
105- await conv .send_message (await event .client .get_string ("prompt_activate" )); is_enabled = (await conv .get_response ()).text .lower ().startswith ('д' )
96+ await conv .send_message (await event .client .get_string ("prompt_activate" )); is_enabled = (await conv .get_response ()).text .lower ().startswith (( 'y' , 'д' ) )
10697
10798 device_model , system_version , app_version = FAKE .android_platform_token (), "SDK 31" , "10.1.0"
10899
@@ -125,7 +116,6 @@ async def add_account_handler(event: events.NewMessage.Event):
125116 await event .respond (await event .client .get_string ("generic_error" , error = str (e )))
126117
127118async def delete_account_handler (event : events .NewMessage .Event ):
128- """Deletes an account from the database."""
129119 account_name = event .pattern_match .group (1 )
130120 try :
131121 async with event .client .conversation (event .chat_id , timeout = 60 ) as conv :
@@ -143,9 +133,7 @@ async def delete_account_handler(event: events.NewMessage.Event):
143133 except asyncio .TimeoutError :
144134 await event .respond (await event .client .get_string ("delete_timeout" ))
145135
146-
147136async def toggle_account_handler (event : events .NewMessage .Event ):
148- """Enables or disables an account."""
149137 account_name = event .pattern_match .group (1 )
150138 async with get_db () as db :
151139 new_status = await db_manager .toggle_account_status (db , account_name )
@@ -158,7 +146,6 @@ async def toggle_account_handler(event: events.NewMessage.Event):
158146 await event .edit (await event .client .get_string ("toggle_disabled" , account_name = account_name ))
159147
160148async def set_lang_handler (event : events .NewMessage .Event ):
161- """Sets the language for the current account."""
162149 lang_code = event .pattern_match .group (1 ).lower ()
163150 account_id = await get_account_id_from_client (event .client )
164151 if not account_id : return
@@ -173,7 +160,6 @@ async def set_lang_handler(event: events.NewMessage.Event):
173160 await event .edit (await event .client .get_string ("lang_update_fail" ))
174161
175162async def help_commands_handler (event : events .NewMessage .Event ):
176- """Displays the help message."""
177163 help_management = "\n " .join ([
178164 f"<code>.listaccs</code> - { await event .client .get_string ('help_listaccs' )} " ,
179165 f"<code>.addacc <name></code> - { await event .client .get_string ('help_addacc' )} " ,
@@ -182,28 +168,35 @@ async def help_commands_handler(event: events.NewMessage.Event):
182168 f"<code>.setlang <code></code> - { await event .client .get_string ('help_setlang' )} " ,
183169 f"<code>.about</code> - { await event .client .get_string ('help_about' )} " ,
184170 ])
185-
186171 final_text = f"{ await event .client .get_string ('help_header_management' )} \n { help_management } "
187172 await event .edit (final_text , parse_mode = "HTML" )
188173
189174async def about_command_handler (event : events .NewMessage .Event ):
190- """Displays information about the userbot."""
191175 await event .edit (await event .client .get_string ("about_text" ), parse_mode = "HTML" )
192176
193- # --- Main Execution ---
194- if __name__ == "__main__" :
177+ async def main ():
178+ """The main entry point for the userbot."""
195179 console .print (text2art ("DeBot" , font = "random" , chr_ignore = True ), style = "cyan" )
196180 console .print ("\n coded by @whynothacked" , style = "yellow" )
197181
182+ await db_setup ()
183+ await manage_clients ()
184+
198185 scheduler = AsyncIOScheduler (timezone = "UTC" )
199186 scheduler .add_job (gc .collect , 'interval' , seconds = GC_INTERVAL_SECONDS , id = 'gc_job' )
200187 scheduler .start ()
201188 console .print (f"-> [system] - GC scheduled every { GC_INTERVAL_SECONDS } seconds." , style = "blue" )
202-
189+
190+ logger .info ("Userbot is running. Press Ctrl+C to stop." )
191+ # Keep the main coroutine alive indefinitely
192+ await asyncio .Event ().wait ()
193+
194+
195+ if __name__ == "__main__" :
203196 try :
204- LOOP . run_forever ( )
197+ asyncio . run ( main () )
205198 except KeyboardInterrupt :
206199 console .print ("\n [MAIN] - Userbot stopped by user." , style = "bold yellow" )
207- finally :
208- if scheduler . running : scheduler . shutdown ( )
209- console . print ( "[MAIN] - Userbot shutdown complete." , style = "bold green" )
200+ except Exception as e :
201+ logger . critical ( f"An unhandled error occurred in main: { e } " , exc_info = True )
202+ sys . exit ( 1 )
0 commit comments