File size: 5,487 Bytes
499c1b4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
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) |