Create multi_start.py
Browse files- Detection/multi_start.py +164 -0
Detection/multi_start.py
ADDED
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import logging
|
2 |
+
import asyncio
|
3 |
+
import pyromod
|
4 |
+
from Detection import assistant
|
5 |
+
from database import db
|
6 |
+
from config import API_ID, API_HASH
|
7 |
+
from pyrogram import Client
|
8 |
+
|
9 |
+
from pyrogram.errors import (
|
10 |
+
UserDeactivatedBan,
|
11 |
+
AuthKeyDuplicated,
|
12 |
+
AuthKeyInvalid,
|
13 |
+
UserDeactivated,
|
14 |
+
AuthKeyUnregistered,
|
15 |
+
SessionRevoked
|
16 |
+
)
|
17 |
+
LOGS = logging.getLogger(__name__)
|
18 |
+
|
19 |
+
async def start_user() -> None:
|
20 |
+
try:
|
21 |
+
sessions = await db.users_detection.find({
|
22 |
+
"user_client": {
|
23 |
+
"$elemMatch": {
|
24 |
+
"is_active": True,
|
25 |
+
"status": "approved"
|
26 |
+
}
|
27 |
+
}
|
28 |
+
}).to_list(length=None)
|
29 |
+
|
30 |
+
if not sessions:
|
31 |
+
LOGS.warning("No approved and active user sessions found.")
|
32 |
+
return
|
33 |
+
|
34 |
+
active_clients = []
|
35 |
+
|
36 |
+
for i, session_data in enumerate(sessions, 1):
|
37 |
+
user_client = session_data.get("user_client", [])
|
38 |
+
for user in user_client:
|
39 |
+
if not (user.get("status") == "approved" and user.get("is_active")):
|
40 |
+
continue
|
41 |
+
|
42 |
+
session_str = user.get("session_string")
|
43 |
+
user_id = user.get("user_id")
|
44 |
+
api_id = user.get("api_id", API_ID)
|
45 |
+
api_hash = user.get("api_hash", API_HASH)
|
46 |
+
|
47 |
+
if not (session_str and user_id):
|
48 |
+
continue
|
49 |
+
|
50 |
+
try:
|
51 |
+
client = Client(
|
52 |
+
name=f"Detection_{i}_{user_id}",
|
53 |
+
api_id=api_id,
|
54 |
+
api_hash=api_hash,
|
55 |
+
session_string=session_str,
|
56 |
+
plugins=dict(root="Detection.UserBot"),
|
57 |
+
app_version="Detection/latest",
|
58 |
+
device_model="Anonymous",
|
59 |
+
system_version="Linux/Kernel-6.5",
|
60 |
+
sleep_threshold=60
|
61 |
+
)
|
62 |
+
await client.start()
|
63 |
+
me = await client.get_me()
|
64 |
+
if me.id != user_id:
|
65 |
+
raise ValueError(f"Session user_id mismatch (expected {user_id}, got {me.id})")
|
66 |
+
|
67 |
+
LOGS.info(f"β
Started User #{i}: Name: {me.first_name}")
|
68 |
+
active_clients.append(client)
|
69 |
+
|
70 |
+
asyncio.create_task(
|
71 |
+
_check_session_health(client, user_id),
|
72 |
+
name=f"health_monitor_{user_id}"
|
73 |
+
)
|
74 |
+
|
75 |
+
except (
|
76 |
+
UserDeactivatedBan,
|
77 |
+
AuthKeyDuplicated,
|
78 |
+
UserDeactivated,
|
79 |
+
AuthKeyUnregistered,
|
80 |
+
SessionRevoked
|
81 |
+
) as e:
|
82 |
+
await _handle_dead_session(user_id, e)
|
83 |
+
continue
|
84 |
+
|
85 |
+
except Exception as e:
|
86 |
+
LOGS.error(f"β οΈ User #{i} failed: {type(e).__name__}: {str(e)}")
|
87 |
+
continue
|
88 |
+
|
89 |
+
except Exception as err:
|
90 |
+
LOGS.error(f"start_user() crashed: {type(err).__name__}: {err}")
|
91 |
+
|
92 |
+
async def _handle_dead_session(user_id: int, error: Exception) -> None:
|
93 |
+
request = await db.users_detection.find_one({"user_id": user_id})
|
94 |
+
if not request:
|
95 |
+
return
|
96 |
+
|
97 |
+
for user in request["user_client"]:
|
98 |
+
if user.get("user_id") == user_id:
|
99 |
+
await db.users_detection.update_one(
|
100 |
+
{
|
101 |
+
"_id": request["_id"],
|
102 |
+
"user_client.user_id": user_id
|
103 |
+
},
|
104 |
+
{
|
105 |
+
"$set": {
|
106 |
+
"user_client.$.is_active": False,
|
107 |
+
"user_client.$.status": "stopped"
|
108 |
+
},
|
109 |
+
"$unset": {
|
110 |
+
"user_client.$.session_string": None
|
111 |
+
}
|
112 |
+
}
|
113 |
+
)
|
114 |
+
break
|
115 |
+
await _send_message_warning(
|
116 |
+
user_id,
|
117 |
+
f"π¨ Session terminated\n"
|
118 |
+
f"User: {user_id}\n"
|
119 |
+
f"Reason: Error: {type(error).__name__}"
|
120 |
+
)
|
121 |
+
LOGS.warning(
|
122 |
+
f"π¨ Session terminated\n"
|
123 |
+
f"User: {user_id}\n"
|
124 |
+
f"Reason: {type(error).__name__}"
|
125 |
+
)
|
126 |
+
|
127 |
+
async def check_connection(client: Client) -> bool:
|
128 |
+
try:
|
129 |
+
return await client.get_me() is not None
|
130 |
+
except:
|
131 |
+
return False
|
132 |
+
|
133 |
+
async def connection_watchdog(client: Client):
|
134 |
+
while True:
|
135 |
+
if not await check_connection(client):
|
136 |
+
LOGS.warning("Reconnecting...")
|
137 |
+
await client.disconnect()
|
138 |
+
await client.connect()
|
139 |
+
await asyncio.sleep(300)
|
140 |
+
|
141 |
+
async def _send_message_warning(user_id, text):
|
142 |
+
try:
|
143 |
+
await assistant.send_message(user_id, text)
|
144 |
+
except:
|
145 |
+
pass
|
146 |
+
|
147 |
+
async def _check_session_health(client: Client, user_id: int, interval: int = 300) -> None:
|
148 |
+
while True:
|
149 |
+
try:
|
150 |
+
await asyncio.wait_for(client.get_me(), timeout=10)
|
151 |
+
|
152 |
+
if not client.is_connected:
|
153 |
+
raise ConnectionError("Client disconnected")
|
154 |
+
|
155 |
+
LOGS.debug(f"Session health OK: User {user_id}")
|
156 |
+
await asyncio.sleep(interval)
|
157 |
+
|
158 |
+
except (UserDeactivated, AuthKeyInvalid) as e:
|
159 |
+
LOGS.warning(f"π Session dead for {user_id}: {type(e).__name__}")
|
160 |
+
await _handle_dead_session(user_id, e)
|
161 |
+
break
|
162 |
+
except Exception as e:
|
163 |
+
LOGS.error(f"Health check failed for {user_id}: {type(e).__name__}: {str(e)}")
|
164 |
+
await asyncio.sleep(60)
|