vault ключей + мост abuse-radar + китайские источники: всё в одном реестре
- omni/vault.py: пул ключей парсеров (env-first, data/vault.json, ротация, cooldown 401/402/403=1ч, 429=10м), только маски в выводе - tools/build_vault.py: сборка пула из MASTER_KEYS.csv и локальных дампов (значения не в git) - tools/vault_check.py: живая проверка с маскированием - searchers: firecrawl/tavily/exa/serper/jina/apify берут ключ из vault, если нет env - omni radar: домены+каналы из radar_server.db -> реестр, --import-posts заливает посты каналов - radar-источники помечены opt_in: общий обход не тормозят (869 против 3337 всего) - omni/sources_cn.py + tools/wave_cn.py: 9 живых китайских источников (52pojie, nodeseek, kanxue, anquanke, 4hou, xz.aliyun, ithome, cnbeta, v2ex) - net.get(proxy=...): принудительный прокси для CF-площадок - /api/keys + строка ключей в панели - tests/test_vault_radar.py: 7 тестов, всего 29 passed
This commit is contained in:
@@ -207,6 +207,58 @@ SOURCES = _dedup(SOURCES_BASE + [Source(**d) for d in EXTRA] + [Source(**d) for
|
||||
BY_NAME = {s.name: s for s in SOURCES}
|
||||
CATEGORIES = sorted({s.category for s in SOURCES})
|
||||
|
||||
_RADAR = {"at": 0.0, "rows": []}
|
||||
|
||||
|
||||
def radar_sources():
|
||||
"""Источники из abuse-radar: data/radar_sources.json (см. omni radar --apply).
|
||||
|
||||
Домены идут html_listing (root страница с маркерами), каналы — tg_web.
|
||||
Файл перечитывается при изменении mtime, реестр не разрастается дублями.
|
||||
"""
|
||||
import json
|
||||
from pathlib import Path
|
||||
p = Path(__file__).resolve().parents[1] / "data" / "radar_sources.json"
|
||||
try:
|
||||
mtime = p.stat().st_mtime
|
||||
except OSError:
|
||||
return []
|
||||
if _RADAR["rows"] and _RADAR["at"] == mtime:
|
||||
return _RADAR["rows"]
|
||||
rows = []
|
||||
try:
|
||||
d = json.loads(p.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
return []
|
||||
for item in d.get("domains") or []:
|
||||
dom, score, title = (list(item) + ["", 0, ""])[:3] if isinstance(item, list) else (item.get("domain"), item.get("score"), item.get("title"))
|
||||
name = "rad_" + str(dom).replace(".", "_").replace("-", "_")
|
||||
rows.append(Source(name=name, category="abuse", kind="site", url="https://" + str(dom),
|
||||
adapter="html_listing", tags=("radar", "abuse"),
|
||||
limit=12, detail=False, extra={"score": score, "title": (title or "")[:120], "opt_in": True}))
|
||||
for ch in d.get("channels") or []:
|
||||
name = "tg_" + str(ch).lstrip("@")
|
||||
rows.append(Source(name=name, category="abuse", kind="tg", url="https://t.me/" + str(ch).lstrip("@"),
|
||||
adapter="tg_web", tags=("tg", "abuse", "radar"), limit=25,
|
||||
detail=False, extra={"opt_in": True}))
|
||||
_RADAR.update(at=mtime, rows=rows)
|
||||
return rows
|
||||
|
||||
|
||||
def _cn_sources():
|
||||
"""Китайские/азиатские источники из сгенерированного omni/sources_cn.py."""
|
||||
try:
|
||||
from .sources_cn import CN
|
||||
except Exception:
|
||||
return []
|
||||
out = []
|
||||
for d in CN:
|
||||
try:
|
||||
out.append(Source(**d))
|
||||
except Exception:
|
||||
continue
|
||||
return out
|
||||
|
||||
|
||||
def all_sources():
|
||||
"""Реестр + пользовательские источники из панели, без дублей по url."""
|
||||
@@ -219,7 +271,7 @@ def all_sources():
|
||||
("name", "category", "kind", "url", "adapter", "tags", "limit", "detail", "extra")}
|
||||
extra.append(Source(**d))
|
||||
seen, out = set(), []
|
||||
for s in SOURCES + extra:
|
||||
for s in SOURCES + _cn_sources() + extra + radar_sources():
|
||||
key = (s.url or "").rstrip("/").lower()
|
||||
if key and key in seen:
|
||||
continue
|
||||
@@ -227,15 +279,27 @@ def all_sources():
|
||||
out.append(s)
|
||||
return out
|
||||
|
||||
def enabled_sources():
|
||||
"""Только включённые: выключенные в панели источники не дёргаем."""
|
||||
def enabled_sources(include_opt_in=False):
|
||||
"""Только включённые: выключенные в панели источники не дёргаем.
|
||||
|
||||
Источники из abuse-radar помечены extra["opt_in"] — их 2000+, в общий обход
|
||||
они не лезут; берутся только когда явно просят (--tags radar / --only / category abuse).
|
||||
"""
|
||||
from . import source_state
|
||||
fl = source_state.flags()
|
||||
return [s for s in all_sources() if fl.get(s.name, {}).get("enabled", True)]
|
||||
out = []
|
||||
for s in all_sources():
|
||||
if not fl.get(s.name, {}).get("enabled", True):
|
||||
continue
|
||||
if not include_opt_in and (s.extra or {}).get("opt_in"):
|
||||
continue
|
||||
out.append(s)
|
||||
return out
|
||||
|
||||
|
||||
def pick(category=None, only=None, tags=None, respect_enabled=True):
|
||||
out = enabled_sources() if respect_enabled else all_sources()
|
||||
explicit = bool(only or tags or category)
|
||||
out = enabled_sources(include_opt_in=explicit) if respect_enabled else all_sources()
|
||||
if category:
|
||||
cats = {c.strip() for c in category.split(",") if c.strip()}
|
||||
out = [s for s in out if s.category in cats]
|
||||
|
||||
Reference in New Issue
Block a user