ravisremotet 2.0__tar.gz → 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.
Files changed (88) hide show
  1. {ravisremotet-2.0/ravisremotet.egg-info → ravisremotet-2.2}/PKG-INFO +1 -1
  2. {ravisremotet-2.0 → ravisremotet-2.2}/handlers/core_handler.py +1 -86
  3. ravisremotet-2.2/moudels/core/status_panel.py +202 -0
  4. {ravisremotet-2.0 → ravisremotet-2.2}/pyproject.toml +1 -1
  5. {ravisremotet-2.0 → ravisremotet-2.2/ravisremotet.egg-info}/PKG-INFO +1 -1
  6. {ravisremotet-2.0 → ravisremotet-2.2}/setup.py +1 -1
  7. ravisremotet-2.0/moudels/core/status_panel.py +0 -82
  8. {ravisremotet-2.0 → ravisremotet-2.2}/LICENSE +0 -0
  9. {ravisremotet-2.0 → ravisremotet-2.2}/MANIFEST.in +0 -0
  10. {ravisremotet-2.0 → ravisremotet-2.2}/README.md +0 -0
  11. {ravisremotet-2.0 → ravisremotet-2.2}/handlers/__init__.py +0 -0
  12. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/__init__.py +0 -0
  13. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/__init__.py +0 -0
  14. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/account_manager.py +0 -0
  15. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/account_viewer.py +0 -0
  16. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/cleaner.py +0 -0
  17. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/client/__init__.py +0 -0
  18. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/client/client_manager.py +0 -0
  19. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/client/flood_guard.py +0 -0
  20. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/client/online_client.py +0 -0
  21. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/client/status_report.py +0 -0
  22. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/client/test.py +0 -0
  23. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/device/__init__.py +0 -0
  24. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/device/device_manager.py +0 -0
  25. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/profile/__init__.py +0 -0
  26. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/profile/profile_info.py +0 -0
  27. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/profile/profile_media.py +0 -0
  28. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/profile/profile_privacy.py +0 -0
  29. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/account/profile/username_manager.py +0 -0
  30. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/admin/__init__.py +0 -0
  31. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/admin/admin_manager.py +0 -0
  32. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/analytics/__init__.py +0 -0
  33. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/analytics/analytics_manager.py +0 -0
  34. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/batch/__init__.py +0 -0
  35. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/batch/batch_manager.py +0 -0
  36. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/batch/batch_scheduler.py +0 -0
  37. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/batch/message_shift.py +0 -0
  38. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/batch/shift_scheduler.py +0 -0
  39. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/core/__init__.py +0 -0
  40. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/core/config.py +0 -0
  41. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/core/getcode_controller.py +0 -0
  42. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/core/help_menu.py +0 -0
  43. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/core/human_behavior.py +0 -0
  44. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/core/menu_state.py +0 -0
  45. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/core/precise_engine.py +0 -0
  46. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/core/response_manager.py +0 -0
  47. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/core/restart_module.py +0 -0
  48. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/core/typing_indicator.py +0 -0
  49. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/db/__init__.py +0 -0
  50. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/db/db_monitor.py +0 -0
  51. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/db/sqlite_utils.py +0 -0
  52. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/forward/__init__.py +0 -0
  53. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/forward/forward_commands.py +0 -0
  54. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/forward/forwarder.py +0 -0
  55. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/forward/speed_for_manager.py +0 -0
  56. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/forward/stop_manager.py +0 -0
  57. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/group/__init__.py +0 -0
  58. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/group/join_controller.py +0 -0
  59. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/group/joiner.py +0 -0
  60. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/group/leave_controller.py +0 -0
  61. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/group/lefter.py +0 -0
  62. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/__init__.py +0 -0
  63. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/actions.py +0 -0
  64. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/backup_legacy_inline/button_actions.py +0 -0
  65. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/backup_legacy_inline/keyboards.py +0 -0
  66. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/callback_router.py +0 -0
  67. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/keyboards.py +0 -0
  68. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/output_view.py +0 -0
  69. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/proxy_message.py +0 -0
  70. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/register.py +0 -0
  71. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/schema.py +0 -0
  72. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/state_catchers.py +0 -0
  73. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/menu/state_manager.py +0 -0
  74. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/text/__init__.py +0 -0
  75. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/text/caption_manager.py +0 -0
  76. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/text/finaly_text.py +0 -0
  77. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/text/mention_manager.py +0 -0
  78. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/text/text_manager.py +0 -0
  79. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/utils/__init__.py +0 -0
  80. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/utils/block_manager.py +0 -0
  81. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/utils/file_sender.py +0 -0
  82. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/utils/health.py +0 -0
  83. {ravisremotet-2.0 → ravisremotet-2.2}/moudels/utils/humanize.py +0 -0
  84. {ravisremotet-2.0 → ravisremotet-2.2}/ravisremotet.egg-info/SOURCES.txt +0 -0
  85. {ravisremotet-2.0 → ravisremotet-2.2}/ravisremotet.egg-info/dependency_links.txt +0 -0
  86. {ravisremotet-2.0 → ravisremotet-2.2}/ravisremotet.egg-info/requires.txt +0 -0
  87. {ravisremotet-2.0 → ravisremotet-2.2}/ravisremotet.egg-info/top_level.txt +0 -0
  88. {ravisremotet-2.0 → ravisremotet-2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ravisremotet
3
- Version: 2.0
3
+ Version: 2.2
4
4
  Summary: Remote client framework for Telegram automation using Pyrogram
5
5
  Home-page: https://github.com/MohammadAhmadi-R/ravisremote
6
6
  Author: MrAhmadiRad
@@ -9,8 +9,7 @@ from moudels.analytics import (analytics_manager)
9
9
  from moudels.batch import (batch_manager)
10
10
  from moudels.core import (config,restart_module,getcode_controller,help_menu,status_panel)
11
11
  from moudels.db import (db_monitor)
12
- from moudels.group import (join_controller,leave_controller)
13
- from moudels.text import (caption_manager,mention_manager,text_manager)
12
+ from moudels.group import (join_controller,leave_controller)
14
13
  from moudels.utils import (block_manager,file_sender)
15
14
  from moudels.menu.register import register_menu
16
15
  from moudels.forward import (speed_for_manager,forward_commands)
@@ -90,90 +89,6 @@ def register_commands(app):
90
89
  @app.on_message(filters.command("delalldevices", "") & admin_filter)
91
90
  async def kill_other_sessions(client, message):
92
91
  await device_manager.terminate_all_other_sessions_cmd(message)
93
-
94
-
95
-
96
- #TEXT
97
- @app.on_message(filters.command('text', prefixes=["/", ""]) & admin_filter)
98
- async def save_text(client, message):
99
- await text_manager.save_text_cmd(message)
100
-
101
- @app.on_message(filters.command('ctext', prefixes=["/", ""]) & admin_filter)
102
- async def clear_texts(client, message):
103
- await text_manager.clear_texts_cmd(message)
104
-
105
- @app.on_message(filters.command('shtext', prefixes=["/", ""]) & admin_filter)
106
- async def show_text(client, message):
107
- await text_manager.show_texts_cmd(message)
108
-
109
- @app.on_message(filters.command('shcap', prefixes=["/", ""]) & admin_filter)
110
- async def show_caption(client, message):
111
- await caption_manager.show_caption_cmd(message, config.spam_config)
112
-
113
- @app.on_message(filters.command('cap', prefixes=["/", ""]) & admin_filter)
114
- async def add_caption(client, message):
115
- await caption_manager.add_caption_cmd(message, config.spam_config)
116
-
117
- @app.on_message(filters.command('ccap', prefixes=["/", ""]) & admin_filter)
118
- async def clear_caption(client, message):
119
- await caption_manager.clear_caption_cmd(message, config.spam_config)
120
-
121
- @app.on_message(admin_filter & filters.command("textmention", prefixes=["/", ""]))
122
- async def _setmention(client, m: Message):
123
- txt = m.text.split(None, 1)[1] if (m.text and len(m.command) > 1) else ""
124
- await m.reply(await mention_manager.set_mention_text(txt))
125
-
126
- @app.on_message(admin_filter & filters.command("mention_user", prefixes=["/", ""]))
127
- async def _mention_user(client, m: Message):
128
- user = m.command[1]
129
- await m.reply(await mention_manager.set_mention_user(user))
130
-
131
- @app.on_message(admin_filter & filters.command("mention_toggle", prefixes=["/", ""]))
132
- async def _mention_toggle(client, m: Message):
133
- if len(m.command) < 2:
134
- return await m.reply("Usage: /mention_toggle <on|off>")
135
- enable = (m.command[1].lower() == "on")
136
- await m.reply(await mention_manager.toggle_mention(enable))
137
-
138
- @app.on_message(admin_filter & filters.command("mention_group_toggle", prefixes=["/", ""]))
139
- async def _mention_group_toggle(client, m: Message):
140
- if len(m.command) < 2:
141
- return await m.reply("Usage: /mention_group_toggle <on|off>")
142
- enable = (m.command[1].lower() == "on")
143
- await m.reply(await mention_manager.toggle_group_mention(enable))
144
-
145
- @app.on_message(admin_filter & filters.command("mention_gps", prefixes=["/", ""]))
146
- async def _mention_gps(client, m: Message):
147
- if not (m.text and len(m.command) > 1):
148
- return await m.reply("Usage: /mention_gps <id1> <id2> ...")
149
- tokens = m.command[1:]
150
- ids = await mention_manager._resolve_many_tokens_to_ids(client, tokens)
151
- if not ids:
152
- return await m.reply("❌ هیچ شناسهٔ معتبری تشخیص داده نشد.")
153
- msg = await mention_manager.add_groups_by_ids(*ids)
154
- await m.reply(msg)
155
-
156
- await m.reply(msg)
157
-
158
- @app.on_message(admin_filter & filters.command("mention_del", prefixes=["/", ""]))
159
- async def _mention_del(client, m: Message):
160
- if not (m.text and len(m.command) > 1):
161
- return await m.reply("Usage: /mention_del <id1> <id2> ...")
162
- tokens = m.command[1:]
163
- ids = await mention_manager._resolve_many_tokens_to_ids(client, tokens)
164
- if not ids:
165
- return await m.reply("❌ هیچ شناسهٔ معتبری برای حذف تشخیص داده نشد.")
166
- msg = await mention_manager.remove_groups_by_ids(*ids)
167
- await m.reply(msg)
168
-
169
- @app.on_message(admin_filter & filters.command("mention_clear", prefixes=["/", ""]))
170
- async def _mention_clear(client, m: Message):
171
- await m.reply(await mention_manager.clear_groups())
172
-
173
- @app.on_message(admin_filter & filters.command("mention_status", prefixes=["/", ""]))
174
- async def _mention_status(client, m: Message):
175
- await m.reply(await mention_manager.mention_status())
176
-
177
92
 
178
93
  #MORE
179
94
  @app.on_message(filters.command('gcode', '') & admin_filter)
@@ -0,0 +1,202 @@
1
+ # remote/moudels/core/status_panel.py
2
+ """
3
+ 📊 پنل وضعیت بات — نمایش دقیق آپ‌تایم، پینگ، مصرف رم (فعلی و سقف مصرف)، CPU و وضعیت اکانت‌ها.
4
+ سازگار با لینوکس (هاست cPanel) و ویندوز بدون نیاز اجباری به پکیج‌های خارجی.
5
+ """
6
+
7
+ import os
8
+ import time
9
+ import asyncio
10
+ import logging
11
+ from typing import Tuple
12
+
13
+ from ..account.client.client_manager import accounts, client_pool
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+ START_TIME = time.time()
18
+ _LAST_CPU_CHECK_WALL = time.perf_counter()
19
+ _LAST_CPU_CHECK_PROC = time.process_time()
20
+ _PEAK_RAM_MB = 0.0
21
+
22
+
23
+ def _format_uptime(seconds: float) -> str:
24
+ m, s = divmod(int(seconds), 60)
25
+ h, m = divmod(m, 60)
26
+ d, h = divmod(h, 24)
27
+ if d:
28
+ return f"{d}d {h}h {m}m"
29
+ if h:
30
+ return f"{h}h {m}m"
31
+ return f"{m}m {s}s"
32
+
33
+
34
+ def _get_memory_usage_mb() -> Tuple[float, float]:
35
+ """
36
+ برمی‌گرداند: (رم فعلی به مگابایت, بیشترین رم ثبت‌شده به مگابایت)
37
+ ابتدا از هسته لینوکس (/proc/self/status) یا psutil و در ویندوز از ctypes می‌خواند.
38
+ """
39
+ global _PEAK_RAM_MB
40
+ current_mb = 0.0
41
+ peak_mb = 0.0
42
+
43
+ # ۱) خواندن مستقیم و فوق‌سبک از کرنل لینوکس (cPanel)
44
+ if os.path.exists("/proc/self/status"):
45
+ try:
46
+ with open("/proc/self/status", "r", encoding="utf-8") as f:
47
+ for line in f:
48
+ if line.startswith("VmRSS:"):
49
+ current_mb = int(line.split()[1]) / 1024.0
50
+ elif line.startswith("VmHWM:"):
51
+ peak_mb = int(line.split()[1]) / 1024.0
52
+ except Exception:
53
+ pass
54
+
55
+ # ۲) استفاده از psutil در صورت موجود بودن و عدم استخراج در مرحله قبل
56
+ if current_mb <= 0.0:
57
+ try:
58
+ import psutil
59
+ proc = psutil.Process(os.getpid())
60
+ mem = proc.memory_info()
61
+ current_mb = mem.rss / (1024.0 * 1024.0)
62
+ peak_mb = getattr(mem, "peak_wset", 0) / (1024.0 * 1024.0)
63
+ except Exception:
64
+ pass
65
+
66
+ # ۳) پشتیبانی بومی از ویندوز (بدون نیاز به psutil)
67
+ if current_mb <= 0.0 and os.name == "nt":
68
+ try:
69
+ import ctypes
70
+ from ctypes import wintypes
71
+
72
+ class PROCESS_MEMORY_COUNTERS(ctypes.Structure):
73
+ _fields_ = [
74
+ ("cb", wintypes.DWORD),
75
+ ("PageFaultCount", wintypes.DWORD),
76
+ ("PeakWorkingSetSize", ctypes.c_size_t),
77
+ ("WorkingSetSize", ctypes.c_size_t),
78
+ ("QuotaPeakPagedPoolUsage", ctypes.c_size_t),
79
+ ("QuotaPagedPoolUsage", ctypes.c_size_t),
80
+ ("QuotaPeakNonPagedPoolUsage", ctypes.c_size_t),
81
+ ("QuotaNonPagedPoolUsage", ctypes.c_size_t),
82
+ ("PagefileUsage", ctypes.c_size_t),
83
+ ("PeakPagefileUsage", ctypes.c_size_t),
84
+ ]
85
+
86
+ pmc = PROCESS_MEMORY_COUNTERS()
87
+ pmc.cb = ctypes.sizeof(PROCESS_MEMORY_COUNTERS)
88
+ handle = ctypes.windll.kernel32.GetCurrentProcess()
89
+ if ctypes.windll.psapi.GetProcessMemoryInfo(handle, ctypes.byref(pmc), pmc.cb):
90
+ current_mb = pmc.WorkingSetSize / (1024.0 * 1024.0)
91
+ peak_mb = pmc.PeakWorkingSetSize / (1024.0 * 1024.0)
92
+ except Exception:
93
+ pass
94
+
95
+ if current_mb > _PEAK_RAM_MB:
96
+ _PEAK_RAM_MB = current_mb
97
+ if peak_mb > _PEAK_RAM_MB:
98
+ _PEAK_RAM_MB = peak_mb
99
+
100
+ return round(current_mb, 2), round(_PEAK_RAM_MB, 2)
101
+
102
+
103
+ async def _measure_ping_and_cpu(app) -> Tuple[int, float, float]:
104
+ """
105
+ همزمان با گرفتن پینگ تلگرام، درصد مصرف لحظه‌ای و میانگین CPU پروسه را محاسبه می‌کند.
106
+ برمی‌گرداند: (پینگ به میلی‌ثانیه, مصرف لحظه‌ای CPU, میانگین مصرف CPU)
107
+ """
108
+ global _LAST_CPU_CHECK_WALL, _LAST_CPU_CHECK_PROC
109
+
110
+ w_start = time.perf_counter()
111
+ p_start = time.process_time()
112
+
113
+ ping_ms = -1
114
+ t0 = time.perf_counter()
115
+ try:
116
+ await app.get_me()
117
+ ping_ms = int((time.perf_counter() - t0) * 1000)
118
+ except Exception:
119
+ ping_ms = -1
120
+
121
+ # اگر پینگ خیلی سریع بود، یک مکث کوتاه می‌کنیم تا نمونه CPU دقیق باشد
122
+ elapsed_wall = time.perf_counter() - w_start
123
+ if elapsed_wall < 0.12:
124
+ await asyncio.sleep(0.12 - elapsed_wall)
125
+
126
+ w_now = time.perf_counter()
127
+ p_now = time.process_time()
128
+
129
+ # مصرف لحظه‌ای در بازه نمونه‌گیری
130
+ inst_wall = max(0.001, w_now - w_start)
131
+ inst_cpu = ((p_now - p_start) / inst_wall) * 100.0
132
+
133
+ # میانگین مصرف از آخرین بازدید پنل وضعیت
134
+ delta_wall = w_now - _LAST_CPU_CHECK_WALL
135
+ if delta_wall >= 1.0:
136
+ avg_recent_cpu = ((p_now - _LAST_CPU_CHECK_PROC) / delta_wall) * 100.0
137
+ else:
138
+ avg_recent_cpu = inst_cpu
139
+
140
+ _LAST_CPU_CHECK_WALL = w_now
141
+ _LAST_CPU_CHECK_PROC = p_now
142
+
143
+ return ping_ms, round(min(100.0, max(0.0, inst_cpu)), 1), round(min(100.0, max(0.0, avg_recent_cpu)), 1)
144
+
145
+
146
+ def _active_coroutines() -> int:
147
+ try:
148
+ return len(asyncio.all_tasks())
149
+ except Exception:
150
+ return -1
151
+
152
+
153
+ def _connected_clients_count() -> int:
154
+ try:
155
+ return sum(1 for cli in client_pool.values() if cli and getattr(cli, "is_connected", False))
156
+ except Exception:
157
+ return 0
158
+
159
+
160
+ def _account_status_text() -> str:
161
+ try:
162
+ from ..account.client import flood_guard
163
+ values = flood_guard.statuses()
164
+ if not values:
165
+ return "وضعیت اکانت‌ها: فعال"
166
+ counts = {}
167
+ for value in values.values():
168
+ counts[value] = counts.get(value, 0) + 1
169
+ return "وضعیت اکانت‌ها: " + " | ".join(f"{k}: {v}" for k, v in sorted(counts.items()))
170
+ except Exception:
171
+ return "وضعیت اکانت‌ها: نامشخص"
172
+
173
+
174
+ async def show_status(app, message) -> None:
175
+ """نمایش کامل وضعیت ربات شامل رم، CPU، پینگ و سشن‌ها."""
176
+ try:
177
+ uptime = _format_uptime(time.time() - START_TIME)
178
+ ping, cpu_now, cpu_avg = await _measure_ping_and_cpu(app)
179
+ ram_now, ram_peak = _get_memory_usage_mb()
180
+
181
+ ping_txt = f"{ping} ms" if ping != -1 else "Failed"
182
+ acc_count = len(accounts())
183
+ connected_count = _connected_clients_count()
184
+ coro_count = _active_coroutines()
185
+
186
+ from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
187
+ await message.reply(
188
+ " <b>وضعیت بات و منابع سرور</b>\n"
189
+ "┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈\n"
190
+ f" آپ‌تایم: <code>{uptime}</code>\n"
191
+ f" رم فعلی: <code>{ram_now:.2f} MB</code> (سقف: <code>{ram_peak:.2f} MB</code>)\n"
192
+ f" مصرف CPU: <code>{cpu_now:.1f}%</code> (میانگین: <code>{cpu_avg:.1f}%</code>)\n"
193
+ f" اکانت‌ها: <code>{acc_count}</code> (متصل در رم: <code>{connected_count}</code>)\n"
194
+ f" تسک‌های فعال (Coroutines): <code>{coro_count}</code>\n"
195
+ f" پینگ تلگرام: <code>{ping_txt}</code>\n"
196
+ f" {_account_status_text()}",
197
+ reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("🔄 رفرش", callback_data="act:sysstatus")]]),
198
+ )
199
+
200
+ except Exception as e:
201
+ logger.exception(f"show_status error: {e}")
202
+ await message.reply(f"💥 خطا در نمایش وضعیت بات: {e}")
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ravisremotet"
7
- version = "2.0"
7
+ version = "2.2"
8
8
  description = "Remote client framework for Telegram automation using Pyrogram"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ravisremotet
3
- Version: 2.0
3
+ Version: 2.2
4
4
  Summary: Remote client framework for Telegram automation using Pyrogram
5
5
  Home-page: https://github.com/MohammadAhmadi-R/ravisremote
6
6
  Author: MrAhmadiRad
@@ -5,7 +5,7 @@ with open("README.md", encoding="utf-8") as f:
5
5
 
6
6
  setup(
7
7
  name="ravisremotet",
8
- version="2.0",
8
+ version="2.2",
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,82 +0,0 @@
1
- # remote/moudels/core/status_panel.py
2
- """
3
- 📊 پنل وضعیت بات — نسخه‌ی ساده‌ی متنی (بدون matplotlib/نمودار/CPU/RAM طبق درخواست).
4
-
5
- فقط: آپ‌تایم + پینگ تلگرام + تعداد اکانت‌ها + تعداد coroutine های فعال.
6
- یک پیام متنی ساده با دکمه‌ی 🔄 رفرش.
7
- """
8
-
9
- import time
10
- import asyncio
11
- import logging
12
-
13
- from ..account.client.client_manager import accounts
14
-
15
- logger = logging.getLogger(__name__)
16
-
17
- START_TIME = time.time()
18
-
19
-
20
- def _format_uptime(seconds: float) -> str:
21
- m, s = divmod(int(seconds), 60)
22
- h, m = divmod(m, 60)
23
- d, h = divmod(h, 24)
24
- if d:
25
- return f"{d}d {h}h {m}m"
26
- if h:
27
- return f"{h}h {m}m"
28
- return f"{m}m {s}s"
29
-
30
-
31
- def _active_coroutines() -> int:
32
- try:
33
- return len(asyncio.all_tasks())
34
- except Exception:
35
- return -1
36
-
37
- def _account_status_text() -> str:
38
- try:
39
- from ..account.client import flood_guard
40
- values = flood_guard.statuses()
41
- if not values:
42
- return "وضعیت اکانت‌ها: فعال"
43
- counts = {}
44
- for value in values.values(): counts[value] = counts.get(value, 0) + 1
45
- return "وضعیت اکانت‌ها: " + " | ".join(f"{k}: {v}" for k, v in sorted(counts.items()))
46
- except Exception:
47
- return "وضعیت اکانت‌ها: نامشخص"
48
-
49
-
50
- async def _telegram_ping(app) -> int:
51
- start = time.time()
52
- try:
53
- await app.get_me()
54
- return int((time.time() - start) * 1000)
55
- except Exception:
56
- return -1
57
-
58
-
59
- async def show_status(app, message) -> None:
60
- """اجرای اصلی: یک پیام متنی با آمار وضعیت بات می‌فرسته."""
61
- try:
62
- uptime = _format_uptime(time.time() - START_TIME)
63
- ping = await _telegram_ping(app)
64
- ping_txt = f"{ping} ms" if ping != -1 else "Failed"
65
- acc_count = len(accounts())
66
- coro_count = _active_coroutines()
67
-
68
- from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
69
- await message.reply(
70
- "📊 <b>وضعیت بات</b>\n"
71
- "┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈\n"
72
- f"⏱ آپ‌تایم: <code>{uptime}</code>\n"
73
- f"👥 اکانت‌ها: <code>{acc_count}</code>\n"
74
- f"🧵 Coroutine های فعال: <code>{coro_count}</code>\n"
75
- f"📡 پینگ تلگرام: <code>{ping_txt}</code>\n"
76
- f"🛡 {_account_status_text()}",
77
- reply_markup=InlineKeyboardMarkup([[InlineKeyboardButton("رفرش", callback_data="act:sysstatus")]]),
78
- )
79
-
80
- except Exception as e:
81
- logger.exception(f"show_status error: {e}")
82
- await message.reply(f"💥 خطا در نمایش وضعیت بات: {e}")
File without changes
File without changes
File without changes
File without changes