From b7d05b1e5cce67f041418a82795194803b8d7e11 Mon Sep 17 00:00:00 2001 From: jaxperro Date: Mon, 6 Jul 2026 13:22:05 -0400 Subject: [PATCH] daily: Discord ping at pipeline kickoff (discord_daily.py --ping) One plain line when the cache refresh starts, so the end-of-run digest isn't the only sign of life. Non-fatal if the webhook is missing. Co-Authored-By: Claude Fable 5 --- live/daily.sh | 2 ++ live/discord_daily.py | 23 ++++++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/live/daily.sh b/live/daily.sh index b5aafcd1..1ff50216 100755 --- a/live/daily.sh +++ b/live/daily.sh @@ -20,6 +20,8 @@ # Schedule with launchd/cron (Mac must be awake). Logs to daily.log. set -u cd "$(dirname "$0")" +# heads-up ping so the run's start is visible in Discord (digest comes at the end) +python3 discord_daily.py --ping "🔄 Daily pipeline started $(date '+%H:%M') — refreshing the bet cache (takes a while); sharp digest lands when it finishes." || true echo "[daily] $(date '+%F %T') 1/6 discover (enumerate last 14d)" python3 enumerate.py 14 echo "[daily] $(date '+%F %T') 2/6 freshen cache (watchlists forced + new wallets)" diff --git a/live/discord_daily.py b/live/discord_daily.py index 442e983c..c97226ff 100644 --- a/live/discord_daily.py +++ b/live/discord_daily.py @@ -24,6 +24,14 @@ HERE = os.path.dirname(os.path.abspath(__file__)) MAX_ROWS = 30 # embed description caps at 4096 chars; 30 rows fits +def _post(hook, payload): + req = urllib.request.Request( + hook, data=json.dumps(payload).encode(), + headers={"Content-Type": "application/json", + "User-Agent": "Mozilla/5.0"}) # Discord 403s the default UA + urllib.request.urlopen(req, timeout=15, context=ssl._create_unverified_context()) + + def main(): try: hook = json.load(open(os.path.join(HERE, "..", "config.json"))).get("daily_webhook") @@ -32,6 +40,15 @@ def main(): if not hook: print("[discord] no daily_webhook in ../config.json — skipping") return + # --ping "text": one plain status line (used by daily.sh's start-of-run + # heads-up so the digest hours later isn't the only sign of life) + if len(sys.argv) > 2 and sys.argv[1] == "--ping": + try: + _post(hook, {"content": sys.argv[2]}) + print("[discord] ping sent") + except Exception as e: + print("[discord] ping failed:", e) + return try: sharps = json.load(open(os.path.join(HERE, "watch_sharps.json"))) except Exception as e: @@ -59,12 +76,8 @@ def main(): "footer": {"text": ((sys.argv[1] + " · ") if len(sys.argv) > 1 else "") + "30D win% · conviction record · conviction P&L (wallet's own)"}, } - req = urllib.request.Request( - hook, data=json.dumps({"embeds": [embed]}).encode(), - headers={"Content-Type": "application/json", - "User-Agent": "Mozilla/5.0"}) # Discord 403s the default UA try: - urllib.request.urlopen(req, timeout=15, context=ssl._create_unverified_context()) + _post(hook, {"embeds": [embed]}) print(f"[discord] daily sharp digest sent ({min(len(sharps), MAX_ROWS)} rows)") except Exception as e: print("[discord] digest failed:", e)