dtcn / Detection /multi_start.py
randydev's picture
Create multi_start.py
499c1b4 verified
import logging
import asyncio
import pyromod
from Detection import assistant
from database import db
from config import API_ID, API_HASH
from pyrogram import Client
from pyrogram.errors import (
UserDeactivatedBan,
AuthKeyDuplicated,
AuthKeyInvalid,
UserDeactivated,
AuthKeyUnregistered,
SessionRevoked
)
LOGS = logging.getLogger(__name__)
async def start_user() -> None:
try:
sessions = await db.users_detection.find({
"user_client": {
"$elemMatch": {
"is_active": True,
"status": "approved"
}
}
}).to_list(length=None)
if not sessions:
LOGS.warning("No approved and active user sessions found.")
return
active_clients = []
for i, session_data in enumerate(sessions, 1):
user_client = session_data.get("user_client", [])
for user in user_client:
if not (user.get("status") == "approved" and user.get("is_active")):
continue
session_str = user.get("session_string")
user_id = user.get("user_id")
api_id = user.get("api_id", API_ID)
api_hash = user.get("api_hash", API_HASH)
if not (session_str and user_id):
continue
try:
client = Client(
name=f"Detection_{i}_{user_id}",
api_id=api_id,
api_hash=api_hash,
session_string=session_str,
plugins=dict(root="Detection.UserBot"),
app_version="Detection/latest",
device_model="Anonymous",
system_version="Linux/Kernel-6.5",
sleep_threshold=60
)
await client.start()
me = await client.get_me()
if me.id != user_id:
raise ValueError(f"Session user_id mismatch (expected {user_id}, got {me.id})")
LOGS.info(f"βœ… Started User #{i}: Name: {me.first_name}")
active_clients.append(client)
asyncio.create_task(
_check_session_health(client, user_id),
name=f"health_monitor_{user_id}"
)
except (
UserDeactivatedBan,
AuthKeyDuplicated,
UserDeactivated,
AuthKeyUnregistered,
SessionRevoked
) as e:
await _handle_dead_session(user_id, e)
continue
except Exception as e:
LOGS.error(f"⚠️ User #{i} failed: {type(e).__name__}: {str(e)}")
continue
except Exception as err:
LOGS.error(f"start_user() crashed: {type(err).__name__}: {err}")
async def _handle_dead_session(user_id: int, error: Exception) -> None:
request = await db.users_detection.find_one({"user_id": user_id})
if not request:
return
for user in request["user_client"]:
if user.get("user_id") == user_id:
await db.users_detection.update_one(
{
"_id": request["_id"],
"user_client.user_id": user_id
},
{
"$set": {
"user_client.$.is_active": False,
"user_client.$.status": "stopped"
},
"$unset": {
"user_client.$.session_string": None
}
}
)
break
await _send_message_warning(
user_id,
f"🚨 Session terminated\n"
f"User: {user_id}\n"
f"Reason: Error: {type(error).__name__}"
)
LOGS.warning(
f"🚨 Session terminated\n"
f"User: {user_id}\n"
f"Reason: {type(error).__name__}"
)
async def check_connection(client: Client) -> bool:
try:
return await client.get_me() is not None
except:
return False
async def connection_watchdog(client: Client):
while True:
if not await check_connection(client):
LOGS.warning("Reconnecting...")
await client.disconnect()
await client.connect()
await asyncio.sleep(300)
async def _send_message_warning(user_id, text):
try:
await assistant.send_message(user_id, text)
except:
pass
async def _check_session_health(client: Client, user_id: int, interval: int = 300) -> None:
while True:
try:
await asyncio.wait_for(client.get_me(), timeout=10)
if not client.is_connected:
raise ConnectionError("Client disconnected")
LOGS.debug(f"Session health OK: User {user_id}")
await asyncio.sleep(interval)
except (UserDeactivated, AuthKeyInvalid) as e:
LOGS.warning(f"πŸ’€ Session dead for {user_id}: {type(e).__name__}")
await _handle_dead_session(user_id, e)
break
except Exception as e:
LOGS.error(f"Health check failed for {user_id}: {type(e).__name__}: {str(e)}")
await asyncio.sleep(60)