CliRemote 1.4.4__tar.gz → 1.4.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cliremote-1.4.4 → cliremote-1.4.6}/CliRemote.egg-info/PKG-INFO +1 -1
- {cliremote-1.4.4 → cliremote-1.4.6}/PKG-INFO +1 -1
- {cliremote-1.4.4 → cliremote-1.4.6}/pyproject.toml +1 -1
- cliremote-1.4.6/remote/account_manager.py +246 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/device_manager.py +3 -2
- {cliremote-1.4.4 → cliremote-1.4.6}/setup.py +1 -1
- cliremote-1.4.4/remote/account_manager.py +0 -160
- {cliremote-1.4.4 → cliremote-1.4.6}/CliRemote.egg-info/SOURCES.txt +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/CliRemote.egg-info/dependency_links.txt +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/CliRemote.egg-info/requires.txt +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/CliRemote.egg-info/top_level.txt +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/LICENSE +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/MANIFEST.in +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/README.md +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/__init__.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/account_viewer.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/admin_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/analytics_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/batch_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/block_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/caption_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/cleaner.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/client_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/client_picker.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/config.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/file_sender.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/getcode_controller.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/health.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/help_menu.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/init.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/join_controller.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/joiner.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/leave_controller.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/lefter.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/mention_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/precise_engine.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/profile_info.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/profile_media.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/profile_privacy.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/spammer.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/speed_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/stop_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/text_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/remote/username_manager.py +0 -0
- {cliremote-1.4.4 → cliremote-1.4.6}/setup.cfg +0 -0
@@ -0,0 +1,246 @@
|
|
1
|
+
import os
|
2
|
+
import json
|
3
|
+
import asyncio
|
4
|
+
import logging
|
5
|
+
import random
|
6
|
+
import traceback
|
7
|
+
from typing import Optional, Dict, List, Set, Tuple
|
8
|
+
from pyrogram import Client, errors
|
9
|
+
|
10
|
+
# ============================================================
|
11
|
+
# ⚙️ تنظیم لاگ دقیق برای دیباگ Pyrogram و SQLite
|
12
|
+
# ============================================================
|
13
|
+
os.makedirs("logs", exist_ok=True)
|
14
|
+
log_file = "logs/client_debug_log.txt"
|
15
|
+
logger = logging.getLogger(__name__)
|
16
|
+
logger.setLevel(logging.DEBUG)
|
17
|
+
|
18
|
+
if not any(isinstance(h, logging.FileHandler) and h.baseFilename.endswith(log_file) for h in logger.handlers):
|
19
|
+
fh = logging.FileHandler(log_file, encoding="utf-8")
|
20
|
+
fmt = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s", "%Y-%m-%d %H:%M:%S")
|
21
|
+
fh.setFormatter(fmt)
|
22
|
+
logger.addHandler(fh)
|
23
|
+
|
24
|
+
logger.info("🧩 Client Manager started in DEBUG MODE.")
|
25
|
+
|
26
|
+
# ============================================================
|
27
|
+
# 🧱 ساختار دادهها
|
28
|
+
# ============================================================
|
29
|
+
client_pool: Dict[str, Client] = {}
|
30
|
+
client_locks: Dict[str, asyncio.Lock] = {}
|
31
|
+
|
32
|
+
ACCOUNTS_FOLDER = "acc"
|
33
|
+
ACCOUNTS_DATA_FOLDER = "acc_data"
|
34
|
+
os.makedirs(ACCOUNTS_FOLDER, exist_ok=True)
|
35
|
+
os.makedirs(ACCOUNTS_DATA_FOLDER, exist_ok=True)
|
36
|
+
|
37
|
+
|
38
|
+
# ============================================================
|
39
|
+
# 🧠 ساخت یا دریافت کلاینت
|
40
|
+
# ============================================================
|
41
|
+
async def get_or_start_client(phone_number: str) -> Optional[Client]:
|
42
|
+
cli = client_pool.get(phone_number)
|
43
|
+
try:
|
44
|
+
if cli is not None and getattr(cli, "is_connected", False):
|
45
|
+
logger.debug(f"{phone_number}: Already connected → {cli.session_name}")
|
46
|
+
return cli
|
47
|
+
|
48
|
+
cli = _make_client_from_json(phone_number)
|
49
|
+
if cli is None:
|
50
|
+
logger.error(f"{phone_number}: ❌ Could not build client (no JSON or invalid data)")
|
51
|
+
return None
|
52
|
+
|
53
|
+
session_db_path = f"{cli.session_name}.session"
|
54
|
+
logger.debug(f"{phone_number}: Session DB path → {session_db_path}")
|
55
|
+
|
56
|
+
if not os.path.exists(session_db_path):
|
57
|
+
logger.warning(f"{phone_number}: Session file not found → {session_db_path}")
|
58
|
+
else:
|
59
|
+
size = os.path.getsize(session_db_path)
|
60
|
+
logger.debug(f"{phone_number}: Session file exists ({size} bytes)")
|
61
|
+
if not os.access(session_db_path, os.R_OK | os.W_OK):
|
62
|
+
logger.warning(f"{phone_number}: ⚠️ No read/write permission for {session_db_path}")
|
63
|
+
|
64
|
+
try:
|
65
|
+
await cli.start()
|
66
|
+
await asyncio.sleep(0.4)
|
67
|
+
logger.info(f"{phone_number}: ✅ Client started successfully.")
|
68
|
+
except errors.SessionPasswordNeeded:
|
69
|
+
twofa = getattr(cli, "_twofa_password", None)
|
70
|
+
if twofa:
|
71
|
+
await cli.check_password(twofa)
|
72
|
+
logger.info(f"{phone_number}: ✅ 2FA password applied.")
|
73
|
+
else:
|
74
|
+
logger.error(f"{phone_number}: ⚠️ 2FA required but missing.")
|
75
|
+
return None
|
76
|
+
except errors.AuthKeyDuplicated:
|
77
|
+
logger.error(f"{phone_number}: ❌ AuthKeyDuplicated (session invalid).")
|
78
|
+
return None
|
79
|
+
except Exception as e:
|
80
|
+
tb = traceback.format_exc(limit=3)
|
81
|
+
logger.error(f"{phone_number}: ❌ Start failed - {type(e).__name__}: {e}\n{tb}")
|
82
|
+
return None
|
83
|
+
|
84
|
+
client_pool[phone_number] = cli
|
85
|
+
client_locks.setdefault(phone_number, asyncio.Lock())
|
86
|
+
return cli
|
87
|
+
|
88
|
+
except Exception as e:
|
89
|
+
tb = traceback.format_exc(limit=3)
|
90
|
+
logger.critical(f"{phone_number}: 💥 Fatal error in get_or_start_client - {type(e).__name__}: {e}\n{tb}")
|
91
|
+
return None
|
92
|
+
|
93
|
+
|
94
|
+
# ============================================================
|
95
|
+
# 🧩 ساخت کلاینت از JSON
|
96
|
+
# ============================================================
|
97
|
+
def _make_client_from_json(phone_number: str) -> Optional[Client]:
|
98
|
+
try:
|
99
|
+
data_path = os.path.join(ACCOUNTS_DATA_FOLDER, f"{phone_number}.json")
|
100
|
+
if not os.path.exists(data_path):
|
101
|
+
logger.error(f"{phone_number}: ⚠️ Account JSON not found → {data_path}")
|
102
|
+
return None
|
103
|
+
|
104
|
+
with open(data_path, "r", encoding="utf-8") as f:
|
105
|
+
account_data = json.load(f)
|
106
|
+
|
107
|
+
session_base = account_data.get("session")
|
108
|
+
if not session_base:
|
109
|
+
logger.error(f"{phone_number}: Missing 'session' key in JSON → {data_path}")
|
110
|
+
return None
|
111
|
+
|
112
|
+
session_path = os.path.join(ACCOUNTS_FOLDER, session_base)
|
113
|
+
if not session_path.endswith(".session"):
|
114
|
+
session_path += ".session"
|
115
|
+
|
116
|
+
os.makedirs(os.path.dirname(session_path), exist_ok=True)
|
117
|
+
|
118
|
+
logger.debug(f"{phone_number}: Final session path → {session_path}")
|
119
|
+
|
120
|
+
api_id = account_data.get("api_id")
|
121
|
+
api_hash = account_data.get("api_hash")
|
122
|
+
if not api_id or not api_hash:
|
123
|
+
logger.error(f"{phone_number}: Missing API credentials in JSON → {data_path}")
|
124
|
+
return None
|
125
|
+
|
126
|
+
cli = Client(
|
127
|
+
name=session_path,
|
128
|
+
api_id=int(api_id),
|
129
|
+
api_hash=str(api_hash),
|
130
|
+
sleep_threshold=30,
|
131
|
+
workdir=os.path.join("acc_temp", phone_number),
|
132
|
+
no_updates=True,
|
133
|
+
)
|
134
|
+
|
135
|
+
if account_data.get("2fa_password"):
|
136
|
+
setattr(cli, "_twofa_password", account_data["2fa_password"])
|
137
|
+
|
138
|
+
return cli
|
139
|
+
|
140
|
+
except Exception as e:
|
141
|
+
tb = traceback.format_exc(limit=3)
|
142
|
+
logger.critical(f"{phone_number}: 💥 Error creating client - {type(e).__name__}: {e}\n{tb}")
|
143
|
+
return None
|
144
|
+
|
145
|
+
|
146
|
+
# ============================================================
|
147
|
+
# 🚀 Preload با لاگ کامل
|
148
|
+
# ============================================================
|
149
|
+
async def preload_clients(limit: Optional[int] = None) -> None:
|
150
|
+
phones = list(get_active_accounts())
|
151
|
+
if limit is not None:
|
152
|
+
phones = phones[:max(0, int(limit))]
|
153
|
+
|
154
|
+
if not phones:
|
155
|
+
logger.info("⚙️ No accounts found for preload.")
|
156
|
+
return
|
157
|
+
|
158
|
+
logger.info(f"🚀 Preloading {len(phones)} clients...")
|
159
|
+
ok, bad = 0, 0
|
160
|
+
|
161
|
+
for idx, phone in enumerate(phones, 1):
|
162
|
+
logger.info(f"🔹 [{idx}/{len(phones)}] Loading client {phone}")
|
163
|
+
try:
|
164
|
+
cli = await get_or_start_client(phone)
|
165
|
+
if cli and getattr(cli, "is_connected", False):
|
166
|
+
ok += 1
|
167
|
+
logger.info(f"{phone}: ✅ Connected.")
|
168
|
+
else:
|
169
|
+
bad += 1
|
170
|
+
logger.warning(f"{phone}: ❌ Not connected after start().")
|
171
|
+
except Exception as e:
|
172
|
+
bad += 1
|
173
|
+
tb = traceback.format_exc(limit=3)
|
174
|
+
logger.error(f"{phone}: ❌ Exception during preload - {type(e).__name__}: {e}\n{tb}")
|
175
|
+
|
176
|
+
await asyncio.sleep(1.0)
|
177
|
+
|
178
|
+
logger.info(f"🎯 Preload completed: OK={ok} | FAIL={bad}")
|
179
|
+
|
180
|
+
|
181
|
+
# ============================================================
|
182
|
+
# 🧹 توقف تمام کلاینتها
|
183
|
+
# ============================================================
|
184
|
+
async def stop_all_clients() -> None:
|
185
|
+
logger.info("🧹 Stopping all clients...")
|
186
|
+
for phone, cli in list(client_pool.items()):
|
187
|
+
try:
|
188
|
+
await cli.stop()
|
189
|
+
logger.info(f"{phone}: 📴 Stopped successfully.")
|
190
|
+
except Exception as e:
|
191
|
+
tb = traceback.format_exc(limit=2)
|
192
|
+
logger.warning(f"{phone}: ⚠️ Error stopping client - {type(e).__name__}: {e}\n{tb}")
|
193
|
+
finally:
|
194
|
+
client_pool.pop(phone, None)
|
195
|
+
await asyncio.sleep(0.3)
|
196
|
+
logger.info("✅ All clients stopped cleanly.")
|
197
|
+
|
198
|
+
|
199
|
+
# ============================================================
|
200
|
+
# 📦 مدیریت JSON دادههای اکانت
|
201
|
+
# ============================================================
|
202
|
+
def get_account_data(phone_number: str) -> Optional[Dict]:
|
203
|
+
"""
|
204
|
+
خواندن دادههای JSON اکانت از acc_data/{phone}.json
|
205
|
+
"""
|
206
|
+
file_path = os.path.join(ACCOUNTS_DATA_FOLDER, f"{phone_number}.json")
|
207
|
+
if not os.path.exists(file_path):
|
208
|
+
logger.warning(f"{phone_number}: ⚠️ Account JSON not found at {file_path}")
|
209
|
+
return None
|
210
|
+
try:
|
211
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
212
|
+
return json.load(f)
|
213
|
+
except Exception as e:
|
214
|
+
logger.error(f"{phone_number}: ⚠️ Error reading JSON - {type(e).__name__}: {e}")
|
215
|
+
return None
|
216
|
+
|
217
|
+
|
218
|
+
def save_account_data(phone_number: str, data: Dict) -> None:
|
219
|
+
"""
|
220
|
+
ذخیره اطلاعات JSON اکانت در acc_data/{phone}.json
|
221
|
+
"""
|
222
|
+
os.makedirs(ACCOUNTS_DATA_FOLDER, exist_ok=True)
|
223
|
+
file_path = os.path.join(ACCOUNTS_DATA_FOLDER, f"{phone_number}.json")
|
224
|
+
try:
|
225
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
226
|
+
json.dump(data, f, ensure_ascii=False, indent=4)
|
227
|
+
logger.info(f"{phone_number}: 💾 Account data saved successfully → {file_path}")
|
228
|
+
except Exception as e:
|
229
|
+
logger.error(f"{phone_number}: ⚠️ Error saving JSON - {type(e).__name__}: {e}")
|
230
|
+
|
231
|
+
|
232
|
+
# ============================================================
|
233
|
+
# 📋 لیست اکانتهای فعال
|
234
|
+
# ============================================================
|
235
|
+
def accounts() -> List[str]:
|
236
|
+
accs: Set[str] = set()
|
237
|
+
if not os.path.isdir(ACCOUNTS_FOLDER):
|
238
|
+
return []
|
239
|
+
for acc in os.listdir(ACCOUNTS_FOLDER):
|
240
|
+
if acc.endswith(".session"):
|
241
|
+
accs.add(acc.split(".")[0])
|
242
|
+
return list(accs)
|
243
|
+
|
244
|
+
|
245
|
+
def get_active_accounts() -> Set[str]:
|
246
|
+
return set(accounts())
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# antispam_core/device_manager.py (updated safe version)
|
2
2
|
import asyncio, logging
|
3
3
|
from pyrogram import Client, errors, raw
|
4
|
-
from .client_manager import get_or_start_client,
|
5
|
-
from . import
|
4
|
+
from .client_manager import get_or_start_client, accounts
|
5
|
+
from .account_manager import get_account_data
|
6
|
+
|
6
7
|
|
7
8
|
logger = logging.getLogger(__name__)
|
8
9
|
|
@@ -5,7 +5,7 @@ with open("README.md", encoding="utf-8") as f:
|
|
5
5
|
|
6
6
|
setup(
|
7
7
|
name="CliRemote",
|
8
|
-
version="1.4.
|
8
|
+
version="1.4.6",
|
9
9
|
author="MrAhmadiRad",
|
10
10
|
author_email="mohammadahmadirad69@gmail.com",
|
11
11
|
description="A precise, async-safe, Telegram automation core (Python 3.8+)",
|
@@ -1,160 +0,0 @@
|
|
1
|
-
# antispam_core/account_manager.py
|
2
|
-
import os, asyncio, json, logging
|
3
|
-
from typing import Optional, Dict, List
|
4
|
-
from pyrogram import Client, errors
|
5
|
-
from .client_manager import (
|
6
|
-
ACCOUNTS_FOLDER,
|
7
|
-
save_account_data,
|
8
|
-
stop_all_clients,
|
9
|
-
accounts,
|
10
|
-
client_pool,
|
11
|
-
client_locks
|
12
|
-
)
|
13
|
-
|
14
|
-
logger = logging.getLogger(__name__)
|
15
|
-
login = {}
|
16
|
-
|
17
|
-
# ==========================
|
18
|
-
# افزودن اکانت جدید
|
19
|
-
# ==========================
|
20
|
-
async def add_account_cmd(message, get_app_info):
|
21
|
-
try:
|
22
|
-
parts = message.text.split(' ', 1)
|
23
|
-
if len(parts) < 2:
|
24
|
-
await message.reply('مثال: `add +989123456789`')
|
25
|
-
return
|
26
|
-
|
27
|
-
phone_number = parts[1].strip()
|
28
|
-
session_file = os.path.join(ACCOUNTS_FOLDER, f'{phone_number}.session')
|
29
|
-
|
30
|
-
if os.path.exists(session_file):
|
31
|
-
await message.reply('این اکانت وجود دارد!')
|
32
|
-
return
|
33
|
-
|
34
|
-
global login
|
35
|
-
api = get_app_info()
|
36
|
-
if not api or len(api) < 2:
|
37
|
-
await message.reply('مشکل در API!')
|
38
|
-
return
|
39
|
-
|
40
|
-
login['id'] = int(api[1])
|
41
|
-
login['hash'] = api[0]
|
42
|
-
login['number'] = phone_number
|
43
|
-
login['api_data'] = {
|
44
|
-
'api_id': api[1],
|
45
|
-
'api_hash': api[0],
|
46
|
-
'phone_number': phone_number,
|
47
|
-
'session': phone_number,
|
48
|
-
'2fa_password': None
|
49
|
-
}
|
50
|
-
|
51
|
-
try:
|
52
|
-
login['client'] = Client(name=session_file.replace('.session', ''), api_id=login['id'], api_hash=login['hash'])
|
53
|
-
await login['client'].connect()
|
54
|
-
login['response'] = await login['client'].send_code(phone_number)
|
55
|
-
await message.reply(f'✅ کد تأیید به {phone_number} ارسال شد.\n`code 12345`')
|
56
|
-
except errors.BadRequest as e:
|
57
|
-
await message.reply(f'Bad request: {str(e)}')
|
58
|
-
except errors.FloodWait as e:
|
59
|
-
await message.reply(f'Flood wait: {e.value} sec')
|
60
|
-
except Exception as e:
|
61
|
-
await message.reply(f'Connection error: {str(e)}')
|
62
|
-
except Exception as e:
|
63
|
-
await message.reply(f'خطا: {str(e)}')
|
64
|
-
|
65
|
-
|
66
|
-
# ==========================
|
67
|
-
# تأیید کد ورود
|
68
|
-
# ==========================
|
69
|
-
async def set_code_cmd(message):
|
70
|
-
global login
|
71
|
-
parts = message.text.split(' ', 1)
|
72
|
-
if len(parts) < 2:
|
73
|
-
await message.reply('`code 12345`')
|
74
|
-
return
|
75
|
-
code = parts[1].strip()
|
76
|
-
|
77
|
-
try:
|
78
|
-
await login['client'].sign_in(login['number'], login['response'].phone_code_hash, code)
|
79
|
-
await login['client'].disconnect()
|
80
|
-
save_account_data(login['number'], login['api_data'])
|
81
|
-
await message.reply(f"✅ اکانت اضافه شد!\n├ شماره: {login['number']}")
|
82
|
-
login = {}
|
83
|
-
except errors.SessionPasswordNeeded:
|
84
|
-
await message.reply('🔒 لطفا رمز را با `pass your_password` بدهید')
|
85
|
-
except errors.BadRequest:
|
86
|
-
await message.reply('ورود با مشکل مواجه شد')
|
87
|
-
except Exception as e:
|
88
|
-
await message.reply(f'⚠️ خطا در ورود: {e}')
|
89
|
-
|
90
|
-
|
91
|
-
# ==========================
|
92
|
-
# افزودن رمز دومرحلهای
|
93
|
-
# ==========================
|
94
|
-
async def set_2fa_cmd(message):
|
95
|
-
global login
|
96
|
-
parts = message.text.split(' ', 1)
|
97
|
-
if len(parts) < 2:
|
98
|
-
await message.reply('`pass my_password`')
|
99
|
-
return
|
100
|
-
password = parts[1].strip()
|
101
|
-
try:
|
102
|
-
await login['client'].check_password(password)
|
103
|
-
login['api_data']['2fa_password'] = password
|
104
|
-
save_account_data(login['number'], login['api_data'])
|
105
|
-
await message.reply(f"✅ اکانت با موفقیت اضافه شد!\n├ شماره: {login['number']}")
|
106
|
-
await login['client'].disconnect()
|
107
|
-
login = {}
|
108
|
-
except errors.BadRequest:
|
109
|
-
await message.reply('رمز اشتباه است!')
|
110
|
-
except Exception as e:
|
111
|
-
await message.reply(f'⚠️ خطا در ثبت پسورد: {e}')
|
112
|
-
|
113
|
-
|
114
|
-
# ==========================
|
115
|
-
# حذف یک اکانت خاص
|
116
|
-
# ==========================
|
117
|
-
def remove_client_from_pool(phone_number: str):
|
118
|
-
cli = client_pool.get(phone_number)
|
119
|
-
if cli:
|
120
|
-
try:
|
121
|
-
asyncio.create_task(cli.stop())
|
122
|
-
except:
|
123
|
-
pass
|
124
|
-
client_pool.pop(phone_number, None)
|
125
|
-
client_locks.pop(phone_number, None)
|
126
|
-
|
127
|
-
|
128
|
-
async def delete_account_cmd(message):
|
129
|
-
try:
|
130
|
-
phone_number = message.text.split()[1]
|
131
|
-
main_path = f'{ACCOUNTS_FOLDER}/{phone_number}.session'
|
132
|
-
remove_client_from_pool(phone_number)
|
133
|
-
if os.path.isfile(main_path):
|
134
|
-
os.unlink(main_path)
|
135
|
-
await message.reply('<b>Account deleted successfully.</b>')
|
136
|
-
else:
|
137
|
-
await message.reply('<b>Account not found in database.</b>')
|
138
|
-
except IndexError:
|
139
|
-
await message.reply('Please enter phone number')
|
140
|
-
except Exception as e:
|
141
|
-
await message.reply(f'<b>Error deleting account: {str(e)}</b>')
|
142
|
-
|
143
|
-
|
144
|
-
# ==========================
|
145
|
-
# حذف تمام اکانتها
|
146
|
-
# ==========================
|
147
|
-
async def delete_all_accounts_cmd(message):
|
148
|
-
try:
|
149
|
-
accountss = accounts()
|
150
|
-
count = len(accountss)
|
151
|
-
await stop_all_clients()
|
152
|
-
for session in accountss:
|
153
|
-
main_path = f'{ACCOUNTS_FOLDER}/{session}.session'
|
154
|
-
try:
|
155
|
-
os.unlink(main_path)
|
156
|
-
except Exception:
|
157
|
-
pass
|
158
|
-
await message.reply(f'<b>{count} accounts deleted.</b>')
|
159
|
-
except Exception as e:
|
160
|
-
await message.reply(f'<b>Error deleting all accounts: {str(e)}</b>')
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|