Files
universal-autoreg/lib/bank.py

86 lines
2.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""bank.py — единый банк аккаунтов (JSONL).
Каждый провайдер пишет сюда: {"provider","email","password","token","extra",...,"ts"}
Дедуп по (provider, email). Статистика по провайдерам.
"""
import json, os, time, threading
BANK_FILE = os.environ.get("UA_BANK", os.path.join(os.path.dirname(__file__), "..", "data", "bank.jsonl"))
_lock = threading.Lock()
_seen_cache = None # PERF: (mtime, size, set) — дедуп O(1) вместо re-read всего банка на каждый add()
def _path():
p = os.path.abspath(BANK_FILE)
os.makedirs(os.path.dirname(p), exist_ok=True)
return p
def _seen_set():
"""Кэш ключей (provider,email); инвалидация по mtime+size (внешние писатели)."""
global _seen_cache
p = _path()
if not os.path.exists(p):
_seen_cache = (0, 0, set())
return _seen_cache[2]
stt = os.stat(p)
if _seen_cache is None or _seen_cache[0] != stt.st_mtime or _seen_cache[1] != stt.st_size:
keys = {(r.get("provider"), r.get("email")) for r in load()}
_seen_cache = (stt.st_mtime, stt.st_size, keys)
return _seen_cache[2]
def add(record: dict) -> bool:
"""Добавить аккаунт. False если дубль (provider,email)."""
global _seen_cache
rec = dict(record)
rec.setdefault("ts", int(time.time()))
with _lock:
seen = _seen_set()
key = (rec.get("provider"), rec.get("email"))
if key in seen:
return False
with open(_path(), "a", encoding="utf-8") as f:
f.write(json.dumps(rec, ensure_ascii=False) + "\n")
seen.add(key)
# держим set горячим, stat — свежий (иначе следующий add перечитал бы файл)
stt = os.stat(_path())
_seen_cache = (stt.st_mtime, stt.st_size, seen)
return True
def load():
p = _path()
if not os.path.exists(p):
return []
out = []
with open(p, encoding="utf-8") as f:
for line in f:
line = line.strip()
if line:
try:
out.append(json.loads(line))
except json.JSONDecodeError:
continue
return out
def stats():
per = {}
for r in load():
p = r.get("provider", "?")
per.setdefault(p, {"total": 0, "with_token": 0})
per[p]["total"] += 1
if r.get("token") or r.get("api_key"):
per[p]["with_token"] += 1
return per
if __name__ == "__main__":
import sys
s = stats()
total = sum(v["total"] for v in s.values())
print(f"BANK {total} аккаунтов, {len(s)} провайдеров")
for p, v in sorted(s.items(), key=lambda x: -x[1]["total"]):
print(f" {p}: {v['total']} (с токеном: {v['with_token']})")