feat: VOTE ULANG SEGERA Telegram notification + emoticon on all notifications
- telegram.py: emoticons on all existing notif (🚀✅⚠️🔴💰🔍) + new notify_warn for expiring voters - db.py: voter_notify table (owner/urgency/notified_at) for state-change dedup - get_voters.py: _notify_warn() after persist() — urgency escalation ⚠️/🔴/🚨 by days remaining - Dockerfile.scan: add telegram.py to COPY - test_get_voters.py: 15 new V66 assertions (schema, record, cleanup, integration, escalation) - test_distribute.py: updated notification format assertions - SPEC.md: V66 + B26
This commit is contained in:
1 parent
eaefad6c1d
commit
1e93437a90
7 files changed
+345
-31
No files matched your search
@@ -132,6 +132,7 @@ V62: stempel scan UTC-naive (B24): `get_voters.persist` menulis `scanned_at`/`fi
|
||||
V63: jeda antar kirim distribusi: send-loop `run_distribution` tidur `DISTRIBUTE_SEND_DELAY` (int, default 30) detik ANTAR pemilih — setelah pemilih ke-i selesai diproses (sent/hold/failed), sebelum pemilih i+1; N pemilih → N−1 tidur, ⊖ tidur setelah pemilih TERAKHIR; real-run saja (dry-run ⊖ tidur — tak ada kirim). Tujuan: beri node/Hyperion waktu mengejar indeks + meratakan beban broadcast run panjang; jeda seragam terlepas hasil pemilih sebelumnya (pacing deterministik utk oracle). Oracle test_distribute V63: 3 pemilih → sleep dipanggil 2× dgn nilai `DISTRIBUTE_SEND_DELAY` | V63,V21,V22
|
||||
V64: banner BERITA hermetik utk oracle (B25): route index menghitung jam via helper modul `_now()` (isi = `datetime.now()` lokal, ⊖ inline di route) & mengoper ke `_next_schedule(now)`/`_recurrence_label(now)` — test mock `dashboard._now` ke tanggal TETAP (sebelum/sesudah launch) sehingga asersi baris-berulang ⊖ bergantung jam dinding nyata; tanpa ini, setelah tanggal first-run baked (2026-08-17) LEWAT di kalender, `_is_first_run_next(real_now)` ⊖ pernah True (`start >= now` gagal) → baris berulang tampil → asersi "TAK tampil saat first-run" gagal walau `_next_schedule` sudah di-mock (B25; test lulus hanya kalau kalender < tanggal launch). Oracle test_dashboard V38: mock `_now` sebelum launch → baris hilang; sesudah launch → baris muncul | V64,V38,V44
|
||||
V65: semua stempel data (audit trail, pembayaran, klaim) UTC-naive konsisten — `distribute.py` `created_at`, `db.py` `updated_at` (update_payment_status), `db.py` `now` (update_claim_fee) memakai `datetime.now(timezone.utc).replace(tzinfo=None)` — sama basis dengan `get_voters.persist` (V62), `eligible_voters` (V57), semua cutoff umur dashboard; ⊖ `datetime.now()` lokal yang menghasilkan WIB (UTC+7) dan merusak perbandingan string UTC. Oracle: test_distribute + test_claim tetap hijau | V65,V62,V57,V40,V52
|
||||
V66: notifikasi VOTE ULANG SEGERA via Telegram + emoticon pada SEMUA notifikasi: `get_voters._notify_warn(now)` setelah `persist()` — query pemilih dalam jendela `now−STALE < last_vote ≤ now−(STALE−WARN)` dari tabel `voters`, hitung urgensi dari sisa hari (≤1d=🚨/3, ≤2d=🔴/2, >2d=⚠️/1), filter yg sdh diberi tahu pada level ≥ urgensi saat ini (tabel `voter_notify`, state-change-only → max 3 notif/pemilih per jendela), kirim via `telegram.notify_warn` ke KOMUNITAS (daftar max 50 + link per-akun `mining.databisnis.id?q={owner}`), catat ke `voter_notify`, bersihkan baris stale. Tabel `voter_notify` (owner PK, urgency INT, notified_at TEXT) — `ensure_notify_schema`/`get_notify_urgency`/`record_notify`/`cleanup_notify` di `db.py`. `Dockerfile.scan` salin `telegram.py`. SEMUA notifikasi Telegram (`notify_start`/`notify_finish`/`notify_failure`/`notify_claim`/`notify_claim_unmeasured`/`notify_claim_failure`) kini punya emoticon prefix (🚀/✅/⚠️/🔴/💰/🔍). Oracle test_get_voters V66: voter_notify schema + record/get/cleanup + _notify_warn integrasi (mock telegram) + skip redundancy + escalation trigger | V66,V62,V40
|
||||
V35: kill-switch distribusi `DISTRIBUTE_ENABLED` default false → run nyata (bukan dry-run) no-op: exit 0, ⊥ baca saldo, ⊥ tanda tangan, ⊥ tulis DB, ⊥ notif; `--dry-run` tetap menampilkan rencana (read-only); nilai `true`/`1`/`yes` → normal
|
||||
V36: notifikasi klaim reward (sukses `notify_claim` & gagal `notify_claim_failure`) → kanal INTERNAL saja, ⊥ pernah ke KOMUNITAS (V30); fee gagal ⊥ spam — satu notif per klaim (saat transisi ke `failed`)
|
||||
V37: jadwal distribusi MINGGUAN (⊥ harian): `distribute_loop` menunggu `DISTRIBUTE_WEEKDAY` — SATU hari (`sat`) atau CSV beberapa hari (`wed,sat`), nama `mon`..`sun` atau 0-6 (V44: multi-hari, event terdekat di antara hari-hari terdaftar) — jam `DISTRIBUTE_HOUR` (lokal TZ); plus satu one-off `DISTRIBUTE_FIRST_RUN` (`YYYY-MM-DD`; default baked `2026-08-17`) yang diambil bila lebih dekat dari mingguan; setelah lewat (atau ⊥ diset) → hanya mingguan; batas dihitung ulang tiap iterasi loop (setelah run → jadwal berikutnya); payout di-tunda bila `DISTRIBUTE_ENABLED=false` (V35) — jadwal tetap maju, run jadi no-op; `distribute_loop.main` baca jadwal via `config` (⊥ `os.getenv` sendiri) agar konsisten dgn dashboard V38
|
||||
@@ -225,3 +226,4 @@ B22|2026-08-13|`_send_rejected` BLACKLIST (deteksi `error` di body) — body 500
|
||||
B23|2026-08-13|respons `/v2/*` bentuk non-dict (200-an `[...]`/`"..."` dari proxy salah) → `AttributeError: 'list' object has no attribute 'get'` DII DALAM `except RequestException` → run distribusi BEBENTI total; sama di `verify_txid`/`reward_from_tx`/`dashboard._get_liquid_vex`|guard `isinstance(data, dict)` di semua pembaca `/v2/*` → non-dict → skip/skip-node/None (V61, F5); oracle `_get_json`/`verify_txid` non-dict → None
|
||||
B24|2026-08-17|`first_seen_at`/`scanned_at` tersimpan WIB (UTC+7) tapi dibandingkan sbg string UTC di SEMUA cutoff umur (dashboard + `db.eligible_voters` + distribusi): `get_voters.persist` memakai `datetime.now()` (waktu lokal container `TZ=Asia/Jakarta`) sedangkan cutoff pakai `datetime.now(timezone.utc)` — offset +7 jam membuat pemilih BARU tampak belum matang ~7 jam lebih lama (kasus nyata: idrsaku33351/m4dhanchocil/danuprasetya first_seen 13 Agt 17:39 WIB, seharusnya matang 16 Agt 17:39 WIB, kode melepas dari BARU baru 17 Agt 00:39 WIB)|`persist` stempel UTC-naive (`datetime.now(timezone.utc).replace(tzinfo=None)`); migrasi data existing WIB→UTC (−7 jam) dgn backup `*_bak_wib` (V62); oracle V62 guard stempel ≈ now-UTC ⊖ WIB
|
||||
B25|2026-08-19|oracle V38 HTML-render bergantung jam dinding nyata: route index `_now = datetime.now()` inline → `_recurrence_label(real_now)` → `_is_first_run_next` cek `start >= now` — setelah tanggal first-run baked (2026-08-17) LEWAT di kalender nyata, `start >= now` ⊖ pernah True → baris berulang `SETIAP RABU & SABTU` tampil → asersi "baris berulang TAK tampil saat first-run" GAGAL walau `_next_schedule` sudah di-mock ke 2026-08-17 (test lulus hanya kalau kalender nyata < tanggal launch)|route pakai helper modul `_now()` injectable + oracle mock `dashboard._now` ke tanggal tetap sebelum/sesudah launch (V64)
|
||||
B26|2026-08-27|tidak ada notifikasi Telegram untuk pemilih yang masuk jendela VOTE ULANG SEGERA — pemilih hanya terlihat di dashboard dgn badge amber, ⊥ alert proaktif ke komunitas → vote kedaluwarsa tanpa peringatan|`get_voters._notify_warn` + `telegram.notify_warn` + tabel `voter_notify` utk state-change dedup + emoticon pada SEMUA notifikasi (V66)
|
||||
Reference in new issue
Block a user