CliRemote 1.7.10__py3-none-any.whl → 1.7.13__py3-none-any.whl
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.10.dist-info → cliremote-1.7.13.dist-info}/METADATA +1 -1
- {cliremote-1.7.10.dist-info → cliremote-1.7.13.dist-info}/RECORD +6 -6
- remote/admin_manager.py +107 -45
- {cliremote-1.7.10.dist-info → cliremote-1.7.13.dist-info}/WHEEL +0 -0
- {cliremote-1.7.10.dist-info → cliremote-1.7.13.dist-info}/licenses/LICENSE +0 -0
- {cliremote-1.7.10.dist-info → cliremote-1.7.13.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,8 @@
|
|
1
|
-
cliremote-1.7.
|
1
|
+
cliremote-1.7.13.dist-info/licenses/LICENSE,sha256=O-0zMbcEi6wXz1DiSdVgzMlQjJcNqNe5KDv08uYzqR0,1055
|
2
2
|
remote/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
remote/account_manager.py,sha256=TepnGIoE2hU-j_NmU5ByoS-JrboE0w3A1bYmQoQX5h8,15176
|
4
4
|
remote/account_viewer.py,sha256=j46KSjbgrBmBi7UxFeJ5tCwHIe0QvCvphkirGIbB2oo,5192
|
5
|
-
remote/admin_manager.py,sha256=
|
5
|
+
remote/admin_manager.py,sha256=JXxZ6dEF5xXUcNmLmxuFAAUE7EyHDf0sLutTQYnTlHY,7392
|
6
6
|
remote/analytics_manager.py,sha256=6jPvwt_ELA4RMbQdD8W_ltfAoaSgILnEkOAp6HZAqsU,7382
|
7
7
|
remote/batch_manager.py,sha256=jVGhYVwHMKJd7f7JxcWjKlwr03dq0RaGD1KdkyYdb00,1051
|
8
8
|
remote/block_manager.py,sha256=R7UaQigr-hTRtjxjG3OvJdKhvp0mDpLaESp3Of1AYhs,5692
|
@@ -33,7 +33,7 @@ remote/text_manager.py,sha256=C2wNSXPSCDu8NSD3RsfbKmUQMWOYd1B5N4tzy-Jsriw,2195
|
|
33
33
|
remote/username_manager.py,sha256=nMNdke-2FIv86xR1Y6rR-43oUoQu_3Khw8wEo54noXI,3388
|
34
34
|
remote/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
35
|
remote/utils/sqlite_utils.py,sha256=5i0oUXsBgKC_8qHZPJ-Gyhp9D1TwqKHVvuZRIhKpS6w,1260
|
36
|
-
cliremote-1.7.
|
37
|
-
cliremote-1.7.
|
38
|
-
cliremote-1.7.
|
39
|
-
cliremote-1.7.
|
36
|
+
cliremote-1.7.13.dist-info/METADATA,sha256=AGkWN4uIhUNz55bPpKmv6t31CJvf53AS2l3uuMsjlJg,1203
|
37
|
+
cliremote-1.7.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
38
|
+
cliremote-1.7.13.dist-info/top_level.txt,sha256=yBZidJ6zCix_a2ubGlYaewvlzBFXWbckQt20dudxJ1E,7
|
39
|
+
cliremote-1.7.13.dist-info/RECORD,,
|
remote/admin_manager.py
CHANGED
@@ -1,67 +1,99 @@
|
|
1
1
|
# remote/admin_manager.py
|
2
|
-
import json
|
2
|
+
import json
|
3
|
+
import os
|
4
|
+
import sys
|
5
|
+
import logging
|
3
6
|
from pathlib import Path
|
4
7
|
from pyrogram import filters
|
5
8
|
from .config import OWNER_ID
|
6
9
|
|
7
|
-
|
10
|
+
# =============================
|
11
|
+
# تنظیم logger فایل
|
12
|
+
# =============================
|
8
13
|
|
9
14
|
def _project_root() -> Path:
|
10
|
-
"""
|
11
|
-
ریشه پروژه = پوشهای که main.py داخلش اجرا شده.
|
12
|
-
"""
|
15
|
+
"""ریشه پروژه = پوشهای که main.py داخلش اجرا شده. در صورت عدم دسترسی، از cwd استفاده میشود."""
|
13
16
|
try:
|
14
17
|
main_file = Path(sys.modules["__main__"].__file__).resolve()
|
15
18
|
return main_file.parent
|
16
19
|
except Exception:
|
17
|
-
# fallback: اگر به هر دلیل __main__.__file__ نبود
|
18
20
|
return Path(os.getcwd()).resolve()
|
19
21
|
|
20
|
-
|
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()
|
22
50
|
|
23
|
-
def
|
51
|
+
def load_admins() -> list[int]:
|
52
|
+
"""
|
53
|
+
بارگذاری لیست ادمینها از فایل.
|
54
|
+
همیشه OWNER_ID را هم به لیست اضافه میکند.
|
55
|
+
"""
|
56
|
+
logger.debug(f"Loading admins from file: {ADMINS_FILE} | OWNER_ID: {OWNER_ID}")
|
57
|
+
s = set(OWNER_ID)
|
24
58
|
try:
|
25
|
-
if
|
26
|
-
with
|
59
|
+
if os.path.exists(ADMINS_FILE):
|
60
|
+
with open(ADMINS_FILE, "r", encoding="utf-8") as f:
|
27
61
|
data = json.load(f)
|
62
|
+
logger.info(f"admins.json loaded. Raw: {data!r}")
|
28
63
|
if isinstance(data, list):
|
29
|
-
out = []
|
30
64
|
for v in data:
|
31
65
|
try:
|
32
|
-
|
33
|
-
except Exception:
|
34
|
-
logger.warning(f"
|
35
|
-
|
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)}")
|
36
71
|
except Exception as e:
|
37
|
-
logger.warning(f"Error loading admins
|
38
|
-
return []
|
72
|
+
logger.warning(f"Error loading admins: {e}", exc_info=True)
|
39
73
|
|
40
|
-
|
41
|
-
ADMINS
|
74
|
+
result = sorted(s)
|
75
|
+
logger.debug(f"Effective ADMINS after merge with OWNER_ID: {result}")
|
76
|
+
return result
|
42
77
|
|
43
|
-
def reload_admins():
|
44
|
-
"""فایل را میخواند و با OWNER_ID ادغام میکند؛ نتیجه در ADMINS."""
|
45
|
-
file_admins = _load_admins_from_file()
|
46
|
-
s = set(file_admins) | set(OWNER_ID)
|
47
|
-
global ADMINS
|
48
|
-
ADMINS = sorted(s)
|
49
|
-
logger.info(f"Loaded admins ({ADMINS_FILE}): {ADMINS}")
|
50
78
|
|
51
79
|
def save_admins():
|
52
80
|
"""
|
53
|
-
|
54
|
-
فقط ادمینهای غیر-Owner را داخل فایل نگه میداریم (Ownerها از config میآیند).
|
81
|
+
ذخیرهی ادمینها در فایل.
|
55
82
|
"""
|
56
83
|
try:
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
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)}")
|
61
89
|
except Exception as e:
|
62
|
-
logger.error(f"Error saving admins: {e}")
|
90
|
+
logger.error(f"Error saving admins: {e}", exc_info=True)
|
63
91
|
|
64
|
-
|
92
|
+
|
93
|
+
ADMINS = load_admins()
|
94
|
+
logger.info(f"Loaded admins at import time: {ADMINS}")
|
95
|
+
|
96
|
+
# فیلترهای دسترسی برای Pyrogram
|
65
97
|
admin_filter = filters.create(
|
66
98
|
lambda _, __, m: bool(getattr(m, "from_user", None)) and int(m.from_user.id) in ADMINS
|
67
99
|
)
|
@@ -69,57 +101,87 @@ owner_filter = filters.create(
|
|
69
101
|
lambda _, __, m: bool(getattr(m, "from_user", None)) and int(m.from_user.id) in OWNER_ID
|
70
102
|
)
|
71
103
|
|
72
|
-
#
|
104
|
+
# =============================
|
105
|
+
# فرمانهای مدیریتی
|
106
|
+
# =============================
|
107
|
+
|
73
108
|
async def add_admin_cmd(message):
|
74
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
|
+
|
75
113
|
parts = (message.text or "").split()
|
76
114
|
if len(parts) < 2:
|
77
|
-
|
115
|
+
logger.debug("add_admin_cmd: missing argument")
|
116
|
+
await message.reply("مثال: addadmin 123456789")
|
78
117
|
return
|
118
|
+
|
79
119
|
uid = int(parts[1])
|
120
|
+
logger.debug(f"add_admin_cmd: parsed target uid={uid}")
|
121
|
+
|
80
122
|
if uid in OWNER_ID:
|
123
|
+
logger.info(f"add_admin_cmd: uid={uid} is OWNER; skip append")
|
81
124
|
await message.reply("ادمین اصلی از قبل وجود دارد")
|
82
125
|
return
|
126
|
+
|
83
127
|
if uid not in ADMINS:
|
84
128
|
ADMINS.append(uid)
|
85
|
-
|
129
|
+
logger.info(f"Admin appended: {uid} | New ADMINS={sorted(ADMINS)}")
|
86
130
|
save_admins()
|
87
|
-
await message.reply(f"ادمین جدید اضافه شد:
|
88
|
-
logger.info(f"Admin added: {uid}")
|
131
|
+
await message.reply(f"ادمین جدید اضافه شد: {uid}")
|
89
132
|
else:
|
133
|
+
logger.info(f"add_admin_cmd: uid={uid} already in ADMINS")
|
90
134
|
await message.reply("قبلاً ادمین بود")
|
91
135
|
except Exception as e:
|
92
136
|
logger.error(f"add_admin_cmd error: {e}", exc_info=True)
|
93
137
|
await message.reply(f"خطا: {e}")
|
94
138
|
|
139
|
+
|
95
140
|
async def del_admin_cmd(message):
|
96
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
|
+
|
97
145
|
parts = (message.text or "").split()
|
98
146
|
if len(parts) < 2:
|
99
|
-
|
147
|
+
logger.debug("del_admin_cmd: missing argument")
|
148
|
+
await message.reply("مثال: deladmin 123456789")
|
100
149
|
return
|
150
|
+
|
101
151
|
uid = int(parts[1])
|
152
|
+
logger.debug(f"del_admin_cmd: parsed target uid={uid}")
|
153
|
+
|
102
154
|
if uid in OWNER_ID:
|
155
|
+
logger.info(f"del_admin_cmd: attempt to remove OWNER uid={uid} blocked")
|
103
156
|
await message.reply("❌ امکان حذف ادمین اصلی وجود ندارد")
|
104
157
|
return
|
158
|
+
|
105
159
|
if uid in ADMINS:
|
106
160
|
ADMINS.remove(uid)
|
161
|
+
logger.info(f"Admin removed: {uid} | New ADMINS={sorted(ADMINS)}")
|
107
162
|
save_admins()
|
108
|
-
await message.reply(f"ادمین حذف شد:
|
109
|
-
logger.info(f"Admin removed: {uid}")
|
163
|
+
await message.reply(f"ادمین حذف شد: {uid}")
|
110
164
|
else:
|
165
|
+
logger.info(f"del_admin_cmd: uid={uid} not in ADMINS")
|
111
166
|
await message.reply("کاربر ادمین نیست")
|
112
167
|
except Exception as e:
|
113
168
|
logger.error(f"del_admin_cmd error: {e}", exc_info=True)
|
114
169
|
await message.reply(f"خطا: {e}")
|
115
170
|
|
171
|
+
|
116
172
|
async def list_admins_cmd(message):
|
117
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
|
+
|
118
177
|
if not ADMINS:
|
178
|
+
logger.info("list_admins_cmd: ADMINS is empty")
|
119
179
|
await message.reply("لیست ادمینها خالی است.")
|
120
180
|
return
|
121
|
-
|
122
|
-
|
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)
|
123
185
|
except Exception as e:
|
124
186
|
logger.error(f"list_admins_cmd error: {e}", exc_info=True)
|
125
187
|
await message.reply(f"خطا: {e}")
|
File without changes
|
File without changes
|
File without changes
|