abuse: строгий free_count (prompt и completion = 0) — 90 панелей вместо 131; sync_panel_items держит тексты панелей в актуальном виде; push_top отправляет топ находок в бота
This commit is contained in:
@@ -10,6 +10,7 @@ import argparse
|
||||
import html
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sqlite3
|
||||
import sys
|
||||
import urllib.parse
|
||||
@@ -24,7 +25,50 @@ from omni import abuse # noqa: E402
|
||||
TAG_RU = {"promo": "промо", "trial": "триал", "keys": "ключи", "leak": "слив",
|
||||
"resale": "перепродажа", "accs": "аккаунты", "credits": "кредиты",
|
||||
"invite": "инвайты", "ltd": "lifetime", "freeapi": "free-API",
|
||||
"combo": "комбо", "tool": "тулза"}
|
||||
"combo": "комбо", "tool": "тулза", "coupon": "купон", "nokyc": "без KYC",
|
||||
"api": "API", "sub": "подписка", "unlimited": "безлимит", "referral": "реф"}
|
||||
|
||||
|
||||
NOISE = ("навигация по каналу", "навигация", "закреп", "правила канала", "прайс-лист",
|
||||
"реклама в канале", "меню канала", "список каналов")
|
||||
EMOJI = re.compile("[🀀-☀-➿⬀-⯿️
]")
|
||||
|
||||
|
||||
def clean(txt: str, n: int = 110) -> str:
|
||||
txt = EMOJI.sub(" ", txt or "")
|
||||
txt = re.sub(r"\s+", " ", txt).strip()
|
||||
if len(txt) <= n:
|
||||
return txt
|
||||
cut = txt[:n]
|
||||
if " " in cut[40:]:
|
||||
cut = cut[:cut.rfind(" ")]
|
||||
return cut.rstrip(" ,.;:-") + "…"
|
||||
|
||||
|
||||
def is_noise(title: str) -> bool:
|
||||
low = (title or "").lower()
|
||||
return any(k in low for k in NOISE)
|
||||
|
||||
|
||||
def panel_block(limit: int = 4) -> list[str]:
|
||||
import json
|
||||
from pathlib import Path
|
||||
pj = ROOT / "data" / "panels.json"
|
||||
if not pj.exists():
|
||||
return []
|
||||
rows = json.load(pj.open(encoding="utf-8"))["panels"]
|
||||
rows = [x for x in rows if int(x.get("free_count") or 0) > 0]
|
||||
rows.sort(key=lambda x: -int(x.get("free_count") or 0))
|
||||
if not rows:
|
||||
return []
|
||||
out = ["<b>ПАНЕЛИ С БЕСПЛАТНЫМИ МОДЕЛЯМИ</b>"]
|
||||
for x in rows[:limit]:
|
||||
names = ", ".join(str(n) for n in (x.get("free") or [])[:3])
|
||||
out.append("%s — <b>%d</b> free из %d%s" % (
|
||||
html.escape(str(x.get("host"))), int(x["free_count"]), int(x.get("models") or 0),
|
||||
(" · " + html.escape(names)) if names else ""))
|
||||
out.append("")
|
||||
return out
|
||||
|
||||
|
||||
def token() -> str:
|
||||
@@ -48,7 +92,7 @@ def build(limit: int) -> str:
|
||||
picks, seen = [], set()
|
||||
for it in res["items"]:
|
||||
key = it.get("sig") or it["id"]
|
||||
if key in seen:
|
||||
if key in seen or is_noise(it.get("title") or ""):
|
||||
continue
|
||||
seen.add(key)
|
||||
picks.append(it)
|
||||
@@ -62,7 +106,7 @@ def build(limit: int) -> str:
|
||||
raw = it.get("tags") or []
|
||||
raw = raw.split(",") if isinstance(raw, str) else list(raw)
|
||||
tags = ", ".join(TAG_RU.get(t, t) for t in raw if t)
|
||||
title = html.escape((it.get("title") or it.get("text") or "")[:110].strip())
|
||||
title = html.escape(clean(it.get("title") or it.get("text") or ""))
|
||||
tags_s = f" · <i>{html.escape(tags)}</i>" if tags else ""
|
||||
dup = f" · копий {it['dups']}" if it.get("dups") else ""
|
||||
link = it.get("url") or ""
|
||||
@@ -72,6 +116,7 @@ def build(limit: int) -> str:
|
||||
if link:
|
||||
out.append(f'<a href="{html.escape(link)}">{html.escape(link[:78])}</a>')
|
||||
out.append("")
|
||||
out.extend(panel_block())
|
||||
return "\n".join(out)[:3900]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user