| Server IP : 157.230.181.24 / Your IP : 216.73.217.11 Web Server : Apache/2.4.58 (Ubuntu) System : Linux conductive 6.8.0-117-generic #117-Ubuntu SMP PREEMPT_DYNAMIC Tue May 5 19:26:24 UTC 2026 x86_64 User : ( 1000) PHP Version : 8.3.31 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /opt/aim-bots/ |
Upload File : |
"""Sample realistic AIM delays from archive timing profiles."""
from __future__ import annotations
import os
import random
def _timing_scale() -> float:
try:
return max(0.25, min(1.0, float(os.environ.get("TIMING_SCALE", "0.55"))))
except ValueError:
return 0.55
class TimingSampler:
def __init__(self, profile: dict | None) -> None:
self.profile = profile or {}
self.scale = _timing_scale()
def _pick(self, samples: list[float], fallback: tuple[float, float]) -> float:
if samples:
return random.choice(samples)
return random.uniform(*fallback)
def reply_delay(self, mode: str, incoming_len: int = 0, afk: bool = False) -> float:
p = self.profile
extra = min(2.0, incoming_len * 0.006)
if afk:
lo = float(p.get("reply_p75_sec") or 60)
hi = float(p.get("reply_p95_sec") or 120)
return min(
(random.uniform(lo, hi) + extra * 0.05) * self.scale,
float(p.get("afk_reply_cap_sec") or 20) * self.scale,
)
if mode == "hot":
samples = p.get("hot_reply_samples") or p.get("reply_samples") or []
base = self._pick(samples, (1.5, 5.0))
cap = float(p.get("hot_reply_cap_sec") or 6.0)
floor = float(p.get("hot_reply_floor_sec") or 1.0)
return max(floor, min(base * random.uniform(0.85, 1.1), cap)) * self.scale + extra * 0.05
if mode == "warm":
med = float(p.get("warm_median_sec") or p.get("reply_median_sec") or 12)
cap = float(p.get("warm_reply_cap_sec") or 10.0)
floor = float(p.get("warm_reply_floor_sec") or 2.0)
return min(
max(floor, random.uniform(max(2.0, med * 0.25), med * 0.85) + extra * 0.08),
cap,
) * self.scale
# cold — still responsive, just a touch slower
cap = float(p.get("cold_reply_cap_sec") or 12.0)
floor = float(p.get("cold_reply_floor_sec") or 2.0)
samples = p.get("reply_samples") or []
if samples:
base = self._pick(samples, (4.0, 12.0))
return min(max(floor, base * random.uniform(0.5, 0.85)), cap) * self.scale
lo = min(float(p.get("reply_target_min_sec") or 2), 4.0)
hi = min(float(p.get("reply_target_max_sec") or 8), 12.0)
return (random.uniform(lo, hi) + extra * 0.05) * self.scale
def burst_gap(self, mode: str, msg_index: int = 0) -> float:
p = self.profile
samples = p.get("burst_gap_samples") or []
med = float(p.get("burst_median_sec") or 3.0)
p90 = float(p.get("burst_p90_sec") or 8.0)
if msg_index == 0:
return 0.0
if samples:
base = self._pick(samples, (1.0, p90))
elif mode == "hot":
base = random.uniform(0.5, min(4.0, med * 1.2))
else:
base = random.uniform(max(1.0, med * 0.5), p90)
jitter = random.uniform(0.85, 1.15)
return max(0.25, min(base * jitter, 20.0)) * self.scale
def typing_delay(self, text: str, mode: str, wpm_min: int, wpm_max: int) -> float:
wpm = random.uniform(wpm_min, wpm_max)
if mode == "hot":
wpm *= random.uniform(1.1, 1.35)
elif mode == "cold":
wpm *= random.uniform(0.6, 0.9)
cps = (wpm / 60.0) * 5.0
delay = len(text) / max(cps, 1.0)
if mode == "hot":
lo, hi = 0.1, 1.8
elif mode == "warm":
lo, hi = 0.25, 5.0
else:
lo, hi = 0.4, 6.0
return (max(lo, min(hi, delay)) + random.uniform(0.02, 0.12)) * self.scale
def should_hesitate(self, mode: str) -> bool:
rate = float(self.profile.get("hesitation_rate") or 0.08)
if mode == "hot":
return random.random() < rate * 0.25
if mode == "warm":
return random.random() < rate * 0.6
return random.random() < rate
def hesitation_filler(self) -> str:
pool = (
"...",
"uh",
"uhh",
"haha",
"lol",
"umm",
"wait",
"hm",
"idk",
)
return random.choice(pool)