CliRemote 1.2.2__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.
Potentially problematic release.
This version of CliRemote might be problematic. Click here for more details.
- cliremote-1.2.2/CliRemote.egg-info/PKG-INFO +39 -0
- cliremote-1.2.2/CliRemote.egg-info/SOURCES.txt +42 -0
- cliremote-1.2.2/CliRemote.egg-info/dependency_links.txt +1 -0
- cliremote-1.2.2/CliRemote.egg-info/requires.txt +6 -0
- cliremote-1.2.2/CliRemote.egg-info/top_level.txt +2 -0
- cliremote-1.2.2/LICENSE +21 -0
- cliremote-1.2.2/MANIFEST.in +3 -0
- cliremote-1.2.2/PKG-INFO +39 -0
- cliremote-1.2.2/README.md +3 -0
- cliremote-1.2.2/pyproject.toml +47 -0
- cliremote-1.2.2/setup.cfg +11 -0
- cliremote-1.2.2/setup.py +39 -0
- cliremote-1.2.2/src/remote/__init__.py +0 -0
- cliremote-1.2.2/src/remote/account_manager.py +161 -0
- cliremote-1.2.2/src/remote/account_viewer.py +102 -0
- cliremote-1.2.2/src/remote/admin_manager.py +111 -0
- cliremote-1.2.2/src/remote/analytics_manager.py +98 -0
- cliremote-1.2.2/src/remote/batch_manager.py +34 -0
- cliremote-1.2.2/src/remote/block_manager.py +165 -0
- cliremote-1.2.2/src/remote/caption_manager.py +25 -0
- cliremote-1.2.2/src/remote/cleaner.py +139 -0
- cliremote-1.2.2/src/remote/client_manager.py +131 -0
- cliremote-1.2.2/src/remote/config.py +63 -0
- cliremote-1.2.2/src/remote/device_manager.py +142 -0
- cliremote-1.2.2/src/remote/file_sender.py +87 -0
- cliremote-1.2.2/src/remote/getcode_controller.py +44 -0
- cliremote-1.2.2/src/remote/health.py +31 -0
- cliremote-1.2.2/src/remote/help_menu.py +58 -0
- cliremote-1.2.2/src/remote/init.py +15 -0
- cliremote-1.2.2/src/remote/join_controller.py +34 -0
- cliremote-1.2.2/src/remote/joiner.py +77 -0
- cliremote-1.2.2/src/remote/leave_controller.py +34 -0
- cliremote-1.2.2/src/remote/lefter.py +101 -0
- cliremote-1.2.2/src/remote/mention_manager.py +82 -0
- cliremote-1.2.2/src/remote/precise_engine.py +19 -0
- cliremote-1.2.2/src/remote/profile_info.py +53 -0
- cliremote-1.2.2/src/remote/profile_media.py +57 -0
- cliremote-1.2.2/src/remote/profile_privacy.py +62 -0
- cliremote-1.2.2/src/remote/spammer.py +115 -0
- cliremote-1.2.2/src/remote/speed_manager.py +30 -0
- cliremote-1.2.2/src/remote/stop_manager.py +30 -0
- cliremote-1.2.2/src/remote/text_manager.py +59 -0
- cliremote-1.2.2/src/remote/username_manager.py +92 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: CliRemote
|
|
3
|
+
Version: 1.2.2
|
|
4
|
+
Summary: Remote client framework for Telegram automation using Pyrogram
|
|
5
|
+
Home-page: https://github.com/MohammadAhmadi-R/CliRemote
|
|
6
|
+
Author: MrAhmadiRad
|
|
7
|
+
Author-email: MohammadAhmadiRad <mohammadahmadirad69@gmail.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/MohammadAhmadi-R/CliRemote
|
|
10
|
+
Keywords: pyrogram,bot,automation,asyncio
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Framework :: AsyncIO
|
|
16
|
+
Classifier: Programming Language :: Python
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: pyrogram>=2.0.106
|
|
28
|
+
Requires-Dist: httpx>=0.27.0
|
|
29
|
+
Requires-Dist: pytz>=2023.3
|
|
30
|
+
Provides-Extra: speedups
|
|
31
|
+
Requires-Dist: tgcrypto>=1.2.5; extra == "speedups"
|
|
32
|
+
Dynamic: author
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
|
|
37
|
+
# Remote
|
|
38
|
+
Core Telegram Remote client engine (MrAhmadiRad)
|
|
39
|
+
[GitHub-flavored Markdown](https://github.com/MohammadAhmadi-R/CliRemote)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
setup.cfg
|
|
6
|
+
setup.py
|
|
7
|
+
CliRemote.egg-info/PKG-INFO
|
|
8
|
+
CliRemote.egg-info/SOURCES.txt
|
|
9
|
+
CliRemote.egg-info/dependency_links.txt
|
|
10
|
+
CliRemote.egg-info/requires.txt
|
|
11
|
+
CliRemote.egg-info/top_level.txt
|
|
12
|
+
src/remote/__init__.py
|
|
13
|
+
src/remote/account_manager.py
|
|
14
|
+
src/remote/account_viewer.py
|
|
15
|
+
src/remote/admin_manager.py
|
|
16
|
+
src/remote/analytics_manager.py
|
|
17
|
+
src/remote/batch_manager.py
|
|
18
|
+
src/remote/block_manager.py
|
|
19
|
+
src/remote/caption_manager.py
|
|
20
|
+
src/remote/cleaner.py
|
|
21
|
+
src/remote/client_manager.py
|
|
22
|
+
src/remote/config.py
|
|
23
|
+
src/remote/device_manager.py
|
|
24
|
+
src/remote/file_sender.py
|
|
25
|
+
src/remote/getcode_controller.py
|
|
26
|
+
src/remote/health.py
|
|
27
|
+
src/remote/help_menu.py
|
|
28
|
+
src/remote/init.py
|
|
29
|
+
src/remote/join_controller.py
|
|
30
|
+
src/remote/joiner.py
|
|
31
|
+
src/remote/leave_controller.py
|
|
32
|
+
src/remote/lefter.py
|
|
33
|
+
src/remote/mention_manager.py
|
|
34
|
+
src/remote/precise_engine.py
|
|
35
|
+
src/remote/profile_info.py
|
|
36
|
+
src/remote/profile_media.py
|
|
37
|
+
src/remote/profile_privacy.py
|
|
38
|
+
src/remote/spammer.py
|
|
39
|
+
src/remote/speed_manager.py
|
|
40
|
+
src/remote/stop_manager.py
|
|
41
|
+
src/remote/text_manager.py
|
|
42
|
+
src/remote/username_manager.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
cliremote-1.2.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
cliremote-1.2.2/PKG-INFO
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: CliRemote
|
|
3
|
+
Version: 1.2.2
|
|
4
|
+
Summary: Remote client framework for Telegram automation using Pyrogram
|
|
5
|
+
Home-page: https://github.com/MohammadAhmadi-R/CliRemote
|
|
6
|
+
Author: MrAhmadiRad
|
|
7
|
+
Author-email: MohammadAhmadiRad <mohammadahmadirad69@gmail.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/MohammadAhmadi-R/CliRemote
|
|
10
|
+
Keywords: pyrogram,bot,automation,asyncio
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Framework :: AsyncIO
|
|
16
|
+
Classifier: Programming Language :: Python
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: pyrogram>=2.0.106
|
|
28
|
+
Requires-Dist: httpx>=0.27.0
|
|
29
|
+
Requires-Dist: pytz>=2023.3
|
|
30
|
+
Provides-Extra: speedups
|
|
31
|
+
Requires-Dist: tgcrypto>=1.2.5; extra == "speedups"
|
|
32
|
+
Dynamic: author
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
|
|
37
|
+
# Remote
|
|
38
|
+
Core Telegram Remote client engine (MrAhmadiRad)
|
|
39
|
+
[GitHub-flavored Markdown](https://github.com/MohammadAhmadi-R/CliRemote)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "CliRemote"
|
|
7
|
+
version = "1.2.2"
|
|
8
|
+
description = "Remote client framework for Telegram automation using Pyrogram"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "MohammadAhmadiRad", email = "mohammadahmadirad69@gmail.com" }
|
|
13
|
+
]
|
|
14
|
+
requires-python = ">=3.13"
|
|
15
|
+
|
|
16
|
+
dependencies = [
|
|
17
|
+
"pyrogram>=2.0.106",
|
|
18
|
+
"httpx>=0.27.0",
|
|
19
|
+
"pytz>=2023.3"
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 4 - Beta",
|
|
24
|
+
"Intended Audience :: Developers",
|
|
25
|
+
"License :: OSI Approved :: MIT License",
|
|
26
|
+
"Operating System :: OS Independent",
|
|
27
|
+
"Framework :: AsyncIO",
|
|
28
|
+
"Programming Language :: Python",
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Programming Language :: Python :: 3.8",
|
|
31
|
+
"Programming Language :: Python :: 3.9",
|
|
32
|
+
"Programming Language :: Python :: 3.10",
|
|
33
|
+
"Programming Language :: Python :: 3.11",
|
|
34
|
+
"Programming Language :: Python :: 3.12",
|
|
35
|
+
"Programming Language :: Python :: 3.13"
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
keywords = ["pyrogram", "bot", "automation", "asyncio"]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://github.com/MohammadAhmadi-R/CliRemote"
|
|
42
|
+
|
|
43
|
+
[project.optional-dependencies]
|
|
44
|
+
speedups = ["tgcrypto>=1.2.5"]
|
|
45
|
+
|
|
46
|
+
[tool.setuptools]
|
|
47
|
+
packages = { find = { where = ["."] } }
|
cliremote-1.2.2/setup.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
with open("README.md", encoding="utf-8") as f:
|
|
4
|
+
long_description = f.read()
|
|
5
|
+
|
|
6
|
+
setup(
|
|
7
|
+
name="CliRemote",
|
|
8
|
+
version="1.2.3", # ← نسخه جدید
|
|
9
|
+
author="MrAhmadiRad",
|
|
10
|
+
author_email="mohammadahmadirad69@gmail.com",
|
|
11
|
+
description="A precise, async-safe, Telegram automation core (Python 3.8+)",
|
|
12
|
+
long_description=long_description,
|
|
13
|
+
long_description_content_type="text/markdown",
|
|
14
|
+
url="https://github.com/MohammadAhmadi-R/CliRemote",
|
|
15
|
+
packages=find_packages(),
|
|
16
|
+
install_requires=[
|
|
17
|
+
"pyrogram>=2.0.106",
|
|
18
|
+
"httpx>=0.27.0",
|
|
19
|
+
"pytz>=2023.3",
|
|
20
|
+
],
|
|
21
|
+
python_requires=">=3.8",
|
|
22
|
+
classifiers=[
|
|
23
|
+
"Development Status :: 4 - Beta",
|
|
24
|
+
"Intended Audience :: Developers",
|
|
25
|
+
"License :: OSI Approved :: MIT License",
|
|
26
|
+
"Operating System :: OS Independent",
|
|
27
|
+
"Framework :: AsyncIO",
|
|
28
|
+
"Topic :: Communications",
|
|
29
|
+
"Topic :: Communications :: Chat",
|
|
30
|
+
"Programming Language :: Python",
|
|
31
|
+
"Programming Language :: Python :: 3",
|
|
32
|
+
"Programming Language :: Python :: 3.8",
|
|
33
|
+
"Programming Language :: Python :: 3.9",
|
|
34
|
+
"Programming Language :: Python :: 3.10",
|
|
35
|
+
"Programming Language :: Python :: 3.11",
|
|
36
|
+
"Programming Language :: Python :: 3.12",
|
|
37
|
+
"Programming Language :: Python :: 3.13",
|
|
38
|
+
],
|
|
39
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,161 @@
|
|
|
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
|
+
get_account_data,
|
|
8
|
+
save_account_data,
|
|
9
|
+
stop_all_clients,
|
|
10
|
+
accounts,
|
|
11
|
+
client_pool,
|
|
12
|
+
client_locks
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
login = {}
|
|
17
|
+
|
|
18
|
+
# ==========================
|
|
19
|
+
# افزودن اکانت جدید
|
|
20
|
+
# ==========================
|
|
21
|
+
async def add_account_cmd(message, get_app_info):
|
|
22
|
+
try:
|
|
23
|
+
parts = message.text.split(' ', 1)
|
|
24
|
+
if len(parts) < 2:
|
|
25
|
+
await message.reply('مثال: `add +989123456789`')
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
phone_number = parts[1].strip()
|
|
29
|
+
session_file = os.path.join(ACCOUNTS_FOLDER, f'{phone_number}.session')
|
|
30
|
+
|
|
31
|
+
if os.path.exists(session_file):
|
|
32
|
+
await message.reply('این اکانت وجود دارد!')
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
global login
|
|
36
|
+
api = get_app_info()
|
|
37
|
+
if not api or len(api) < 2:
|
|
38
|
+
await message.reply('مشکل در API!')
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
login['id'] = int(api[1])
|
|
42
|
+
login['hash'] = api[0]
|
|
43
|
+
login['number'] = phone_number
|
|
44
|
+
login['api_data'] = {
|
|
45
|
+
'api_id': api[1],
|
|
46
|
+
'api_hash': api[0],
|
|
47
|
+
'phone_number': phone_number,
|
|
48
|
+
'session': phone_number,
|
|
49
|
+
'2fa_password': None
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
login['client'] = Client(name=session_file.replace('.session', ''), api_id=login['id'], api_hash=login['hash'])
|
|
54
|
+
await login['client'].connect()
|
|
55
|
+
login['response'] = await login['client'].send_code(phone_number)
|
|
56
|
+
await message.reply(f'✅ کد تأیید به {phone_number} ارسال شد.\n`code 12345`')
|
|
57
|
+
except errors.BadRequest as e:
|
|
58
|
+
await message.reply(f'Bad request: {str(e)}')
|
|
59
|
+
except errors.FloodWait as e:
|
|
60
|
+
await message.reply(f'Flood wait: {e.value} sec')
|
|
61
|
+
except Exception as e:
|
|
62
|
+
await message.reply(f'Connection error: {str(e)}')
|
|
63
|
+
except Exception as e:
|
|
64
|
+
await message.reply(f'خطا: {str(e)}')
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# ==========================
|
|
68
|
+
# تأیید کد ورود
|
|
69
|
+
# ==========================
|
|
70
|
+
async def set_code_cmd(message):
|
|
71
|
+
global login
|
|
72
|
+
parts = message.text.split(' ', 1)
|
|
73
|
+
if len(parts) < 2:
|
|
74
|
+
await message.reply('`code 12345`')
|
|
75
|
+
return
|
|
76
|
+
code = parts[1].strip()
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
await login['client'].sign_in(login['number'], login['response'].phone_code_hash, code)
|
|
80
|
+
await login['client'].disconnect()
|
|
81
|
+
save_account_data(login['number'], login['api_data'])
|
|
82
|
+
await message.reply(f"✅ اکانت اضافه شد!\n├ شماره: {login['number']}")
|
|
83
|
+
login = {}
|
|
84
|
+
except errors.SessionPasswordNeeded:
|
|
85
|
+
await message.reply('🔒 لطفا رمز را با `pass your_password` بدهید')
|
|
86
|
+
except errors.BadRequest:
|
|
87
|
+
await message.reply('ورود با مشکل مواجه شد')
|
|
88
|
+
except Exception as e:
|
|
89
|
+
await message.reply(f'⚠️ خطا در ورود: {e}')
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# ==========================
|
|
93
|
+
# افزودن رمز دومرحلهای
|
|
94
|
+
# ==========================
|
|
95
|
+
async def set_2fa_cmd(message):
|
|
96
|
+
global login
|
|
97
|
+
parts = message.text.split(' ', 1)
|
|
98
|
+
if len(parts) < 2:
|
|
99
|
+
await message.reply('`pass my_password`')
|
|
100
|
+
return
|
|
101
|
+
password = parts[1].strip()
|
|
102
|
+
try:
|
|
103
|
+
await login['client'].check_password(password)
|
|
104
|
+
login['api_data']['2fa_password'] = password
|
|
105
|
+
save_account_data(login['number'], login['api_data'])
|
|
106
|
+
await message.reply(f"✅ اکانت با موفقیت اضافه شد!\n├ شماره: {login['number']}")
|
|
107
|
+
await login['client'].disconnect()
|
|
108
|
+
login = {}
|
|
109
|
+
except errors.BadRequest:
|
|
110
|
+
await message.reply('رمز اشتباه است!')
|
|
111
|
+
except Exception as e:
|
|
112
|
+
await message.reply(f'⚠️ خطا در ثبت پسورد: {e}')
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
# ==========================
|
|
116
|
+
# حذف یک اکانت خاص
|
|
117
|
+
# ==========================
|
|
118
|
+
def remove_client_from_pool(phone_number: str):
|
|
119
|
+
cli = client_pool.get(phone_number)
|
|
120
|
+
if cli:
|
|
121
|
+
try:
|
|
122
|
+
asyncio.create_task(cli.stop())
|
|
123
|
+
except:
|
|
124
|
+
pass
|
|
125
|
+
client_pool.pop(phone_number, None)
|
|
126
|
+
client_locks.pop(phone_number, None)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
async def delete_account_cmd(message):
|
|
130
|
+
try:
|
|
131
|
+
phone_number = message.text.split()[1]
|
|
132
|
+
main_path = f'{ACCOUNTS_FOLDER}/{phone_number}.session'
|
|
133
|
+
remove_client_from_pool(phone_number)
|
|
134
|
+
if os.path.isfile(main_path):
|
|
135
|
+
os.unlink(main_path)
|
|
136
|
+
await message.reply('<b>Account deleted successfully.</b>')
|
|
137
|
+
else:
|
|
138
|
+
await message.reply('<b>Account not found in database.</b>')
|
|
139
|
+
except IndexError:
|
|
140
|
+
await message.reply('Please enter phone number')
|
|
141
|
+
except Exception as e:
|
|
142
|
+
await message.reply(f'<b>Error deleting account: {str(e)}</b>')
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# ==========================
|
|
146
|
+
# حذف تمام اکانتها
|
|
147
|
+
# ==========================
|
|
148
|
+
async def delete_all_accounts_cmd(message):
|
|
149
|
+
try:
|
|
150
|
+
accountss = accounts()
|
|
151
|
+
count = len(accountss)
|
|
152
|
+
await stop_all_clients()
|
|
153
|
+
for session in accountss:
|
|
154
|
+
main_path = f'{ACCOUNTS_FOLDER}/{session}.session'
|
|
155
|
+
try:
|
|
156
|
+
os.unlink(main_path)
|
|
157
|
+
except Exception:
|
|
158
|
+
pass
|
|
159
|
+
await message.reply(f'<b>{count} accounts deleted.</b>')
|
|
160
|
+
except Exception as e:
|
|
161
|
+
await message.reply(f'<b>Error deleting all accounts: {str(e)}</b>')
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# antispam_core/account_viewer.py
|
|
2
|
+
import asyncio, logging
|
|
3
|
+
from pyrogram import errors
|
|
4
|
+
from .client_manager import client_pool, get_or_start_client, accounts
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
async def list_accounts_cmd(message):
|
|
9
|
+
"""
|
|
10
|
+
نمایش دقیق وضعیت اکانتها (با حفظ اتصالها)
|
|
11
|
+
از client_pool برای بررسی فعال بودن استفاده میکند.
|
|
12
|
+
"""
|
|
13
|
+
try:
|
|
14
|
+
acc_list = accounts()
|
|
15
|
+
if not acc_list:
|
|
16
|
+
await message.reply('لیست اکانتها:\n(هیچ اکانتی وجود ندارد)')
|
|
17
|
+
return
|
|
18
|
+
|
|
19
|
+
lines = ['📋 <b>لیست اکانتها:</b>']
|
|
20
|
+
success, failed = 0, 0
|
|
21
|
+
|
|
22
|
+
for idx, phone in enumerate(acc_list, start=1):
|
|
23
|
+
try:
|
|
24
|
+
# 🔹 دریافت کلاینت از pool یا ساخت مجدد
|
|
25
|
+
cli = client_pool.get(phone)
|
|
26
|
+
if cli is None or not getattr(cli, 'is_connected', False):
|
|
27
|
+
cli = await get_or_start_client(phone)
|
|
28
|
+
|
|
29
|
+
# تلاش مجدد در صورت قطع بودن
|
|
30
|
+
if cli is None:
|
|
31
|
+
await asyncio.sleep(0.8)
|
|
32
|
+
cli = await get_or_start_client(phone)
|
|
33
|
+
|
|
34
|
+
if cli is None:
|
|
35
|
+
raise Exception("Client could not be started")
|
|
36
|
+
|
|
37
|
+
# 🔁 تا دو بار تلاش برای دریافت اطلاعات
|
|
38
|
+
retry = 0
|
|
39
|
+
me = None
|
|
40
|
+
while retry < 2:
|
|
41
|
+
try:
|
|
42
|
+
me = await cli.get_me()
|
|
43
|
+
if me:
|
|
44
|
+
break
|
|
45
|
+
except errors.FloodWait as e:
|
|
46
|
+
await asyncio.sleep(e.value)
|
|
47
|
+
except Exception:
|
|
48
|
+
retry += 1
|
|
49
|
+
await asyncio.sleep(1)
|
|
50
|
+
|
|
51
|
+
if me:
|
|
52
|
+
success += 1
|
|
53
|
+
full_name = (me.first_name or "") + " " + (me.last_name or "")
|
|
54
|
+
full_name = full_name.strip() or "-"
|
|
55
|
+
uid = me.id
|
|
56
|
+
lines.append(f"\n<b>{idx}. {phone}</b>")
|
|
57
|
+
lines.append(f"Status : ✅ OK")
|
|
58
|
+
lines.append(f"Power : 🟢 ON")
|
|
59
|
+
lines.append(f"Name : {full_name}")
|
|
60
|
+
lines.append(f"UserID : <code>{uid}</code>")
|
|
61
|
+
else:
|
|
62
|
+
failed += 1
|
|
63
|
+
lines.append(f"\n<b>{idx}. {phone}</b>")
|
|
64
|
+
lines.append(f"Status : ❌ ERROR")
|
|
65
|
+
lines.append(f"Power : 🔴 OFF")
|
|
66
|
+
lines.append(f"Name : -")
|
|
67
|
+
lines.append(f"UserID : -")
|
|
68
|
+
|
|
69
|
+
except errors.UserDeactivated:
|
|
70
|
+
failed += 1
|
|
71
|
+
lines.append(f"\n<b>{idx}. {phone}</b>")
|
|
72
|
+
lines.append(f"Status : 🚫 Deactivated")
|
|
73
|
+
lines.append(f"Power : 🔴 OFF")
|
|
74
|
+
lines.append(f"Name : -")
|
|
75
|
+
lines.append(f"UserID : -")
|
|
76
|
+
|
|
77
|
+
except Exception as e:
|
|
78
|
+
failed += 1
|
|
79
|
+
lines.append(f"\n<b>{idx}. {phone}</b>")
|
|
80
|
+
lines.append(f"Status : ⚠️ Error: {str(e)[:40]}")
|
|
81
|
+
lines.append(f"Power : 🔴 OFF")
|
|
82
|
+
lines.append(f"Name : -")
|
|
83
|
+
lines.append(f"UserID : -")
|
|
84
|
+
|
|
85
|
+
await asyncio.sleep(0.5)
|
|
86
|
+
|
|
87
|
+
total = len(acc_list)
|
|
88
|
+
lines.append(f"\n📊 <b>نتیجه:</b>\n✅ سالم: {success}\n❌ خطادار: {failed}\n🔹 مجموع: {total}")
|
|
89
|
+
|
|
90
|
+
text = "\n".join(lines)
|
|
91
|
+
|
|
92
|
+
# ✅ اگر خروجی خیلی طولانی بود، فایل گزارش ارسال شود
|
|
93
|
+
if len(text) > 3900:
|
|
94
|
+
await message.reply_document(
|
|
95
|
+
document=("accounts_report.txt", text.encode('utf-8')),
|
|
96
|
+
caption="📋 گزارش کامل اکانتها"
|
|
97
|
+
)
|
|
98
|
+
else:
|
|
99
|
+
await message.reply(text, disable_web_page_preview=True)
|
|
100
|
+
|
|
101
|
+
except Exception as e:
|
|
102
|
+
await message.reply(f'<b>خطا در نمایش لیست اکانتها:</b>\n{e}')
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# antispam_core/admin_manager.py
|
|
2
|
+
import json, os, logging
|
|
3
|
+
from pyrogram import filters
|
|
4
|
+
from .config import OWNER_ID
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
ADMINS_FILE = "admins.json"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def load_admins() -> list[int]:
|
|
12
|
+
"""
|
|
13
|
+
بارگذاری لیست ادمینها از فایل.
|
|
14
|
+
همیشه OWNER_ID را هم به لیست اضافه میکند.
|
|
15
|
+
"""
|
|
16
|
+
s = set(OWNER_ID)
|
|
17
|
+
try:
|
|
18
|
+
if os.path.exists(ADMINS_FILE):
|
|
19
|
+
with open(ADMINS_FILE, "r", encoding="utf-8") as f:
|
|
20
|
+
data = json.load(f)
|
|
21
|
+
if isinstance(data, list):
|
|
22
|
+
for v in data:
|
|
23
|
+
try:
|
|
24
|
+
s.add(int(v))
|
|
25
|
+
except:
|
|
26
|
+
pass
|
|
27
|
+
except Exception as e:
|
|
28
|
+
logger.warning(f"Error loading admins: {e}")
|
|
29
|
+
return list(s)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def save_admins():
|
|
33
|
+
"""
|
|
34
|
+
ذخیرهی ادمینها در فایل.
|
|
35
|
+
"""
|
|
36
|
+
try:
|
|
37
|
+
with open(ADMINS_FILE, "w", encoding="utf-8") as f:
|
|
38
|
+
json.dump(list(ADMINS), f, ensure_ascii=False, indent=2)
|
|
39
|
+
except Exception as e:
|
|
40
|
+
logger.error(f"Error saving admins: {e}")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
ADMINS = load_admins()
|
|
44
|
+
|
|
45
|
+
# فیلترهای دسترسی برای Pyrogram
|
|
46
|
+
admin_filter = filters.create(
|
|
47
|
+
lambda _, __, m: bool(getattr(m, "from_user", None))
|
|
48
|
+
and int(m.from_user.id) in ADMINS
|
|
49
|
+
)
|
|
50
|
+
owner_filter = filters.create(
|
|
51
|
+
lambda _, __, m: bool(getattr(m, "from_user", None))
|
|
52
|
+
and int(m.from_user.id) in OWNER_ID
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# =============================
|
|
57
|
+
# فرمانهای مدیریتی
|
|
58
|
+
# =============================
|
|
59
|
+
|
|
60
|
+
async def add_admin_cmd(message):
|
|
61
|
+
try:
|
|
62
|
+
parts = message.text.split()
|
|
63
|
+
if len(parts) < 2:
|
|
64
|
+
await message.reply("مثال: addadmin 123456789")
|
|
65
|
+
return
|
|
66
|
+
uid = int(parts[1])
|
|
67
|
+
if uid in OWNER_ID:
|
|
68
|
+
await message.reply("ادمین اصلی از قبل وجود دارد")
|
|
69
|
+
return
|
|
70
|
+
if uid not in ADMINS:
|
|
71
|
+
ADMINS.append(uid)
|
|
72
|
+
save_admins()
|
|
73
|
+
await message.reply(f"ادمین جدید اضافه شد: {uid}")
|
|
74
|
+
else:
|
|
75
|
+
await message.reply("قبلاً ادمین بود")
|
|
76
|
+
except Exception as e:
|
|
77
|
+
logger.error(f"add_admin_cmd error: {e}")
|
|
78
|
+
await message.reply(f"خطا: {e}")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
async def del_admin_cmd(message):
|
|
82
|
+
try:
|
|
83
|
+
parts = message.text.split()
|
|
84
|
+
if len(parts) < 2:
|
|
85
|
+
await message.reply("مثال: deladmin 123456789")
|
|
86
|
+
return
|
|
87
|
+
uid = int(parts[1])
|
|
88
|
+
if uid in OWNER_ID:
|
|
89
|
+
await message.reply("❌ امکان حذف ادمین اصلی وجود ندارد")
|
|
90
|
+
return
|
|
91
|
+
if uid in ADMINS:
|
|
92
|
+
ADMINS.remove(uid)
|
|
93
|
+
save_admins()
|
|
94
|
+
await message.reply(f"ادمین حذف شد: {uid}")
|
|
95
|
+
else:
|
|
96
|
+
await message.reply("کاربر ادمین نیست")
|
|
97
|
+
except Exception as e:
|
|
98
|
+
logger.error(f"del_admin_cmd error: {e}")
|
|
99
|
+
await message.reply(f"خطا: {e}")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
async def list_admins_cmd(message):
|
|
103
|
+
try:
|
|
104
|
+
if not ADMINS:
|
|
105
|
+
await message.reply("لیست ادمینها خالی است.")
|
|
106
|
+
return
|
|
107
|
+
text = "👑 <b>ADMINS:</b>\n" + "\n".join([str(x) for x in ADMINS])
|
|
108
|
+
await message.reply(text)
|
|
109
|
+
except Exception as e:
|
|
110
|
+
logger.error(f"list_admins_cmd error: {e}")
|
|
111
|
+
await message.reply(f"خطا: {e}")
|