CliRemote 1.7.12__tar.gz → 1.7.14__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.7.12 → cliremote-1.7.14}/CliRemote.egg-info/PKG-INFO +1 -1
- {cliremote-1.7.12 → cliremote-1.7.14}/PKG-INFO +1 -1
- {cliremote-1.7.12 → cliremote-1.7.14}/pyproject.toml +1 -1
- cliremote-1.7.14/remote/admin_manager.py +187 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/setup.py +1 -1
- cliremote-1.7.12/remote/admin_manager.py +0 -111
- {cliremote-1.7.12 → cliremote-1.7.14}/CliRemote.egg-info/SOURCES.txt +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/CliRemote.egg-info/dependency_links.txt +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/CliRemote.egg-info/requires.txt +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/CliRemote.egg-info/top_level.txt +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/LICENSE +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/MANIFEST.in +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/README.md +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/__init__.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/account_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/account_viewer.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/analytics_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/batch_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/block_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/caption_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/cleaner.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/client_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/client_picker.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/config.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/device_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/file_sender.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/getcode_controller.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/health.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/help_menu.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/init.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/join_controller.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/joiner.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/leave_controller.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/lefter.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/mention_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/precise_engine.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/profile_info.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/profile_media.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/profile_privacy.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/spammer.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/speed_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/stop_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/text_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/username_manager.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/utils/__init__.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/remote/utils/sqlite_utils.py +0 -0
- {cliremote-1.7.12 → cliremote-1.7.14}/setup.cfg +0 -0
@@ -0,0 +1,187 @@
|
|
1
|
+
# remote/admin_manager.py
|
2
|
+
import json
|
3
|
+
import os
|
4
|
+
import sys
|
5
|
+
import logging
|
6
|
+
from pathlib import Path
|
7
|
+
from pyrogram import filters
|
8
|
+
from . import config
|
9
|
+
|
10
|
+
# =============================
|
11
|
+
# تنظیم logger فایل
|
12
|
+
# =============================
|
13
|
+
|
14
|
+
def _project_root() -> Path:
|
15
|
+
"""ریشه پروژه = پوشهای که main.py داخلش اجرا شده. در صورت عدم دسترسی، از cwd استفاده میشود."""
|
16
|
+
try:
|
17
|
+
main_file = Path(sys.modules["__main__"].__file__).resolve()
|
18
|
+
return main_file.parent
|
19
|
+
except Exception:
|
20
|
+
return Path(os.getcwd()).resolve()
|
21
|
+
|
22
|
+
_PROJECT_ROOT = _project_root()
|
23
|
+
_LOG_DIR = _PROJECT_ROOT / "logs"
|
24
|
+
_LOG_DIR.mkdir(parents=True, exist_ok=True)
|
25
|
+
_LOG_PATH = _LOG_DIR / "admins_log.txt"
|
26
|
+
|
27
|
+
# logger اختصاصی این ماژول
|
28
|
+
logger = logging.getLogger("remote.admin_manager")
|
29
|
+
logger.setLevel(logging.DEBUG)
|
30
|
+
|
31
|
+
# جلوگیری از افزودن چندبارهی هندلر هنگام ریلود
|
32
|
+
if not any(isinstance(h, logging.FileHandler) and getattr(h, "_admin_log", False) for h in logger.handlers):
|
33
|
+
fh = logging.FileHandler(_LOG_PATH, encoding="utf-8")
|
34
|
+
fh._admin_log = True # پرچم داخلی برای تشخیص
|
35
|
+
fh.setLevel(logging.DEBUG)
|
36
|
+
fmt = logging.Formatter(
|
37
|
+
fmt="%(asctime)s | %(levelname)s | %(name)s | %(message)s",
|
38
|
+
datefmt="%Y-%m-%d %H:%M:%S"
|
39
|
+
)
|
40
|
+
fh.setFormatter(fmt)
|
41
|
+
logger.addHandler(fh)
|
42
|
+
|
43
|
+
logger.debug(f"Admin manager initialized. Log path: {_LOG_PATH}")
|
44
|
+
|
45
|
+
# =============================
|
46
|
+
# تنظیمات فایل ادمینها
|
47
|
+
# =============================
|
48
|
+
|
49
|
+
ADMINS_FILE = "admins.json" # اگر میخواهی کنار main.py باشد: ( _PROJECT_ROOT / "admins.json" ).as_posix()
|
50
|
+
|
51
|
+
def load_admins() -> list[int]:
|
52
|
+
"""
|
53
|
+
بارگذاری لیست ادمینها از فایل.
|
54
|
+
همیشه OWNER_ID را هم به لیست اضافه میکند.
|
55
|
+
"""
|
56
|
+
logger.debug(f"Loading admins from file: {ADMINS_FILE} | OWNER_ID: {config.OWNER_ID}")
|
57
|
+
s = set(config.OWNER_ID)
|
58
|
+
try:
|
59
|
+
if os.path.exists(ADMINS_FILE):
|
60
|
+
with open(ADMINS_FILE, "r", encoding="utf-8") as f:
|
61
|
+
data = json.load(f)
|
62
|
+
logger.info(f"admins.json loaded. Raw: {data!r}")
|
63
|
+
if isinstance(data, list):
|
64
|
+
for v in data:
|
65
|
+
try:
|
66
|
+
s.add(int(v))
|
67
|
+
except Exception as conv_err:
|
68
|
+
logger.warning(f"Skip invalid admin id in file: {v!r} | err={conv_err}")
|
69
|
+
else:
|
70
|
+
logger.info(f"admins.json not found at: {os.path.abspath(ADMINS_FILE)}")
|
71
|
+
except Exception as e:
|
72
|
+
logger.warning(f"Error loading admins: {e}", exc_info=True)
|
73
|
+
|
74
|
+
result = sorted(s)
|
75
|
+
logger.debug(f"Effective ADMINS after merge with OWNER_ID: {result}")
|
76
|
+
return result
|
77
|
+
|
78
|
+
|
79
|
+
def save_admins():
|
80
|
+
"""
|
81
|
+
ذخیرهی ادمینها در فایل.
|
82
|
+
"""
|
83
|
+
try:
|
84
|
+
# نکته: در این طراحی، ADMINS شامل OWNER_ID هم میتواند باشد؛ مشکلی نیست
|
85
|
+
logger.debug(f"Saving ADMINS to file: {ADMINS_FILE} | Data: {ADMINS}")
|
86
|
+
with open(ADMINS_FILE, "w", encoding="utf-8") as f:
|
87
|
+
json.dump(list(ADMINS), f, ensure_ascii=False, indent=2)
|
88
|
+
logger.info(f"Admins saved to {os.path.abspath(ADMINS_FILE)}")
|
89
|
+
except Exception as e:
|
90
|
+
logger.error(f"Error saving admins: {e}", exc_info=True)
|
91
|
+
|
92
|
+
|
93
|
+
ADMINS = load_admins()
|
94
|
+
logger.info(f"Loaded admins at import time: {ADMINS}")
|
95
|
+
|
96
|
+
# فیلترهای دسترسی برای Pyrogram
|
97
|
+
admin_filter = filters.create(
|
98
|
+
lambda _, __, m: bool(getattr(m, "from_user", None)) and int(m.from_user.id) in ADMINS
|
99
|
+
)
|
100
|
+
owner_filter = filters.create(
|
101
|
+
lambda _, __, m: bool(getattr(m, "from_user", None)) and int(m.from_user.id) in config.OWNER_ID
|
102
|
+
)
|
103
|
+
|
104
|
+
# =============================
|
105
|
+
# فرمانهای مدیریتی
|
106
|
+
# =============================
|
107
|
+
|
108
|
+
async def add_admin_cmd(message):
|
109
|
+
try:
|
110
|
+
uid_display = getattr(getattr(message, "from_user", None), "id", None)
|
111
|
+
logger.debug(f"add_admin_cmd triggered by user_id={uid_display} | text={message.text!r}")
|
112
|
+
|
113
|
+
parts = (message.text or "").split()
|
114
|
+
if len(parts) < 2:
|
115
|
+
logger.debug("add_admin_cmd: missing argument")
|
116
|
+
await message.reply("مثال: addadmin 123456789")
|
117
|
+
return
|
118
|
+
|
119
|
+
uid = int(parts[1])
|
120
|
+
logger.debug(f"add_admin_cmd: parsed target uid={uid}")
|
121
|
+
|
122
|
+
if uid in config.OWNER_ID:
|
123
|
+
logger.info(f"add_admin_cmd: uid={uid} is OWNER; skip append")
|
124
|
+
await message.reply("ادمین اصلی از قبل وجود دارد")
|
125
|
+
return
|
126
|
+
|
127
|
+
if uid not in ADMINS:
|
128
|
+
ADMINS.append(uid)
|
129
|
+
logger.info(f"Admin appended: {uid} | New ADMINS={sorted(ADMINS)}")
|
130
|
+
save_admins()
|
131
|
+
await message.reply(f"ادمین جدید اضافه شد: {uid}")
|
132
|
+
else:
|
133
|
+
logger.info(f"add_admin_cmd: uid={uid} already in ADMINS")
|
134
|
+
await message.reply("قبلاً ادمین بود")
|
135
|
+
except Exception as e:
|
136
|
+
logger.error(f"add_admin_cmd error: {e}", exc_info=True)
|
137
|
+
await message.reply(f"خطا: {e}")
|
138
|
+
|
139
|
+
|
140
|
+
async def del_admin_cmd(message):
|
141
|
+
try:
|
142
|
+
uid_display = getattr(getattr(message, "from_user", None), "id", None)
|
143
|
+
logger.debug(f"del_admin_cmd triggered by user_id={uid_display} | text={message.text!r}")
|
144
|
+
|
145
|
+
parts = (message.text or "").split()
|
146
|
+
if len(parts) < 2:
|
147
|
+
logger.debug("del_admin_cmd: missing argument")
|
148
|
+
await message.reply("مثال: deladmin 123456789")
|
149
|
+
return
|
150
|
+
|
151
|
+
uid = int(parts[1])
|
152
|
+
logger.debug(f"del_admin_cmd: parsed target uid={uid}")
|
153
|
+
|
154
|
+
if uid in config.OWNER_ID:
|
155
|
+
logger.info(f"del_admin_cmd: attempt to remove OWNER uid={uid} blocked")
|
156
|
+
await message.reply("❌ امکان حذف ادمین اصلی وجود ندارد")
|
157
|
+
return
|
158
|
+
|
159
|
+
if uid in ADMINS:
|
160
|
+
ADMINS.remove(uid)
|
161
|
+
logger.info(f"Admin removed: {uid} | New ADMINS={sorted(ADMINS)}")
|
162
|
+
save_admins()
|
163
|
+
await message.reply(f"ادمین حذف شد: {uid}")
|
164
|
+
else:
|
165
|
+
logger.info(f"del_admin_cmd: uid={uid} not in ADMINS")
|
166
|
+
await message.reply("کاربر ادمین نیست")
|
167
|
+
except Exception as e:
|
168
|
+
logger.error(f"del_admin_cmd error: {e}", exc_info=True)
|
169
|
+
await message.reply(f"خطا: {e}")
|
170
|
+
|
171
|
+
|
172
|
+
async def list_admins_cmd(message):
|
173
|
+
try:
|
174
|
+
uid_display = getattr(getattr(message, "from_user", None), "id", None)
|
175
|
+
logger.debug(f"list_admins_cmd triggered by user_id={uid_display}")
|
176
|
+
|
177
|
+
if not ADMINS:
|
178
|
+
logger.info("list_admins_cmd: ADMINS is empty")
|
179
|
+
await message.reply("لیست ادمینها خالی است.")
|
180
|
+
return
|
181
|
+
|
182
|
+
text = "👑 <b>ADMINS:</b>\n" + "\n".join([str(x) for x in sorted(ADMINS)])
|
183
|
+
logger.debug(f"list_admins_cmd: respond with {len(ADMINS)} admins")
|
184
|
+
await message.reply(text)
|
185
|
+
except Exception as e:
|
186
|
+
logger.error(f"list_admins_cmd error: {e}", exc_info=True)
|
187
|
+
await message.reply(f"خطا: {e}")
|
@@ -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.7.
|
8
|
+
version="1.7.14",
|
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,111 +0,0 @@
|
|
1
|
-
# remote/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}")
|
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
|
File without changes
|
File without changes
|
File without changes
|