init: workspace opencode sync
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
# Telegram Reset Button untuk Notifikasi Expired (MSR Hotspot)
|
||||
|
||||
> Ringkasan perubahan arsitektur notifikasi expired hotspot & tombol "🔄 Reset" via Telegram.
|
||||
> Tanggal: 1 Agu 2026 · RouterOS v6.49.6 · Mikhmon (Docker)
|
||||
|
||||
---
|
||||
|
||||
## 1. Masalah Awal
|
||||
|
||||
1. Notifikasi "User X expired" sebelumnya dikirim oleh `notify-expire.php` di server Mikhmon, yang menampilkan inline keyboard **🔄 Reset** dengan `callback_data=reset_<user>`.
|
||||
2. Router (MikroTik) tidak bisa menjangkau path lama (`192.168.100.6`, sudah mati). Scheduler di router mengirim notifikasi ke URL Telegram lama yang tidak lagi berfungsi.
|
||||
3. Akibatnya pesan expired terkirim **tanpa tombol Reset**, dan callback reset tidak berfungsi.
|
||||
|
||||
## 2. Solusi Baru (Arsitektur)
|
||||
|
||||
```
|
||||
[RouterOS Scheduler] --/tool/fetch sendMessage--> [Telegram Bot] --Kirim ke Grup (thread "Notif Expire")
|
||||
^
|
||||
[User klik 🔄 Reset] --> callback_query --> [Bot] --> poller getUpdates
|
||||
|
|
||||
v
|
||||
[Host rl] cron tiap menit --> msr-poller.sh --> docker start mikhmon
|
||||
|
|
||||
v
|
||||
telegram-cb.php (di container) --> RouterOS API reset user
|
||||
|
|
||||
v
|
||||
Telegram: "✅ {user} has been reset"
|
||||
```
|
||||
|
||||
### Komponen
|
||||
| Komponen | Lokasi | Peran |
|
||||
|---|---|---|
|
||||
| Scheduler RouterOS | Router 192.168.100.2 | Kirim pesan expired + `reply_markup` tombol Reset langsung ke Telegram |
|
||||
| Telegram Bot | `5115036608:AAGey...` | Terima/teruskan pesan & callback |
|
||||
| Cron host | `/usr/local/bin/msr-poller.sh` di `rl` | Setiap menit: `docker start mikhmon` + curl `telegram-cb.php` |
|
||||
| `telegram-cb.php` | `/var/www/html/` di container `mikhmon` | getUpdates → reset user di RouterOS → jawab callback + kirim konfirmasi |
|
||||
| `lib/routeros_api.class.php` | `/var/www/html/lib/` | Koneksi RouterOS API dari PHP |
|
||||
|
||||
## 3. Perubahan yang Dilakukan
|
||||
|
||||
### 3.1 Scheduler RouterOS (Family, Bulanan2, Bulanan4)
|
||||
`on-event` scheduler sekarang melakukan `/tool/fetch` ke Telegram `sendMessage` dengan:
|
||||
- `chat_id=-1002554941429`, `message_thread_id=42` (thread "Notif Expire")
|
||||
- `text=" . $name . "+expired`
|
||||
- `reply_markup` = JSON inline keyboard **URL-encoded**:
|
||||
|
||||
```
|
||||
%7B%22inline_keyboard%22%3A%5B%5B%7B%22text%22%3A%22%F0%9F%94%84%20Reset%22%2C%22callback_data%22%3A%22reset_" . $name . "%22%7D%5D%5D%7D
|
||||
```
|
||||
|
||||
yang setara dengan:
|
||||
```json
|
||||
{"inline_keyboard":[[{"text":"🔴 Reset","callback_data":"reset_<name>"}]]}
|
||||
```
|
||||
|
||||
Contoh cuplikan on-event Family:
|
||||
```
|
||||
tool fetch url=("https://api.telegram.org/bot5115036608:AAGey.../sendMessage?chat_id=-1002554941429&message_thread_id=42&text=" . $name . "+expired&reply_markup=" . "%7B%22inline_keyboard%22%3A...%22reset_" . $name . "%22%7D%5D%5D%7D") mode=https http-method=get keep-result=no
|
||||
```
|
||||
|
||||
**Penting:** deduplikasi (`:if ($curlim = "")`) tetap dipertahankan agar setiap user hanya dikirim sekali.
|
||||
|
||||
### 3.2 Container Mikhmon — Install php81-curl
|
||||
Container PHP 8.1 (Alpine) awalnya tanpa ekstensi cURL → `telegram-cb.php` error HTTP 500.
|
||||
```sh
|
||||
docker exec -u root mikhmon apk add --no-cache php81-curl
|
||||
```
|
||||
|
||||
### 3.3 Perbaikan include path `telegram-cb.php`
|
||||
Dari `dirname(__DIR__) . '/lib/routeros_api.class.php'` → `__DIR__ . '/lib/routeros_api.class.php'` (2 tempat), karena file berada langsung di `/var/www/html/`.
|
||||
|
||||
### 3.4 Poller Host (atasi sablier)
|
||||
Container `mikhmon` dikelola **sablier** (traefik plugin) yang mematikannya setelah **5 menit idle** — cron di dalam container tidak bisa diandalkan. Solusi: cron di **host** yang men-starter container lalu memanggil callback.
|
||||
|
||||
`/usr/local/bin/msr-poller.sh`:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
CB_KEY="msr-2026-reset"
|
||||
URL="http://172.18.0.15/telegram-cb.php?key=${CB_KEY}"
|
||||
docker start mikhmon >/dev/null 2>&1
|
||||
sleep 1
|
||||
curl -s -m 30 "$URL" >/dev/null 2>&1
|
||||
```
|
||||
|
||||
Crontab host (`crontab -l`):
|
||||
```
|
||||
* * * * * /usr/local/bin/msr-poller.sh >/dev/null 2>&1
|
||||
```
|
||||
|
||||
Catatan:
|
||||
- `docker start` idempotent (kalau sudah jalan, no-op) → otomatis menjaga container hidup.
|
||||
- Polling maksimal latency ~1 menit setelah klik tombol.
|
||||
|
||||
### 3.5 Callback Handler `telegram-cb.php`
|
||||
- Auth via `?key=msr-2026-reset` (403 kalau salah).
|
||||
- `getUpdates` (hanya `callback_query`).
|
||||
- Untuk `data` berawalan `reset_`:
|
||||
1. Cari user di `/ip/hotspot/user/print?name=<user>`
|
||||
2. `set limit-uptime=0, comment=''` + `reset-counters`
|
||||
3. Hapus scheduler bernama `<user>` (jika ada)
|
||||
4. `answerCallbackQuery` (`✅ {user} reset!`)
|
||||
5. `sendMessage` ke chat/thread: `✅ *{user}* has been reset\nReady to use again`
|
||||
- User tidak ditemukan → `answerCallbackQuery` alert `User {user} not found` (tanpa pesan).
|
||||
- Meng-konfirmasi offset via `getUpdates?offset=<last_id+1>` setelah diproses.
|
||||
|
||||
## 4. Verifikasi
|
||||
|
||||
| Item | Hasil |
|
||||
|---|---|
|
||||
| Pesan expired + tombol Reset muncul di grup | ✅ Bubble punya `reply-markup-button` "Reset" |
|
||||
| Klik tombol → callback `reset_<user>` sampai ke bot | ✅ `data: "reset_TMR-1"` via getUpdates |
|
||||
| Poller cron memproses callback | ✅ `processed: 1` |
|
||||
| User di-reset di router | ✅ `limit-uptime` 10s → None (unlimited), counters reset |
|
||||
| Scheduler user dihapus | ✅ |
|
||||
| Konfirmasi bot di grup | ✅ `msr_net: TMR-1 has been reset` (09:11) |
|
||||
|
||||
Test user `TMR-1` dibuat khusus lalu dihapus setelah verifikasi.
|
||||
|
||||
## 5. Operasional & Troubleshooting
|
||||
|
||||
### Cek status
|
||||
- Poller: `ssh rl "cat /usr/local/bin/msr-poller.sh; crontab -l | grep poller"`
|
||||
- Container: `ssh rl "docker ps --filter name=mikhmon --format '{{.Status}}'"`
|
||||
- Callback pending: `curl 'http://172.18.0.15/telegram-cb.php?key=msr-2026-reset'` → harus `processed: 0` / `no updates`
|
||||
- Webhook tidak terpasang (poller getUpdates aman): `getWebhookInfo` → `url: ""`, `allowed_updates:["callback_query"]`
|
||||
|
||||
### Gejala umum
|
||||
- **HTTP 500 dari telegram-cb.php** → cek cURL: `docker exec mikhmon php -r 'var_dump(function_exists("curl_init"));'`
|
||||
- **Container mati** → sablier mematikannya setelah 5m idle; poller harusnya men-starter. Cek log poller/cron.
|
||||
- **Callback tidak terproses** → JANGAN baca `getUpdates` manual (maju offset & poller kehilangan callback). Biarkan poller cron yang memproses.
|
||||
- **Tombol tidak muncul** → `reply_markup` tidak ter-encode dengan benar; cek `verify-markup.py` & on-event scheduler.
|
||||
|
||||
## 6. Kredensial & Referensi
|
||||
|
||||
- Router: `192.168.100.2`, API `remote.vpnmurahjogja.my.id:33206`, login `mi4`/`m14`
|
||||
- Bot: `5115036608:AAGeyXVq5eNvdAkaCQHU9NfH16uAAiSKiuk`
|
||||
- Chat/Grup: `-1002554941429`, thread `42` ("Notif Expire")
|
||||
- Container: `mikhmon` (animegasan/mikhmon:v3-latest) di host `rl` (`root@100.100.31.46`, ssh alias `rl`, key `~/.ssh/pl`)
|
||||
- Callback secret: `msr-2026-reset`
|
||||
- Container IP: `172.18.0.15`
|
||||
|
||||
## 7. Skrip Bantu (folder `C:\Users\Admin\dev\mikhmon-fix\`)
|
||||
|
||||
| Skrip | Fungsi |
|
||||
|---|---|
|
||||
| `patch-notif2.py` | Patch on-event scheduler → tambah `reply_markup` Reset button |
|
||||
| `verify-markup.py` | Verifikasi on-event berisi `reply_markup` & `reset_` |
|
||||
| `verify-notif.py` | Verifikasi isi scheduler (api.telegram.org, tidak ada URL lama) |
|
||||
| `dump-sched.py` | Dump penuh on-event scheduler |
|
||||
| `telegram-cb.php` | Callback handler (sumber; di-deploy ke container) |
|
||||
| `poller.sh` | Poller host (sumber; di-deploy ke `/usr/local/bin/msr-poller.sh`) |
|
||||
| `mk-user.py` / `rm-user.py` | Buat / hapus user test |
|
||||
| `send-expired-tmr.py` | Kirim pesan expired + tombol untuk user tertentu |
|
||||
| `check-reset.py` | Cek limit-uptime & scheduler user setelah reset |
|
||||
|
||||
## 8. Catatan
|
||||
- Bot menampilkan tombol sebagai "Reset" — teks `🔄` (U+1F504, `%F0%9F%94%84`) di-render Telegram sebagai ikon 🔄.
|
||||
- `keep-result=no` di scheduler fetch (tidak menyimpan file respons di router). Saat debug bisa ubah `keep-result=yes` untuk lihat file `sendMessage?...`.
|
||||
- Jika tombol ditekan dua kali, user kedua dikirim ulang notif "expired" (karena sudah reset, limit-uptime unlimited → tidak ada scheduler baru sampai limit diubah lagi).
|
||||
Reference in New Issue
Block a user