diff --git a/docs/PROJECT_INVENTORY.md b/docs/PROJECT_INVENTORY.md index 652a0a7f5..6c5fd1715 100644 --- a/docs/PROJECT_INVENTORY.md +++ b/docs/PROJECT_INVENTORY.md @@ -8,12 +8,12 @@ | Метрика | Значение | |---|---:| | Package version | `19.9.0` | -| Стабильных tracked-файлов | 6,370 | -| Строк | 612,637 | +| Стабильных tracked-файлов | 6,371 | +| Строк | 612,727 | | Размер | 24.99 MiB | -| Python-файлов | 3,524 | -| Строк Python | 362,343 | -| Классов / функций / async | 2,988 / 20,004 / 1,636 | +| Python-файлов | 3,525 | +| Строк Python | 362,433 | +| Классов / функций / async | 2,988 / 20,008 / 1,636 | | Python syntax errors | 0 | | Test Python files / test functions | 972 / 6,728 | | Markdown-файлов | 2,046 | @@ -29,7 +29,7 @@ | `docs` | 477 | 76,067 | 3.27 MiB | | `tests` | 554 | 71,349 | 2.48 MiB | | `[root]` | 217 | 35,241 | 1.39 MiB | -| `scripts` | 280 | 33,755 | 1.28 MiB | +| `scripts` | 281 | 33,845 | 1.28 MiB | | `attic` | 33 | 30,669 | 1.61 MiB | | `octopus_services` | 110 | 27,850 | 0.90 MiB | | `tg_bot` | 34 | 12,812 | 0.65 MiB | @@ -49,7 +49,7 @@ | Расширение | Файлов | |---|---:| -| `.py` | 3,524 | +| `.py` | 3,525 | | `.md` | 2,046 | | `.json` | 147 | | `.service` | 135 | diff --git a/scripts/send_trading_report.py b/scripts/send_trading_report.py new file mode 100644 index 000000000..712815d41 --- /dev/null +++ b/scripts/send_trading_report.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +"""Send the detailed trading report (Трейдинг button content) to the owner's +Telegram chat: data chunks immediately, LLM section after generation.""" + +import json +import sys +import urllib.request +from pathlib import Path + +ROOT = Path("/root/AIOS") +sys.path.insert(0, str(ROOT)) + + +def _env(key: str) -> str: + if key in ("AIOS_TELEGRAM_TOKEN", "TELEGRAM_BOT_TOKEN"): + from tg_bot.credentials import secret_from_env_or_credential + value = secret_from_env_or_credential( + "AIOS_TELEGRAM_TOKEN", "TELEGRAM_BOT_TOKEN", credential="telegram_token" + ) + if value: + return value + if key in ("TELEGRAM_CHAT_ID", "AIOS_OWNER_CHAT_ID"): + from tg_bot.credentials import read_systemd_credential + value = read_systemd_credential("telegram_owner_chat_id") + if value: + return value + import os + v = os.environ.get(key, "") + if v: + return v + p = ROOT / ".env" + if p.exists(): + for line in p.read_text(encoding="utf-8").splitlines(): + line = line.strip() + if line.startswith(key + "="): + return line.split("=", 1)[1].strip().strip('"').strip("'") + return "" + + +def _post(payload: dict, token: str) -> tuple[bool, str]: + req = urllib.request.Request( + f"https://api.telegram.org/bot{token}/sendMessage", + data=json.dumps(payload).encode(), + headers={"Content-Type": "application/json"}) + try: + with urllib.request.urlopen(req, timeout=60) as resp: + data = json.loads(resp.read()) + return bool(data.get("ok")), data.get("description", "") + except urllib.error.HTTPError as exc: + return False, exc.read().decode(errors="replace")[:300] + except Exception as exc: + return False, str(exc) + + +def tg_send(text: str) -> tuple[bool, str]: + token = _env("TELEGRAM_BOT_TOKEN") or _env("AIOS_TELEGRAM_TOKEN") + chat = _env("TELEGRAM_CHAT_ID") or _env("AIOS_OWNER_CHAT_ID") + if not token or not chat: + return False, "no credentials" + base = { + "chat_id": int(chat), + "text": text[:3900], + "disable_web_page_preview": True, + } + ok, err = _post({**base, "parse_mode": "HTML"}, token) + if ok: + return True, "" + # HTML-режим мог сломаться о символы в LLM-тексте — ретрай без разметки + ok2, err2 = _post(base, token) + return ok2, f"html:{err[:80]}; plain:{err2[:120]}" + + +def main() -> int: + from tg_bot.trading_report import full_report + + messages = full_report() + sent = 0 + for i, msg in enumerate(messages, 1): + ok, err = tg_send(msg) + if ok: + sent += 1 + print(f"chunk {i}/{len(messages)}: sent ({len(msg)} chars)") + else: + print(f"chunk {i}/{len(messages)}: FAIL {err[:200]}") + print(f"total sent: {sent}/{len(messages)}") + return 0 if sent == len(messages) else 1 + + +if __name__ == "__main__": + raise SystemExit(main())