CliRemote 1.8.0__tar.gz → 1.8.3__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.8.0 → cliremote-1.8.3}/CliRemote.egg-info/PKG-INFO +1 -1
- {cliremote-1.8.0 → cliremote-1.8.3}/PKG-INFO +1 -1
- {cliremote-1.8.0 → cliremote-1.8.3}/pyproject.toml +1 -1
- cliremote-1.8.3/remote/precise_engine.py +19 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/setup.py +1 -1
- cliremote-1.8.0/remote/precise_engine.py +0 -102
- {cliremote-1.8.0 → cliremote-1.8.3}/CliRemote.egg-info/SOURCES.txt +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/CliRemote.egg-info/dependency_links.txt +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/CliRemote.egg-info/requires.txt +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/CliRemote.egg-info/top_level.txt +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/LICENSE +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/MANIFEST.in +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/README.md +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/__init__.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/account_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/account_viewer.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/admin_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/analytics_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/batch_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/block_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/caption_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/cleaner.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/client_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/client_picker.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/config.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/device_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/file_sender.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/getcode_controller.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/health.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/help_menu.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/init.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/join_controller.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/joiner.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/leave_controller.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/lefter.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/mention_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/profile_info.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/profile_media.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/profile_privacy.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/spammer.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/speed_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/stop_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/text_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/username_manager.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/utils/__init__.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/remote/utils/sqlite_utils.py +0 -0
- {cliremote-1.8.0 → cliremote-1.8.3}/setup.cfg +0 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
# antispam_core/precise_engine.py
|
2
|
+
import asyncio, time
|
3
|
+
|
4
|
+
class PreciseTicker:
|
5
|
+
def __init__(self, interval: float):
|
6
|
+
self.interval = float(interval)
|
7
|
+
self.next_tick = time.perf_counter()
|
8
|
+
|
9
|
+
async def sleep(self):
|
10
|
+
"""خواب دقیق بدون drift در زمان"""
|
11
|
+
self.next_tick += self.interval
|
12
|
+
delay = self.next_tick - time.perf_counter()
|
13
|
+
if delay > 0:
|
14
|
+
await asyncio.sleep(delay)
|
15
|
+
else:
|
16
|
+
self.next_tick = time.perf_counter() # ریست در صورت عقب افتادن
|
17
|
+
|
18
|
+
def reset(self):
|
19
|
+
self.next_tick = time.perf_counter()
|
@@ -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.8.
|
8
|
+
version="1.8.3",
|
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,102 +0,0 @@
|
|
1
|
-
# antispam_core/precise_engine.py
|
2
|
-
import asyncio
|
3
|
-
import time
|
4
|
-
from dataclasses import dataclass
|
5
|
-
|
6
|
-
@dataclass
|
7
|
-
class TickerStats:
|
8
|
-
last_target_ns: int = 0
|
9
|
-
last_wakeup_ns: int = 0
|
10
|
-
last_jitter_ns: int = 0 # wakeup - target (>= 0)
|
11
|
-
|
12
|
-
class HiPrecisionTicker:
|
13
|
-
"""
|
14
|
-
Drift-free asyncio ticker with hybrid coarse-sleep + fine spin.
|
15
|
-
- Absolute scheduling: next_target = prev_target + period (no cumulative drift).
|
16
|
-
- Coarse sleep via asyncio, then busy-wait for final microseconds.
|
17
|
-
- Uses time.perf_counter_ns() (monotonic, high-resolution).
|
18
|
-
|
19
|
-
Notes:
|
20
|
-
* Sub-microsecond accuracy is NOT realistic on general OS with Python.
|
21
|
-
* 'spin' burns CPU on the running core; keep margins reasonable.
|
22
|
-
* Tune margins for your hardware/OS.
|
23
|
-
|
24
|
-
Args:
|
25
|
-
interval_sec: desired period in seconds (float).
|
26
|
-
sleep_margin_ns: if remaining > (sleep_margin + spin_margin), we await asyncio.sleep.
|
27
|
-
spin_margin_ns: final window to busy-wait (e.g., 50-200 µs).
|
28
|
-
|
29
|
-
Stats:
|
30
|
-
.stats.last_jitter_ns gives (actual_wakeup - scheduled_target) in ns.
|
31
|
-
"""
|
32
|
-
|
33
|
-
__slots__ = (
|
34
|
-
"period_ns", "sleep_margin_ns", "spin_margin_ns",
|
35
|
-
"next_target_ns", "stats"
|
36
|
-
)
|
37
|
-
|
38
|
-
def __init__(self,
|
39
|
-
interval_sec: float,
|
40
|
-
sleep_margin_ns: int = 200_000, # 200 µs
|
41
|
-
spin_margin_ns: int = 50_000): # 50 µs
|
42
|
-
if interval_sec <= 0:
|
43
|
-
raise ValueError("interval_sec must be > 0")
|
44
|
-
self.period_ns = int(interval_sec * 1e9)
|
45
|
-
if self.period_ns <= 1_000: # sanity: <1 µs period is nonsense for Python
|
46
|
-
raise ValueError("interval too small for Python environment")
|
47
|
-
if sleep_margin_ns < 0 or spin_margin_ns < 0:
|
48
|
-
raise ValueError("margins must be non-negative")
|
49
|
-
self.sleep_margin_ns = int(sleep_margin_ns)
|
50
|
-
self.spin_margin_ns = int(spin_margin_ns)
|
51
|
-
self.next_target_ns: int | None = None
|
52
|
-
self.stats = TickerStats()
|
53
|
-
|
54
|
-
async def sleep(self):
|
55
|
-
now = time.perf_counter_ns()
|
56
|
-
|
57
|
-
# First use: schedule at now + period (absolute target)
|
58
|
-
if self.next_target_ns is None:
|
59
|
-
self.next_target_ns = now + self.period_ns
|
60
|
-
|
61
|
-
remaining = self.next_target_ns - now
|
62
|
-
|
63
|
-
if remaining <= 0:
|
64
|
-
# We're already late: skip sleeping, jump target forward
|
65
|
-
# so we don't try to "catch up" with negative sleeps.
|
66
|
-
self.stats.last_target_ns = self.next_target_ns
|
67
|
-
self.stats.last_wakeup_ns = now
|
68
|
-
self.stats.last_jitter_ns = now - self.next_target_ns
|
69
|
-
self.next_target_ns = now + self.period_ns
|
70
|
-
return
|
71
|
-
|
72
|
-
# Coarse sleep: leave 'spin_margin_ns' to finish in busy-wait.
|
73
|
-
# Also keep a 'sleep_margin_ns' cushion to reduce overshoot risk.
|
74
|
-
coarse_threshold = self.sleep_margin_ns + self.spin_margin_ns
|
75
|
-
if remaining > coarse_threshold:
|
76
|
-
# target - spin_margin => leave that much for spinning
|
77
|
-
coarse_sleep_ns = remaining - self.spin_margin_ns
|
78
|
-
# asyncio.sleep takes seconds
|
79
|
-
await asyncio.sleep(coarse_sleep_ns / 1e9)
|
80
|
-
|
81
|
-
# Fine spin until target
|
82
|
-
target = self.next_target_ns
|
83
|
-
while True:
|
84
|
-
now = time.perf_counter_ns()
|
85
|
-
if now >= target:
|
86
|
-
break
|
87
|
-
# Tight spin: do nothing. If you see high CPU, you can insert
|
88
|
-
# a minimal pause on some platforms via time.sleep(0) sporadically,
|
89
|
-
# but that will hurt accuracy.
|
90
|
-
|
91
|
-
# Record stats
|
92
|
-
self.stats.last_target_ns = target
|
93
|
-
self.stats.last_wakeup_ns = now
|
94
|
-
self.stats.last_jitter_ns = now - target # >= 0
|
95
|
-
|
96
|
-
# Advance absolute target by exactly one period (no drift accumulation)
|
97
|
-
self.next_target_ns = target + self.period_ns
|
98
|
-
|
99
|
-
def reset(self):
|
100
|
-
"""Reset baseline; next sleep schedules from current time + period."""
|
101
|
-
self.next_target_ns = None
|
102
|
-
self.stats = TickerStats()
|
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
|