v1.2-Beta: Telegram notifications, bug fixes, compact number display
This commit is contained in:
366
README.md
366
README.md
@@ -10,7 +10,7 @@
|
|||||||
M A N A G E R
|
M A N A G E R
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
@@ -18,31 +18,55 @@
|
|||||||
|
|
||||||
A powerful management tool for deploying and managing Psiphon Conduit nodes on Linux servers. Help users access the open internet during network restrictions.
|
A powerful management tool for deploying and managing Psiphon Conduit nodes on Linux servers. Help users access the open internet during network restrictions.
|
||||||
|
|
||||||
## Quick Install
|
## Quick Install (Beta)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sL https://raw.githubusercontent.com/SamNet-dev/conduit-manager/main/conduit.sh | sudo bash
|
curl -sL https://raw.githubusercontent.com/SamNet-dev/conduit-manager/beta-releases/conduit.sh | sudo bash
|
||||||
```
|
```
|
||||||
|
|
||||||
Or download and run manually:
|
Or download and run manually:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
wget https://raw.githubusercontent.com/SamNet-dev/conduit-manager/main/conduit.sh
|
wget https://raw.githubusercontent.com/SamNet-dev/conduit-manager/beta-releases/conduit.sh
|
||||||
sudo bash conduit.sh
|
sudo bash conduit.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
## What's New in v1.1
|
> For stable release, use `main` instead of `beta-releases` in the URL above.
|
||||||
|
|
||||||
- **Multi-Container Support** — Run up to 5 Conduit containers on a single server for higher throughput
|
## v1.2-Beta Changelog
|
||||||
- **Background Traffic Tracker** — Continuous tcpdump-based tracker service with per-country GeoIP stats
|
|
||||||
- **Advanced Stats Page** — Live dashboard with top countries by peers, download, upload, and unique IPs (bar charts, auto-refresh)
|
> This list will grow as more features are added before the full v1.2 release.
|
||||||
- **Live Dashboard Overhaul** — Side-by-side active clients and top upload by country with real-time bars
|
|
||||||
- **Per-Container Settings** — Configure max-clients and bandwidth individually for each container
|
**New Features**
|
||||||
- **Container Manager** — Add or remove containers on the fly with auto-refreshing status view
|
- Telegram bot notifications with guided setup wizard (periodic status reports via Telegram)
|
||||||
- **Smart Install** — Detects CPU cores and RAM, recommends container count for your hardware
|
- Systemd-based notification service (survives reboots and TUI exits)
|
||||||
- **Info & Help Hub** — Multi-page guide covering the tracker, stats, containers, privacy, and about
|
- Compact number display — large counts show as 16.5K, 1.2M
|
||||||
- **Service Auto-Recovery** — Automatically restarts failed conduit.service on script launch
|
- Active clients count in dashboard and Telegram reports
|
||||||
- **Seamless Upgrade** — Existing v1.0.x users can run the new script without reinstalling; old containers are recognized automatically
|
- Total bandwidth served in reports
|
||||||
|
- Timestamps on all Telegram reports
|
||||||
|
|
||||||
|
**Bug Fixes**
|
||||||
|
- Auto-restart for stuck containers with improved detection
|
||||||
|
- False WAITING status in health check for connected containers without stats
|
||||||
|
- Container start/stop/restart logic
|
||||||
|
- Duplicate country entries in GeoIP data with broader name normalization
|
||||||
|
- TUI stability (multiple fixes)
|
||||||
|
- Health check edge cases
|
||||||
|
- CPU normalization in reports (divide by core count)
|
||||||
|
- Peers count consistency across views
|
||||||
|
- Telegram markdown escaping (backslash handling)
|
||||||
|
- Wizard failure paths now preserve existing config
|
||||||
|
- Uninstall cleanup for Telegram service
|
||||||
|
- Menu no longer restarts notification loop on every open
|
||||||
|
- PID management for background processes
|
||||||
|
|
||||||
|
**Security**
|
||||||
|
- Silent bot token input (not echoed)
|
||||||
|
- Numeric-only chat ID validation
|
||||||
|
- Restricted PID file permissions (600)
|
||||||
|
- BotFather privacy guidance in setup wizard
|
||||||
|
- OPSEC warning for operators in censored regions
|
||||||
|
- Curl calls with `--max-filesize` and `--max-time` limits
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -54,12 +78,11 @@ sudo bash conduit.sh
|
|||||||
- **Advanced Stats** — Top countries by connected peers, download, upload, and unique IPs with bar charts
|
- **Advanced Stats** — Top countries by connected peers, download, upload, and unique IPs with bar charts
|
||||||
- **Live Peer Traffic** — Real-time traffic table by country with speed, total bytes, and IP/client counts
|
- **Live Peer Traffic** — Real-time traffic table by country with speed, total bytes, and IP/client counts
|
||||||
- **Background Tracker** — Continuous traffic monitoring via systemd service with GeoIP resolution
|
- **Background Tracker** — Continuous traffic monitoring via systemd service with GeoIP resolution
|
||||||
|
- **Telegram Notifications** — Optional periodic status reports and alerts via Telegram bot
|
||||||
- **Per-Container Settings** — Configure max-clients and bandwidth per container
|
- **Per-Container Settings** — Configure max-clients and bandwidth per container
|
||||||
- **Easy Management** — Powerful CLI commands or interactive menu
|
|
||||||
- **Backup & Restore** — Backup and restore your node identity keys
|
- **Backup & Restore** — Backup and restore your node identity keys
|
||||||
- **Health Checks** — Comprehensive diagnostics for troubleshooting
|
- **Health Checks** — Comprehensive diagnostics for troubleshooting
|
||||||
- **Info & Help** — Built-in multi-page guide explaining how everything works
|
- **Complete Uninstall** — Clean removal of all components including Telegram service
|
||||||
- **Complete Uninstall** — Clean removal of all components
|
|
||||||
|
|
||||||
## Supported Distributions
|
## Supported Distributions
|
||||||
|
|
||||||
@@ -75,102 +98,28 @@ sudo bash conduit.sh
|
|||||||
|
|
||||||
After installation, use the `conduit` command:
|
After installation, use the `conduit` command:
|
||||||
|
|
||||||
### Status & Monitoring
|
|
||||||
```bash
|
```bash
|
||||||
conduit status # Show current status and resource usage
|
|
||||||
conduit stats # View live statistics (real-time dashboard)
|
|
||||||
conduit logs # View raw Docker logs
|
|
||||||
conduit health # Run health check diagnostics
|
|
||||||
conduit peers # Live peer traffic by country (GeoIP)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Rewards
|
|
||||||
```bash
|
|
||||||
conduit qr # Show QR code to claim rewards via Ryve app
|
|
||||||
```
|
|
||||||
|
|
||||||
### Container Management
|
|
||||||
```bash
|
|
||||||
conduit start # Start all Conduit containers
|
|
||||||
conduit stop # Stop all Conduit containers
|
|
||||||
conduit restart # Restart all Conduit containers
|
|
||||||
conduit update # Update to the latest Conduit image
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
```bash
|
|
||||||
conduit settings # Change max-clients and bandwidth per container
|
|
||||||
conduit menu # Open interactive management menu
|
conduit menu # Open interactive management menu
|
||||||
```
|
conduit status # Show current status
|
||||||
|
conduit stats # Live statistics dashboard
|
||||||
### Backup & Restore
|
conduit peers # Live peer traffic by country
|
||||||
```bash
|
conduit start # Start all containers
|
||||||
conduit backup # Backup your node identity keys
|
conduit stop # Stop all containers
|
||||||
conduit restore # Restore node identity from backup
|
conduit restart # Restart all containers
|
||||||
```
|
conduit update # Update Conduit image
|
||||||
|
conduit backup # Backup node identity keys
|
||||||
### Maintenance
|
conduit restore # Restore from backup
|
||||||
```bash
|
conduit qr # Show QR code for rewards
|
||||||
|
conduit health # Run health diagnostics
|
||||||
conduit uninstall # Remove all components
|
conduit uninstall # Remove all components
|
||||||
conduit version # Show version information
|
|
||||||
conduit help # Show help message
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Interactive Menu
|
## Configuration
|
||||||
|
|
||||||
The interactive menu (`conduit menu`) provides access to all features:
|
|
||||||
|
|
||||||
| Option | Description |
|
|
||||||
|--------|-------------|
|
|
||||||
| **1** | View status dashboard — real-time stats with active clients and top upload by country |
|
|
||||||
| **2** | Live connection stats — streaming stats from Docker logs |
|
|
||||||
| **3** | View logs — raw Docker log output |
|
|
||||||
| **4** | Live peers by country — per-country traffic table with speed and client counts |
|
|
||||||
| **5** | Start Conduit |
|
|
||||||
| **6** | Stop Conduit |
|
|
||||||
| **7** | Restart Conduit |
|
|
||||||
| **8** | Update Conduit image |
|
|
||||||
| **9** | Settings & Tools — max-clients, bandwidth, QR code, backup, restore, health check, uninstall |
|
|
||||||
| **c** | Manage containers — add or remove containers (up to 5) |
|
|
||||||
| **a** | Advanced stats — top 5 charts for peers, download, upload, unique IPs |
|
|
||||||
| **i** | Info & Help — multi-page guide with tracker, stats, containers, privacy, about |
|
|
||||||
| **0** | Exit |
|
|
||||||
|
|
||||||
## Configuration Options
|
|
||||||
|
|
||||||
| Option | Default | Range | Description |
|
| Option | Default | Range | Description |
|
||||||
|--------|---------|-------|-------------|
|
|--------|---------|-------|-------------|
|
||||||
| `max-clients` | 200 | 1–1000 | Maximum concurrent proxy clients per container |
|
| `max-clients` | 200 | 1–1000 | Max concurrent clients per container |
|
||||||
| `bandwidth` | 5 | 1–40, -1 | Bandwidth limit per peer (Mbps). Use -1 for unlimited. |
|
| `bandwidth` | 5 | 1–40, -1 | Bandwidth limit per peer (Mbps). -1 for unlimited |
|
||||||
|
|
||||||
**Recommended values based on server hardware:**
|
|
||||||
|
|
||||||
| CPU Cores | RAM | Recommended Containers | Max Clients (per container) |
|
|
||||||
|-----------|-----|------------------------|-----------------------------|
|
|
||||||
| 1 Core | < 1 GB | 1 | 100 |
|
|
||||||
| 2 Cores | 2 GB | 1–2 | 200 |
|
|
||||||
| 4 Cores | 4 GB+ | 2–3 | 400 |
|
|
||||||
| 8+ Cores | 8 GB+ | 3–5 | 800 |
|
|
||||||
|
|
||||||
## Installation Options
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Standard install
|
|
||||||
sudo bash conduit.sh
|
|
||||||
|
|
||||||
# Force reinstall
|
|
||||||
sudo bash conduit.sh --reinstall
|
|
||||||
|
|
||||||
# Uninstall everything
|
|
||||||
sudo bash conduit.sh --uninstall
|
|
||||||
|
|
||||||
# Show help
|
|
||||||
sudo bash conduit.sh --help
|
|
||||||
```
|
|
||||||
|
|
||||||
## Upgrading from v1.0.x
|
|
||||||
|
|
||||||
Just run the new script. When prompted, select **"Open management menu"** — your existing container is recognized automatically. No reinstall needed. The background tracker service starts when you next start/restart from the menu.
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@@ -179,210 +128,23 @@ Just run the new script. When prompted, select **"Open management menu"** — yo
|
|||||||
- Internet connection
|
- Internet connection
|
||||||
- Minimum 512MB RAM (1GB+ recommended for multi-container)
|
- Minimum 512MB RAM (1GB+ recommended for multi-container)
|
||||||
|
|
||||||
## How It Works
|
## Upgrading
|
||||||
|
|
||||||
1. **Detection** — Identifies your Linux distribution and init system
|
Just run the install command above. When prompted, select **"Open management menu"** — existing containers are recognized automatically. Telegram settings are preserved across upgrades.
|
||||||
2. **Docker Setup** — Installs Docker if not present
|
|
||||||
3. **Hardware Check** — Detects CPU/RAM and recommends container count
|
|
||||||
4. **Container Deployment** — Pulls and runs the official Psiphon Conduit image
|
|
||||||
5. **Auto-Start Configuration** — Sets up systemd/OpenRC/SysVinit service
|
|
||||||
6. **Tracker Service** — Starts background traffic tracker with GeoIP resolution
|
|
||||||
7. **CLI Installation** — Creates the `conduit` management command
|
|
||||||
|
|
||||||
## Claim Rewards (OAT Tokens)
|
## Claim Rewards (OAT Tokens)
|
||||||
|
|
||||||
Conduit node operators can earn OAT tokens for contributing to the Psiphon network. To claim rewards:
|
1. Install the **Ryve app** on your phone
|
||||||
|
2. Create a **crypto wallet** within the app
|
||||||
1. **Install the Ryve app** on your phone
|
3. Run `conduit qr` or use the menu to show your QR code
|
||||||
2. **Create a crypto wallet** within the app
|
4. Scan with Ryve to link your node and start earning
|
||||||
3. **Link your Conduit containers** by scanning the QR code:
|
|
||||||
- From the menu: Select Settings & Tools **Option 6 → Show QR Code & Conduit ID**
|
|
||||||
- From Manage Containers: press **[q]** to display QR code
|
|
||||||
- CLI: `conduit qr`
|
|
||||||
4. **Scan the QR code** with the Ryve app to link your node
|
|
||||||
5. **Monitor & earn** — the app shows your last 48 hours of connection activity and OAT token rewards
|
|
||||||
|
|
||||||
> Each container has its own unique Conduit ID and QR code. If running multiple containers, you'll need to link each one separately.
|
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
- **Secure Backups**: Node identity keys are stored with restricted permissions (600)
|
- **Secure Backups**: Node identity keys stored with restricted permissions (600)
|
||||||
- **No Telemetry**: The manager collects no data and sends nothing externally
|
- **No Telemetry**: The manager collects no data and sends nothing externally
|
||||||
- **Local Tracking Only**: Traffic stats are stored locally and never transmitted
|
- **Local Tracking Only**: Traffic stats are stored locally and never transmitted
|
||||||
|
- **Telegram Optional**: Bot notifications are opt-in only, zero resources used if disabled
|
||||||
---
|
|
||||||
|
|
||||||
<div dir="rtl">
|
|
||||||
|
|
||||||
# راهنمای فارسی - مدیریت کاندوییت
|
|
||||||
|
|
||||||
ابزار قدرتمند برای راهاندازی و مدیریت نود سایفون کاندوییت روی سرورهای لینوکس. به کاربران کمک کنید تا در زمان محدودیتهای اینترنتی به اینترنت آزاد دسترسی داشته باشند.
|
|
||||||
|
|
||||||
## نصب سریع
|
|
||||||
|
|
||||||
دستور زیر را در ترمینال سرور اجرا کنید:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -sL https://raw.githubusercontent.com/SamNet-dev/conduit-manager/main/conduit.sh | sudo bash
|
|
||||||
```
|
|
||||||
|
|
||||||
یا دانلود و اجرای دستی:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
wget https://raw.githubusercontent.com/SamNet-dev/conduit-manager/main/conduit.sh
|
|
||||||
sudo bash conduit.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## تازههای نسخه 1.1
|
|
||||||
|
|
||||||
- **پشتیبانی از چند کانتینر** — اجرای تا ۵ کانتینر روی یک سرور برای ظرفیت بیشتر
|
|
||||||
- **ردیاب ترافیک پسزمینه** — سرویس ردیابی مداوم با آمار جغرافیایی به تفکیک کشور
|
|
||||||
- **صفحه آمار پیشرفته** — داشبورد زنده با نمودار میلهای برای برترین کشورها
|
|
||||||
- **داشبورد بازطراحی شده** — نمایش کلاینتهای فعال و آپلود برتر به تفکیک کشور
|
|
||||||
- **تنظیمات هر کانتینر** — پیکربندی جداگانه حداکثر کاربران و پهنای باند
|
|
||||||
- **مدیریت کانتینرها** — اضافه یا حذف کانتینر به صورت آنی
|
|
||||||
- **نصب هوشمند** — تشخیص CPU و RAM و پیشنهاد تعداد کانتینر مناسب
|
|
||||||
- **بخش راهنما** — راهنمای چندصفحهای شامل ردیاب، آمار، کانتینرها، حریم خصوصی و درباره ما
|
|
||||||
- **بازیابی خودکار سرویس** — ریستارت خودکار سرویس در صورت خرابی
|
|
||||||
- **ارتقا بدون نصب مجدد** — کاربران نسخه قبلی بدون نیاز به نصب مجدد میتوانند آپدیت کنند
|
|
||||||
|
|
||||||
## ویژگیها
|
|
||||||
|
|
||||||
- **نصب با یک کلیک** — داکر و تمام موارد مورد نیاز به صورت خودکار نصب میشود
|
|
||||||
- **مقیاسپذیری چند کانتینره** — اجرای ۱ تا ۵ کانتینر برای حداکثر استفاده از سرور
|
|
||||||
- **پشتیبانی از توزیعهای مختلف** — اوبونتو، دبیان، سنتاواس، فدورا، آرچ، آلپاین
|
|
||||||
- **راهاندازی خودکار** — پس از ریستارت سرور، سرویس به صورت خودکار اجرا میشود
|
|
||||||
- **داشبورد زنده** — نمایش لحظهای وضعیت، تعداد کاربران، مصرف CPU و RAM
|
|
||||||
- **آمار پیشرفته** — نمودار میلهای برترین کشورها بر اساس اتصال، دانلود، آپلود و IP
|
|
||||||
- **مانیتورینگ ترافیک** — جدول لحظهای ترافیک بر اساس کشور با سرعت و تعداد کلاینت
|
|
||||||
- **ردیاب پسزمینه** — سرویس ردیابی مداوم ترافیک با تشخیص جغرافیایی
|
|
||||||
- **تنظیمات هر کانتینر** — پیکربندی حداکثر کاربران و پهنای باند برای هر کانتینر
|
|
||||||
- **مدیریت آسان** — دستورات قدرتمند CLI یا منوی تعاملی
|
|
||||||
- **پشتیبانگیری و بازیابی** — پشتیبانگیری و بازیابی کلیدهای هویت نود
|
|
||||||
- **بررسی سلامت** — تشخیص جامع برای عیبیابی
|
|
||||||
- **راهنما و اطلاعات** — راهنمای چندصفحهای داخلی
|
|
||||||
- **حذف کامل** — پاکسازی تمام فایلها و تنظیمات
|
|
||||||
|
|
||||||
## دستورات CLI
|
|
||||||
|
|
||||||
### وضعیت و مانیتورینگ
|
|
||||||
```bash
|
|
||||||
conduit status # نمایش وضعیت و مصرف منابع
|
|
||||||
conduit stats # داشبورد زنده (لحظهای)
|
|
||||||
conduit logs # لاگهای داکر
|
|
||||||
conduit health # بررسی سلامت سیستم
|
|
||||||
conduit peers # ترافیک بر اساس کشور (GeoIP)
|
|
||||||
```
|
|
||||||
|
|
||||||
### پاداش
|
|
||||||
```bash
|
|
||||||
conduit qr # نمایش QR کد برای دریافت پاداش از اپلیکیشن Ryve
|
|
||||||
```
|
|
||||||
|
|
||||||
### مدیریت کانتینر
|
|
||||||
```bash
|
|
||||||
conduit start # شروع تمام کانتینرها
|
|
||||||
conduit stop # توقف تمام کانتینرها
|
|
||||||
conduit restart # ریستارت تمام کانتینرها
|
|
||||||
conduit update # بهروزرسانی به آخرین نسخه
|
|
||||||
```
|
|
||||||
|
|
||||||
### پیکربندی
|
|
||||||
```bash
|
|
||||||
conduit settings # تغییر تنظیمات هر کانتینر
|
|
||||||
conduit menu # منوی تعاملی
|
|
||||||
```
|
|
||||||
|
|
||||||
### پشتیبانگیری و بازیابی
|
|
||||||
```bash
|
|
||||||
conduit backup # پشتیبانگیری از کلیدهای نود
|
|
||||||
conduit restore # بازیابی کلیدهای نود از پشتیبان
|
|
||||||
```
|
|
||||||
|
|
||||||
### نگهداری
|
|
||||||
```bash
|
|
||||||
conduit uninstall # حذف کامل
|
|
||||||
conduit version # نمایش نسخه
|
|
||||||
conduit help # راهنما
|
|
||||||
```
|
|
||||||
|
|
||||||
## منوی تعاملی
|
|
||||||
|
|
||||||
| گزینه | توضیحات |
|
|
||||||
|-------|---------|
|
|
||||||
| **1** | داشبورد وضعیت — آمار لحظهای با کلاینتهای فعال و آپلود برتر |
|
|
||||||
| **2** | آمار زنده اتصال — استریم آمار از لاگ داکر |
|
|
||||||
| **3** | مشاهده لاگ — خروجی لاگ داکر |
|
|
||||||
| **4** | ترافیک زنده به تفکیک کشور — جدول ترافیک با سرعت و تعداد کلاینت |
|
|
||||||
| **5** | شروع کاندوییت |
|
|
||||||
| **6** | توقف کاندوییت |
|
|
||||||
| **7** | ریستارت کاندوییت |
|
|
||||||
| **8** | بهروزرسانی ایمیج |
|
|
||||||
| **9** | تنظیمات و ابزارها — پهنای باند، QR کد، پشتیبانگیری، بازیابی، بررسی سلامت، حذف نصب |
|
|
||||||
| **c** | مدیریت کانتینرها — اضافه یا حذف (تا ۵) |
|
|
||||||
| **a** | آمار پیشرفته — نمودار برترین کشورها |
|
|
||||||
| **i** | راهنما — توضیحات ردیاب، آمار، کانتینرها، حریم خصوصی |
|
|
||||||
| **0** | خروج |
|
|
||||||
|
|
||||||
## تنظیمات
|
|
||||||
|
|
||||||
| گزینه | پیشفرض | محدوده | توضیحات |
|
|
||||||
|-------|---------|--------|---------|
|
|
||||||
| `max-clients` | 200 | ۱–۱۰۰۰ | حداکثر کاربران همزمان برای هر کانتینر |
|
|
||||||
| `bandwidth` | 5 | ۱–۴۰ یا ۱- | محدودیت پهنای باند (Mbps). برای نامحدود ۱- وارد کنید. |
|
|
||||||
|
|
||||||
**مقادیر پیشنهادی بر اساس سختافزار سرور:**
|
|
||||||
|
|
||||||
| پردازنده | رم | کانتینر پیشنهادی | حداکثر کاربران (هر کانتینر) |
|
|
||||||
|----------|-----|-------------------|----------------------------|
|
|
||||||
| ۱ هسته | کمتر از ۱ گیگ | ۱ | ۱۰۰ |
|
|
||||||
| ۲ هسته | ۲ گیگ | ۱–۲ | ۲۰۰ |
|
|
||||||
| ۴ هسته | ۴ گیگ+ | ۲–۳ | ۴۰۰ |
|
|
||||||
| ۸+ هسته | ۸ گیگ+ | ۳–۵ | ۸۰۰ |
|
|
||||||
|
|
||||||
## ارتقا از نسخه 1.0.x
|
|
||||||
|
|
||||||
فقط اسکریپت جدید را اجرا کنید. وقتی سوال پرسیده شد، گزینه **«Open management menu»** را انتخاب کنید. کانتینر موجود شما به صورت خودکار شناسایی میشود. نیازی به نصب مجدد نیست.
|
|
||||||
|
|
||||||
## پیشنیازها
|
|
||||||
|
|
||||||
- سرور لینوکس
|
|
||||||
- دسترسی root یا sudo
|
|
||||||
- اتصال اینترنت
|
|
||||||
- حداقل ۵۱۲ مگابایت رم (۱ گیگ+ برای چند کانتینر پیشنهاد میشود)
|
|
||||||
|
|
||||||
## نحوه عملکرد
|
|
||||||
|
|
||||||
1. **تشخیص** — شناسایی توزیع لینوکس و سیستم init
|
|
||||||
2. **نصب داکر** — در صورت نبود، داکر نصب میشود
|
|
||||||
3. **بررسی سختافزار** — تشخیص CPU و RAM و پیشنهاد تعداد کانتینر
|
|
||||||
4. **راهاندازی کانتینر** — دانلود و اجرای ایمیج رسمی سایفون
|
|
||||||
5. **پیکربندی سرویس** — تنظیم سرویس خودکار (systemd/OpenRC/SysVinit)
|
|
||||||
6. **سرویس ردیاب** — شروع ردیاب ترافیک پسزمینه
|
|
||||||
7. **نصب CLI** — ایجاد دستور مدیریت `conduit`
|
|
||||||
|
|
||||||
## دریافت پاداش (توکن OAT)
|
|
||||||
|
|
||||||
اپراتورهای نود کاندوییت میتوانند با مشارکت در شبکه سایفون توکن OAT کسب کنند. مراحل دریافت پاداش:
|
|
||||||
|
|
||||||
1. **اپلیکیشن Ryve** را روی گوشی نصب کنید
|
|
||||||
2. **یک کیف پول کریپتو** در اپلیکیشن بسازید
|
|
||||||
3. **کانتینرهای خود را لینک کنید** با اسکن QR کد:
|
|
||||||
- از منو تنظیمات: **گزینه ۶ ← نمایش QR کد و شناسه کاندوییت**
|
|
||||||
- از مدیریت کانتینرها: کلید **[q]** را بزنید
|
|
||||||
- CLI: `conduit qr`
|
|
||||||
4. **QR کد را اسکن کنید** با اپلیکیشن Ryve تا نود شما لینک شود
|
|
||||||
5. **مانیتور و کسب درآمد** — اپلیکیشن فعالیت ۴۸ ساعت اخیر و توکنهای OAT را نمایش میدهد
|
|
||||||
|
|
||||||
> هر کانتینر شناسه و QR کد منحصر به فرد خود را دارد. اگر چند کانتینر اجرا میکنید، باید هر کدام را جداگانه لینک کنید.
|
|
||||||
|
|
||||||
## امنیت
|
|
||||||
|
|
||||||
- **پشتیبانگیری امن**: کلیدهای هویت نود با دسترسی محدود (600) ذخیره میشوند
|
|
||||||
- **بدون تلمتری**: هیچ دادهای جمعآوری یا ارسال نمیشود
|
|
||||||
- **ردیابی محلی**: آمار ترافیک فقط به صورت محلی ذخیره شده و هرگز ارسال نمیشود
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -394,6 +156,8 @@ MIT License
|
|||||||
|
|
||||||
Pull requests welcome. For major changes, open an issue first.
|
Pull requests welcome. For major changes, open an issue first.
|
||||||
|
|
||||||
|
This is a **beta release** — please report any issues.
|
||||||
|
|
||||||
## Links
|
## Links
|
||||||
|
|
||||||
- [Psiphon](https://psiphon.ca/)
|
- [Psiphon](https://psiphon.ca/)
|
||||||
|
|||||||
743
conduit.sh
743
conduit.sh
@@ -31,7 +31,7 @@ if [ -z "$BASH_VERSION" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
VERSION="1.1"
|
VERSION="1.2-Beta"
|
||||||
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest"
|
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest"
|
||||||
INSTALL_DIR="${INSTALL_DIR:-/opt/conduit}"
|
INSTALL_DIR="${INSTALL_DIR:-/opt/conduit}"
|
||||||
BACKUP_DIR="$INSTALL_DIR/backups"
|
BACKUP_DIR="$INSTALL_DIR/backups"
|
||||||
@@ -679,6 +679,15 @@ run_conduit() {
|
|||||||
|
|
||||||
save_settings_install() {
|
save_settings_install() {
|
||||||
mkdir -p "$INSTALL_DIR"
|
mkdir -p "$INSTALL_DIR"
|
||||||
|
# Preserve existing Telegram settings on reinstall
|
||||||
|
local _tg_token="" _tg_chat="" _tg_interval="6" _tg_enabled="false"
|
||||||
|
if [ -f "$INSTALL_DIR/settings.conf" ]; then
|
||||||
|
source "$INSTALL_DIR/settings.conf" 2>/dev/null
|
||||||
|
_tg_token="${TELEGRAM_BOT_TOKEN:-}"
|
||||||
|
_tg_chat="${TELEGRAM_CHAT_ID:-}"
|
||||||
|
_tg_interval="${TELEGRAM_INTERVAL:-6}"
|
||||||
|
_tg_enabled="${TELEGRAM_ENABLED:-false}"
|
||||||
|
fi
|
||||||
cat > "$INSTALL_DIR/settings.conf" << EOF
|
cat > "$INSTALL_DIR/settings.conf" << EOF
|
||||||
MAX_CLIENTS=$MAX_CLIENTS
|
MAX_CLIENTS=$MAX_CLIENTS
|
||||||
BANDWIDTH=$BANDWIDTH
|
BANDWIDTH=$BANDWIDTH
|
||||||
@@ -688,6 +697,10 @@ DATA_CAP_IFACE=
|
|||||||
DATA_CAP_BASELINE_RX=0
|
DATA_CAP_BASELINE_RX=0
|
||||||
DATA_CAP_BASELINE_TX=0
|
DATA_CAP_BASELINE_TX=0
|
||||||
DATA_CAP_PRIOR_USAGE=0
|
DATA_CAP_PRIOR_USAGE=0
|
||||||
|
TELEGRAM_BOT_TOKEN="$_tg_token"
|
||||||
|
TELEGRAM_CHAT_ID="$_tg_chat"
|
||||||
|
TELEGRAM_INTERVAL=$_tg_interval
|
||||||
|
TELEGRAM_ENABLED=$_tg_enabled
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
chmod 600 "$INSTALL_DIR/settings.conf" 2>/dev/null || true
|
chmod 600 "$INSTALL_DIR/settings.conf" 2>/dev/null || true
|
||||||
@@ -810,7 +823,7 @@ create_management_script() {
|
|||||||
# Reference: https://github.com/ssmirr/conduit/releases/latest
|
# Reference: https://github.com/ssmirr/conduit/releases/latest
|
||||||
#
|
#
|
||||||
|
|
||||||
VERSION="1.1"
|
VERSION="1.2-Beta"
|
||||||
INSTALL_DIR="REPLACE_ME_INSTALL_DIR"
|
INSTALL_DIR="REPLACE_ME_INSTALL_DIR"
|
||||||
BACKUP_DIR="$INSTALL_DIR/backups"
|
BACKUP_DIR="$INSTALL_DIR/backups"
|
||||||
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest"
|
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest"
|
||||||
@@ -835,6 +848,10 @@ DATA_CAP_IFACE=${DATA_CAP_IFACE:-}
|
|||||||
DATA_CAP_BASELINE_RX=${DATA_CAP_BASELINE_RX:-0}
|
DATA_CAP_BASELINE_RX=${DATA_CAP_BASELINE_RX:-0}
|
||||||
DATA_CAP_BASELINE_TX=${DATA_CAP_BASELINE_TX:-0}
|
DATA_CAP_BASELINE_TX=${DATA_CAP_BASELINE_TX:-0}
|
||||||
DATA_CAP_PRIOR_USAGE=${DATA_CAP_PRIOR_USAGE:-0}
|
DATA_CAP_PRIOR_USAGE=${DATA_CAP_PRIOR_USAGE:-0}
|
||||||
|
TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
|
||||||
|
TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID:-}
|
||||||
|
TELEGRAM_INTERVAL=${TELEGRAM_INTERVAL:-6}
|
||||||
|
TELEGRAM_ENABLED=${TELEGRAM_ENABLED:-false}
|
||||||
|
|
||||||
# Ensure we're running as root
|
# Ensure we're running as root
|
||||||
if [ "$EUID" -ne 0 ]; then
|
if [ "$EUID" -ne 0 ]; then
|
||||||
@@ -1155,7 +1172,7 @@ show_dashboard() {
|
|||||||
[ "$pct" -gt 100 ] && pct=100
|
[ "$pct" -gt 100 ] && pct=100
|
||||||
local bl=$((pct / 20)); [ "$bl" -lt 1 ] && bl=1; [ "$bl" -gt 5 ] && bl=5
|
local bl=$((pct / 20)); [ "$bl" -lt 1 ] && bl=1; [ "$bl" -gt 5 ] && bl=5
|
||||||
local bf=""; local bp=""; for ((bi=0; bi<bl; bi++)); do bf+="█"; done; for ((bi=bl; bi<5; bi++)); do bp+=" "; done
|
local bf=""; local bp=""; for ((bi=0; bi<bl; bi++)); do bf+="█"; done; for ((bi=bl; bi<5; bi++)); do bp+=" "; done
|
||||||
left_lines+=("$(printf "%-11.11s %3d%% \033[32m%s%s\033[0m %5d" "$country" "$pct" "$bf" "$bp" "$est")")
|
left_lines+=("$(printf "%-11.11s %3d%% \033[32m%s%s\033[0m %5s" "$country" "$pct" "$bf" "$bp" "$(format_number $est)")")
|
||||||
done <<< "$snap_data"
|
done <<< "$snap_data"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -1418,6 +1435,19 @@ format_bytes() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
format_number() {
|
||||||
|
local n=$1
|
||||||
|
if [ -z "$n" ] || [ "$n" -eq 0 ] 2>/dev/null; then
|
||||||
|
echo "0"
|
||||||
|
elif [ "$n" -ge 1000000 ]; then
|
||||||
|
awk "BEGIN {printf \"%.1fM\", $n/1000000}"
|
||||||
|
elif [ "$n" -ge 1000 ]; then
|
||||||
|
awk "BEGIN {printf \"%.1fK\", $n/1000}"
|
||||||
|
else
|
||||||
|
echo "$n"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Background tracker helper
|
# Background tracker helper
|
||||||
is_tracker_active() {
|
is_tracker_active() {
|
||||||
if command -v systemctl &>/dev/null; then
|
if command -v systemctl &>/dev/null; then
|
||||||
@@ -1689,6 +1719,12 @@ check_stuck_containers() {
|
|||||||
if docker restart "$cname" >/dev/null 2>&1; then
|
if docker restart "$cname" >/dev/null 2>&1; then
|
||||||
CONTAINER_LAST_RESTART[$cname]=$now
|
CONTAINER_LAST_RESTART[$cname]=$now
|
||||||
CONTAINER_LAST_ACTIVE[$cname]=$now
|
CONTAINER_LAST_ACTIVE[$cname]=$now
|
||||||
|
# Send Telegram alert if enabled
|
||||||
|
if [ "$TELEGRAM_ENABLED" = "true" ] && [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
|
||||||
|
local safe_cname=$(escape_telegram_markdown "$cname")
|
||||||
|
telegram_send_message "⚠️ *Conduit Alert*
|
||||||
|
Container ${safe_cname} was stuck (no peers for $((idle_time/3600))h) and has been auto-restarted."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@@ -2004,7 +2040,7 @@ show_advanced_stats() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local tstat="${RED}Off${NC}"; is_tracker_active && tstat="${GREEN}On${NC}"
|
local tstat="${RED}Off${NC}"; is_tracker_active && tstat="${GREEN}On${NC}"
|
||||||
printf "${CYAN}║${NC} Tracker: %b Clients: ${GREEN}%d${NC} Unique IPs: ${YELLOW}%d${NC} In: ${GREEN}%s${NC} Out: ${YELLOW}%s${NC}\033[K\n" "$tstat" "$total_conn" "$total_active" "$(format_bytes $total_in)" "$(format_bytes $total_out)"
|
printf "${CYAN}║${NC} Tracker: %b Clients: ${GREEN}%s${NC} Unique IPs: ${YELLOW}%s${NC} In: ${GREEN}%s${NC} Out: ${YELLOW}%s${NC}\033[K\n" "$tstat" "$(format_number $total_conn)" "$(format_number $total_active)" "$(format_bytes $total_in)" "$(format_bytes $total_out)"
|
||||||
|
|
||||||
# TOP 5 by Unique IPs (from tracker)
|
# TOP 5 by Unique IPs (from tracker)
|
||||||
echo -e "${CYAN}╠─── ${CYAN}TOP 5 BY UNIQUE IPs${NC} ${DIM}(tracked)${NC}\033[K"
|
echo -e "${CYAN}╠─── ${CYAN}TOP 5 BY UNIQUE IPs${NC} ${DIM}(tracked)${NC}\033[K"
|
||||||
@@ -2016,7 +2052,7 @@ show_advanced_stats() {
|
|||||||
local pct=$((peers * 100 / total_conn))
|
local pct=$((peers * 100 / total_conn))
|
||||||
local blen=$((pct / 8)); [ "$blen" -lt 1 ] && blen=1; [ "$blen" -gt 14 ] && blen=14
|
local blen=$((pct / 8)); [ "$blen" -lt 1 ] && blen=1; [ "$blen" -gt 14 ] && blen=14
|
||||||
local bfill=""; for ((i=0; i<blen; i++)); do bfill+="█"; done
|
local bfill=""; for ((i=0; i<blen; i++)); do bfill+="█"; done
|
||||||
printf "${CYAN}║${NC} %-16.16s %3d%% ${CYAN}%-14s${NC} (%d IPs)\033[K\n" "$country" "$pct" "$bfill" "$peers"
|
printf "${CYAN}║${NC} %-16.16s %3d%% ${CYAN}%-14s${NC} (%s IPs)\033[K\n" "$country" "$pct" "$bfill" "$(format_number $peers)"
|
||||||
done
|
done
|
||||||
elif [ "$total_traffic" -gt 0 ]; then
|
elif [ "$total_traffic" -gt 0 ]; then
|
||||||
for c in "${!cbw_in[@]}"; do
|
for c in "${!cbw_in[@]}"; do
|
||||||
@@ -2217,7 +2253,7 @@ show_peers() {
|
|||||||
est_clients=$(( (snap_cnt * total_clients) / snap_total_from_ips ))
|
est_clients=$(( (snap_cnt * total_clients) / snap_total_from_ips ))
|
||||||
[ "$est_clients" -eq 0 ] && [ "$snap_cnt" -gt 0 ] && est_clients=1
|
[ "$est_clients" -eq 0 ] && [ "$snap_cnt" -gt 0 ] && est_clients=1
|
||||||
fi
|
fi
|
||||||
printf " ${GREEN}%-26.26s${NC} %10s %10s/s %5d/%d${EL}\n" "$country" "$(format_bytes $bytes)" "$speed_str" "$ips_all" "$est_clients"
|
printf " ${GREEN}%-26.26s${NC} %10s %10s/s %5s/%s${EL}\n" "$country" "$(format_bytes $bytes)" "$speed_str" "$(format_number $ips_all)" "$(format_number $est_clients)"
|
||||||
done < <(for c in "${!cumul_from[@]}"; do echo "${cumul_from[$c]:-0}|$c"; done | sort -t'|' -k1 -nr | head -10)
|
done < <(for c in "${!cumul_from[@]}"; do echo "${cumul_from[$c]:-0}|$c"; done | sort -t'|' -k1 -nr | head -10)
|
||||||
else
|
else
|
||||||
echo -e " ${DIM}Waiting for data...${NC}${EL}"
|
echo -e " ${DIM}Waiting for data...${NC}${EL}"
|
||||||
@@ -2242,7 +2278,7 @@ show_peers() {
|
|||||||
est_clients=$(( (snap_cnt * total_clients) / snap_total_to_ips ))
|
est_clients=$(( (snap_cnt * total_clients) / snap_total_to_ips ))
|
||||||
[ "$est_clients" -eq 0 ] && [ "$snap_cnt" -gt 0 ] && est_clients=1
|
[ "$est_clients" -eq 0 ] && [ "$snap_cnt" -gt 0 ] && est_clients=1
|
||||||
fi
|
fi
|
||||||
printf " ${YELLOW}%-26.26s${NC} %10s %10s/s %5d/%d${EL}\n" "$country" "$(format_bytes $bytes)" "$speed_str" "$ips_all" "$est_clients"
|
printf " ${YELLOW}%-26.26s${NC} %10s %10s/s %5s/%s${EL}\n" "$country" "$(format_bytes $bytes)" "$speed_str" "$(format_number $ips_all)" "$(format_number $est_clients)"
|
||||||
done < <(for c in "${!cumul_to[@]}"; do echo "${cumul_to[$c]:-0}|$c"; done | sort -t'|' -k1 -nr | head -10)
|
done < <(for c in "${!cumul_to[@]}"; do echo "${cumul_to[$c]:-0}|$c"; done | sort -t'|' -k1 -nr | head -10)
|
||||||
else
|
else
|
||||||
echo -e " ${DIM}Waiting for data...${NC}${EL}"
|
echo -e " ${DIM}Waiting for data...${NC}${EL}"
|
||||||
@@ -2872,6 +2908,9 @@ show_logs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uninstall_all() {
|
uninstall_all() {
|
||||||
|
telegram_disable_service
|
||||||
|
rm -f /etc/systemd/system/conduit-telegram.service 2>/dev/null
|
||||||
|
systemctl daemon-reload 2>/dev/null || true
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${RED}╔═══════════════════════════════════════════════════════════════════╗${NC}"
|
echo -e "${RED}╔═══════════════════════════════════════════════════════════════════╗${NC}"
|
||||||
echo -e "${RED}║ ⚠️ UNINSTALL CONDUIT ║${NC}"
|
echo -e "${RED}║ ⚠️ UNINSTALL CONDUIT ║${NC}"
|
||||||
@@ -3429,6 +3468,10 @@ DATA_CAP_IFACE=$DATA_CAP_IFACE
|
|||||||
DATA_CAP_BASELINE_RX=$DATA_CAP_BASELINE_RX
|
DATA_CAP_BASELINE_RX=$DATA_CAP_BASELINE_RX
|
||||||
DATA_CAP_BASELINE_TX=$DATA_CAP_BASELINE_TX
|
DATA_CAP_BASELINE_TX=$DATA_CAP_BASELINE_TX
|
||||||
DATA_CAP_PRIOR_USAGE=${DATA_CAP_PRIOR_USAGE:-0}
|
DATA_CAP_PRIOR_USAGE=${DATA_CAP_PRIOR_USAGE:-0}
|
||||||
|
TELEGRAM_BOT_TOKEN="$TELEGRAM_BOT_TOKEN"
|
||||||
|
TELEGRAM_CHAT_ID="$TELEGRAM_CHAT_ID"
|
||||||
|
TELEGRAM_INTERVAL=${TELEGRAM_INTERVAL:-6}
|
||||||
|
TELEGRAM_ENABLED=${TELEGRAM_ENABLED:-false}
|
||||||
EOF
|
EOF
|
||||||
# Save per-container overrides
|
# Save per-container overrides
|
||||||
for i in $(seq 1 5); do
|
for i in $(seq 1 5); do
|
||||||
@@ -3440,6 +3483,452 @@ EOF
|
|||||||
chmod 600 "$INSTALL_DIR/settings.conf" 2>/dev/null || true
|
chmod 600 "$INSTALL_DIR/settings.conf" 2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ─── Telegram Bot Functions ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
escape_telegram_markdown() {
|
||||||
|
local text="$1"
|
||||||
|
text="${text//\\/\\\\}"
|
||||||
|
text="${text//\*/\\*}"
|
||||||
|
text="${text//_/\\_}"
|
||||||
|
text="${text//\`/\\\`}"
|
||||||
|
text="${text//\[/\\[}"
|
||||||
|
text="${text//\]/\\]}"
|
||||||
|
echo "$text"
|
||||||
|
}
|
||||||
|
|
||||||
|
telegram_send_message() {
|
||||||
|
local message="$1"
|
||||||
|
{ [ -z "$TELEGRAM_BOT_TOKEN" ] || [ -z "$TELEGRAM_CHAT_ID" ]; } && return 1
|
||||||
|
local response
|
||||||
|
response=$(curl -s --max-time 10 --max-filesize 1048576 -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
||||||
|
--data-urlencode "chat_id=$TELEGRAM_CHAT_ID" \
|
||||||
|
--data-urlencode "text=$message" \
|
||||||
|
--data-urlencode "parse_mode=Markdown" 2>/dev/null)
|
||||||
|
[ $? -ne 0 ] && return 1
|
||||||
|
echo "$response" | grep -q '"ok":true' && return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
telegram_test_message() {
|
||||||
|
local interval_label="${TELEGRAM_INTERVAL:-6}"
|
||||||
|
local report=$(telegram_build_report)
|
||||||
|
local message="✅ *Conduit Manager Connected!*
|
||||||
|
|
||||||
|
🔗 *What is Psiphon Conduit?*
|
||||||
|
You are running a Psiphon relay node that helps people in censored regions access the open internet.
|
||||||
|
|
||||||
|
📬 *What this bot sends you every ${interval_label}h:*
|
||||||
|
• Container status & uptime
|
||||||
|
• Connected peers count
|
||||||
|
• Upload & download totals
|
||||||
|
• CPU & RAM usage
|
||||||
|
• Data cap usage (if set)
|
||||||
|
• Top countries being served
|
||||||
|
|
||||||
|
⚠️ *Alerts:*
|
||||||
|
If a container gets stuck and is auto-restarted, you will receive an immediate alert.
|
||||||
|
|
||||||
|
━━━━━━━━━━━━━━━━━━━━
|
||||||
|
📊 *Your first report:*
|
||||||
|
━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
${report}"
|
||||||
|
telegram_send_message "$message"
|
||||||
|
}
|
||||||
|
|
||||||
|
telegram_get_chat_id() {
|
||||||
|
local response
|
||||||
|
response=$(curl -s --max-time 10 --max-filesize 1048576 "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/getUpdates" 2>/dev/null)
|
||||||
|
[ -z "$response" ] && return 1
|
||||||
|
# Verify API returned success
|
||||||
|
echo "$response" | grep -q '"ok":true' || return 1
|
||||||
|
# Extract chat id: find "message"..."chat":{"id":NUMBER pattern
|
||||||
|
# Use python if available for reliable JSON parsing, fall back to grep
|
||||||
|
local chat_id=""
|
||||||
|
if command -v python3 &>/dev/null; then
|
||||||
|
chat_id=$(python3 -c "
|
||||||
|
import json,sys
|
||||||
|
try:
|
||||||
|
d=json.loads(sys.stdin.read())
|
||||||
|
msgs=d.get('result',[])
|
||||||
|
if msgs:
|
||||||
|
print(msgs[-1]['message']['chat']['id'])
|
||||||
|
except: pass
|
||||||
|
" <<< "$response" 2>/dev/null)
|
||||||
|
fi
|
||||||
|
# Fallback: POSIX-compatible grep extraction
|
||||||
|
if [ -z "$chat_id" ]; then
|
||||||
|
chat_id=$(echo "$response" | grep -o '"chat"[[:space:]]*:[[:space:]]*{[[:space:]]*"id"[[:space:]]*:[[:space:]]*-*[0-9]*' | grep -o -- '-*[0-9]*$' | tail -1 2>/dev/null)
|
||||||
|
fi
|
||||||
|
if [ -n "$chat_id" ]; then
|
||||||
|
# Validate chat_id is numeric (with optional leading minus for groups)
|
||||||
|
if ! echo "$chat_id" | grep -qE '^-?[0-9]+$'; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
TELEGRAM_CHAT_ID="$chat_id"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
telegram_build_report() {
|
||||||
|
local report="📊 *Conduit Status Report*"
|
||||||
|
report+=$'\n'
|
||||||
|
report+="🕐 $(date '+%Y-%m-%d %H:%M %Z')"
|
||||||
|
report+=$'\n'
|
||||||
|
report+=$'\n'
|
||||||
|
|
||||||
|
# Container status & uptime (check all containers, use earliest start)
|
||||||
|
local running_count=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^conduit" || echo 0)
|
||||||
|
local total=$CONTAINER_COUNT
|
||||||
|
if [ "$running_count" -gt 0 ]; then
|
||||||
|
local earliest_start=""
|
||||||
|
for i in $(seq 1 $CONTAINER_COUNT); do
|
||||||
|
local cname=$(get_container_name $i)
|
||||||
|
local started=$(docker inspect --format='{{.State.StartedAt}}' "$cname" 2>/dev/null | cut -d'.' -f1)
|
||||||
|
if [ -n "$started" ]; then
|
||||||
|
local se=$(date -d "$started" +%s 2>/dev/null || echo 0)
|
||||||
|
if [ -z "$earliest_start" ] || [ "$se" -lt "$earliest_start" ] 2>/dev/null; then
|
||||||
|
earliest_start=$se
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -n "$earliest_start" ] && [ "$earliest_start" -gt 0 ] 2>/dev/null; then
|
||||||
|
local now=$(date +%s)
|
||||||
|
local up=$((now - earliest_start))
|
||||||
|
local days=$((up / 86400))
|
||||||
|
local hours=$(( (up % 86400) / 3600 ))
|
||||||
|
local mins=$(( (up % 3600) / 60 ))
|
||||||
|
if [ "$days" -gt 0 ]; then
|
||||||
|
report+="⏱ Uptime: ${days}d ${hours}h ${mins}m"
|
||||||
|
else
|
||||||
|
report+="⏱ Uptime: ${hours}h ${mins}m"
|
||||||
|
fi
|
||||||
|
report+=$'\n'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
report+="📦 Containers: ${running_count}/${total} running"
|
||||||
|
report+=$'\n'
|
||||||
|
|
||||||
|
# Connected peers (use awk like show_status does)
|
||||||
|
local total_peers=0
|
||||||
|
for i in $(seq 1 $CONTAINER_COUNT); do
|
||||||
|
local cname=$(get_container_name $i)
|
||||||
|
local last_stat=$(docker logs --tail 50 "$cname" 2>&1 | grep "\[STATS\]" | tail -1)
|
||||||
|
local peers=$(echo "$last_stat" | awk '{for(j=1;j<=NF;j++){if($j=="Connected:") print $(j+1)+0}}' | head -1)
|
||||||
|
total_peers=$((total_peers + ${peers:-0}))
|
||||||
|
done
|
||||||
|
report+="👥 Peers: ${total_peers} connected"
|
||||||
|
report+=$'\n'
|
||||||
|
|
||||||
|
# CPU / RAM (normalize CPU by core count like dashboard)
|
||||||
|
local stats=$(get_container_stats)
|
||||||
|
local raw_cpu=$(echo "$stats" | awk '{print $1}')
|
||||||
|
local cores=$(get_cpu_cores)
|
||||||
|
local cpu=$(awk "BEGIN {printf \"%.1f%%\", ${raw_cpu%\%} / $cores}" 2>/dev/null || echo "$raw_cpu")
|
||||||
|
local ram=$(echo "$stats" | awk '{print $2, $3, $4}')
|
||||||
|
cpu=$(escape_telegram_markdown "$cpu")
|
||||||
|
ram=$(escape_telegram_markdown "$ram")
|
||||||
|
report+="🖥 CPU: ${cpu} | RAM: ${ram}"
|
||||||
|
report+=$'\n'
|
||||||
|
|
||||||
|
# Data usage
|
||||||
|
if [ "$DATA_CAP_GB" -gt 0 ] 2>/dev/null; then
|
||||||
|
local usage=$(get_data_usage 2>/dev/null)
|
||||||
|
local used_rx=$(echo "$usage" | awk '{print $1}')
|
||||||
|
local used_tx=$(echo "$usage" | awk '{print $2}')
|
||||||
|
local total_used=$(( ${used_rx:-0} + ${used_tx:-0} + ${DATA_CAP_PRIOR_USAGE:-0} ))
|
||||||
|
local used_gb=$(awk "BEGIN {printf \"%.2f\", $total_used/1073741824}" 2>/dev/null || echo "0")
|
||||||
|
report+="📈 Data: ${used_gb} GB / ${DATA_CAP_GB} GB"
|
||||||
|
report+=$'\n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Top countries from cumulative_data (field 3 = upload bytes, matching dashboard)
|
||||||
|
local data_file="$INSTALL_DIR/traffic_stats/cumulative_data"
|
||||||
|
if [ -s "$data_file" ]; then
|
||||||
|
local top_countries
|
||||||
|
top_countries=$(awk -F'|' '{if($1!="" && $3+0>0) bytes[$1]+=$3+0} END{for(c in bytes) print bytes[c]"|"c}' "$data_file" 2>/dev/null | sort -t'|' -k1 -nr | head -3)
|
||||||
|
if [ -n "$top_countries" ]; then
|
||||||
|
report+="🌍 Top countries:"
|
||||||
|
report+=$'\n'
|
||||||
|
while IFS='|' read -r bytes country; do
|
||||||
|
[ -z "$country" ] && continue
|
||||||
|
local safe_country=$(escape_telegram_markdown "$country")
|
||||||
|
local fmt=$(format_bytes "$bytes" 2>/dev/null || echo "${bytes} B")
|
||||||
|
report+=" • ${safe_country} (${fmt})"
|
||||||
|
report+=$'\n'
|
||||||
|
done <<< "$top_countries"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Active clients from tracker_snapshot
|
||||||
|
local snapshot_file="$INSTALL_DIR/traffic_stats/tracker_snapshot"
|
||||||
|
if [ -s "$snapshot_file" ]; then
|
||||||
|
local active_clients=$(wc -l < "$snapshot_file" 2>/dev/null || echo 0)
|
||||||
|
report+="📡 Active clients: ${active_clients}"
|
||||||
|
report+=$'\n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Total bandwidth served from cumulative_data
|
||||||
|
if [ -s "$data_file" ]; then
|
||||||
|
local total_bw
|
||||||
|
total_bw=$(awk -F'|' '{s+=$2+0; s+=$3+0} END{printf "%.0f", s}' "$data_file" 2>/dev/null || echo 0)
|
||||||
|
if [ "${total_bw:-0}" -gt 0 ] 2>/dev/null; then
|
||||||
|
local total_bw_fmt=$(format_bytes "$total_bw" 2>/dev/null || echo "${total_bw} B")
|
||||||
|
report+="📊 Total bandwidth served: ${total_bw_fmt}"
|
||||||
|
report+=$'\n'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$report"
|
||||||
|
}
|
||||||
|
|
||||||
|
telegram_generate_notify_script() {
|
||||||
|
cat > "$INSTALL_DIR/conduit-telegram.sh" << 'TGEOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# Conduit Telegram Notification Service
|
||||||
|
# Runs as a systemd service, sends periodic status reports
|
||||||
|
|
||||||
|
INSTALL_DIR="/opt/conduit"
|
||||||
|
|
||||||
|
[ -f "$INSTALL_DIR/settings.conf" ] && source "$INSTALL_DIR/settings.conf"
|
||||||
|
|
||||||
|
# Exit if not configured
|
||||||
|
[ "$TELEGRAM_ENABLED" != "true" ] && exit 0
|
||||||
|
[ -z "$TELEGRAM_BOT_TOKEN" ] && exit 0
|
||||||
|
[ -z "$TELEGRAM_CHAT_ID" ] && exit 0
|
||||||
|
|
||||||
|
telegram_send() {
|
||||||
|
local message="$1"
|
||||||
|
curl -s --max-time 10 --max-filesize 1048576 -X POST \
|
||||||
|
"https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
|
||||||
|
--data-urlencode "chat_id=$TELEGRAM_CHAT_ID" \
|
||||||
|
--data-urlencode "text=$message" \
|
||||||
|
--data-urlencode "parse_mode=Markdown" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
escape_md() {
|
||||||
|
local text="$1"
|
||||||
|
text="${text//\\/\\\\}"
|
||||||
|
text="${text//\*/\\*}"
|
||||||
|
text="${text//_/\\_}"
|
||||||
|
text="${text//\`/\\\`}"
|
||||||
|
text="${text//\[/\\[}"
|
||||||
|
text="${text//\]/\\]}"
|
||||||
|
echo "$text"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_container_name() {
|
||||||
|
local i=$1
|
||||||
|
if [ "$i" -le 1 ]; then
|
||||||
|
echo "conduit"
|
||||||
|
else
|
||||||
|
echo "conduit${i}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_cpu_cores() {
|
||||||
|
local cores=1
|
||||||
|
if command -v nproc &>/dev/null; then
|
||||||
|
cores=$(nproc)
|
||||||
|
elif [ -f /proc/cpuinfo ]; then
|
||||||
|
cores=$(grep -c '^processor' /proc/cpuinfo 2>/dev/null || echo 1)
|
||||||
|
fi
|
||||||
|
[ "$cores" -lt 1 ] 2>/dev/null && cores=1
|
||||||
|
echo "$cores"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_report() {
|
||||||
|
local report="📊 *Conduit Status Report*"
|
||||||
|
report+=$'\n'
|
||||||
|
report+="🕐 $(date '+%Y-%m-%d %H:%M %Z')"
|
||||||
|
report+=$'\n'
|
||||||
|
report+=$'\n'
|
||||||
|
|
||||||
|
# Container status + uptime
|
||||||
|
local running=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -c "^conduit" || echo 0)
|
||||||
|
local total=${CONTAINER_COUNT:-1}
|
||||||
|
report+="📦 Containers: ${running}/${total} running"
|
||||||
|
report+=$'\n'
|
||||||
|
|
||||||
|
# Uptime from earliest container
|
||||||
|
local earliest_start=""
|
||||||
|
for i in $(seq 1 ${CONTAINER_COUNT:-1}); do
|
||||||
|
local cname=$(get_container_name $i)
|
||||||
|
local started=$(docker inspect --format='{{.State.StartedAt}}' "$cname" 2>/dev/null)
|
||||||
|
[ -z "$started" ] && continue
|
||||||
|
local se=$(date -d "$started" +%s 2>/dev/null || echo 0)
|
||||||
|
if [ -z "$earliest_start" ] || [ "$se" -lt "$earliest_start" ] 2>/dev/null; then
|
||||||
|
earliest_start=$se
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -n "$earliest_start" ] && [ "$earliest_start" -gt 0 ] 2>/dev/null; then
|
||||||
|
local now=$(date +%s)
|
||||||
|
local diff=$((now - earliest_start))
|
||||||
|
local days=$((diff / 86400))
|
||||||
|
local hours=$(( (diff % 86400) / 3600 ))
|
||||||
|
local mins=$(( (diff % 3600) / 60 ))
|
||||||
|
report+="⏱ Uptime: ${days}d ${hours}h ${mins}m"
|
||||||
|
report+=$'\n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Peers
|
||||||
|
local total_peers=0
|
||||||
|
for i in $(seq 1 ${CONTAINER_COUNT:-1}); do
|
||||||
|
local cname=$(get_container_name $i)
|
||||||
|
local last_stat=$(docker logs --tail 50 "$cname" 2>&1 | grep "\[STATS\]" | tail -1)
|
||||||
|
local peers=$(echo "$last_stat" | awk '{for(j=1;j<=NF;j++){if($j=="Connected:") print $(j+1)+0}}' | head -1)
|
||||||
|
total_peers=$((total_peers + ${peers:-0}))
|
||||||
|
done
|
||||||
|
report+="👥 Peers: ${total_peers} connected"
|
||||||
|
report+=$'\n'
|
||||||
|
|
||||||
|
# Active unique clients
|
||||||
|
local snapshot_file="$INSTALL_DIR/traffic_stats/tracker_snapshot"
|
||||||
|
if [ -s "$snapshot_file" ]; then
|
||||||
|
local active_clients=$(wc -l < "$snapshot_file" 2>/dev/null || echo 0)
|
||||||
|
report+="👤 Active clients: ${active_clients} unique IPs"
|
||||||
|
report+=$'\n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Total bandwidth served (all-time from cumulative_data)
|
||||||
|
local data_file_bw="$INSTALL_DIR/traffic_stats/cumulative_data"
|
||||||
|
if [ -s "$data_file_bw" ]; then
|
||||||
|
local total_bytes=$(awk -F'|' '{s+=$2+$3} END{print s+0}' "$data_file_bw" 2>/dev/null)
|
||||||
|
local total_served=""
|
||||||
|
if [ "${total_bytes:-0}" -gt 0 ] 2>/dev/null; then
|
||||||
|
total_served=$(awk "BEGIN {b=$total_bytes; if(b>1099511627776) printf \"%.2f TB\",b/1099511627776; else if(b>1073741824) printf \"%.2f GB\",b/1073741824; else printf \"%.1f MB\",b/1048576}" 2>/dev/null)
|
||||||
|
report+="📡 Total served: ${total_served}"
|
||||||
|
report+=$'\n'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# CPU / RAM
|
||||||
|
local stats=$(docker stats --no-stream --format "{{.CPUPerc}} {{.MemUsage}}" $(docker ps --format '{{.Names}}' 2>/dev/null | grep "^conduit") 2>/dev/null | head -1)
|
||||||
|
local raw_cpu=$(echo "$stats" | awk '{print $1}')
|
||||||
|
local cores=$(get_cpu_cores)
|
||||||
|
local cpu=$(awk "BEGIN {printf \"%.1f%%\", ${raw_cpu%\%} / $cores}" 2>/dev/null || echo "$raw_cpu")
|
||||||
|
local ram=$(echo "$stats" | awk '{print $2, $3, $4}')
|
||||||
|
cpu=$(escape_md "$cpu")
|
||||||
|
ram=$(escape_md "$ram")
|
||||||
|
report+="🖥 CPU: ${cpu} | RAM: ${ram}"
|
||||||
|
report+=$'\n'
|
||||||
|
|
||||||
|
# Data usage
|
||||||
|
if [ "${DATA_CAP_GB:-0}" -gt 0 ] 2>/dev/null; then
|
||||||
|
local iface="${DATA_CAP_IFACE:-eth0}"
|
||||||
|
local rx=$(cat /sys/class/net/$iface/statistics/rx_bytes 2>/dev/null || echo 0)
|
||||||
|
local tx=$(cat /sys/class/net/$iface/statistics/tx_bytes 2>/dev/null || echo 0)
|
||||||
|
local total_used=$(( rx + tx + ${DATA_CAP_PRIOR_USAGE:-0} ))
|
||||||
|
local used_gb=$(awk "BEGIN {printf \"%.2f\", $total_used/1073741824}" 2>/dev/null || echo "0")
|
||||||
|
report+="📈 Data: ${used_gb} GB / ${DATA_CAP_GB} GB"
|
||||||
|
report+=$'\n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Top countries
|
||||||
|
local data_file="$INSTALL_DIR/traffic_stats/cumulative_data"
|
||||||
|
if [ -s "$data_file" ]; then
|
||||||
|
local top_countries
|
||||||
|
top_countries=$(awk -F'|' '{if($1!="" && $3+0>0) bytes[$1]+=$3+0} END{for(c in bytes) print bytes[c]"|"c}' "$data_file" 2>/dev/null | sort -t'|' -k1 -nr | head -3)
|
||||||
|
if [ -n "$top_countries" ]; then
|
||||||
|
report+="🌍 Top countries:"
|
||||||
|
report+=$'\n'
|
||||||
|
local total_upload=$(awk -F'|' '{s+=$3+0} END{print s+0}' "$data_file" 2>/dev/null)
|
||||||
|
while IFS='|' read -r bytes country; do
|
||||||
|
[ -z "$country" ] && continue
|
||||||
|
local pct=0
|
||||||
|
[ "$total_upload" -gt 0 ] 2>/dev/null && pct=$(awk "BEGIN {printf \"%.0f\", ($bytes/$total_upload)*100}" 2>/dev/null || echo 0)
|
||||||
|
local safe_country=$(escape_md "$country")
|
||||||
|
local fmt=$(awk "BEGIN {b=$bytes; if(b>1073741824) printf \"%.1f GB\",b/1073741824; else if(b>1048576) printf \"%.1f MB\",b/1048576; else printf \"%.1f KB\",b/1024}" 2>/dev/null)
|
||||||
|
report+=" • ${safe_country}: ${pct}% (${fmt})"
|
||||||
|
report+=$'\n'
|
||||||
|
done <<< "$top_countries"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$report"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main loop
|
||||||
|
elapsed=0
|
||||||
|
interval_secs=$(( ${TELEGRAM_INTERVAL:-6} * 3600 ))
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
sleep 60
|
||||||
|
elapsed=$((elapsed + 60))
|
||||||
|
|
||||||
|
# Re-read settings
|
||||||
|
[ -f "$INSTALL_DIR/settings.conf" ] && source "$INSTALL_DIR/settings.conf"
|
||||||
|
|
||||||
|
# Exit if disabled
|
||||||
|
[ "$TELEGRAM_ENABLED" != "true" ] && exit 0
|
||||||
|
[ -z "$TELEGRAM_BOT_TOKEN" ] && exit 0
|
||||||
|
|
||||||
|
# Update interval
|
||||||
|
interval_secs=$(( ${TELEGRAM_INTERVAL:-6} * 3600 ))
|
||||||
|
|
||||||
|
if [ "$elapsed" -ge "$interval_secs" ]; then
|
||||||
|
report=$(build_report)
|
||||||
|
telegram_send "$report"
|
||||||
|
elapsed=0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
TGEOF
|
||||||
|
chmod 700 "$INSTALL_DIR/conduit-telegram.sh"
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_telegram_service() {
|
||||||
|
telegram_generate_notify_script
|
||||||
|
if command -v systemctl &>/dev/null; then
|
||||||
|
cat > /etc/systemd/system/conduit-telegram.service << EOF
|
||||||
|
[Unit]
|
||||||
|
Description=Conduit Telegram Notifications
|
||||||
|
After=network.target docker.service
|
||||||
|
Requires=docker.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/bin/bash $INSTALL_DIR/conduit-telegram.sh
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=30
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
systemctl daemon-reload 2>/dev/null || true
|
||||||
|
systemctl enable conduit-telegram.service 2>/dev/null || true
|
||||||
|
systemctl restart conduit-telegram.service 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
telegram_stop_notify() {
|
||||||
|
if command -v systemctl &>/dev/null && [ -f /etc/systemd/system/conduit-telegram.service ]; then
|
||||||
|
systemctl stop conduit-telegram.service 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
# Also clean up legacy PID-based loop if present
|
||||||
|
if [ -f "$INSTALL_DIR/telegram_notify.pid" ]; then
|
||||||
|
local pid=$(cat "$INSTALL_DIR/telegram_notify.pid" 2>/dev/null)
|
||||||
|
if echo "$pid" | grep -qE '^[0-9]+$' && kill -0 "$pid" 2>/dev/null; then
|
||||||
|
kill -- -"$pid" 2>/dev/null || kill "$pid" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
rm -f "$INSTALL_DIR/telegram_notify.pid"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
telegram_start_notify() {
|
||||||
|
telegram_stop_notify
|
||||||
|
if [ "$TELEGRAM_ENABLED" = "true" ] && [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
|
||||||
|
setup_telegram_service
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
telegram_disable_service() {
|
||||||
|
if command -v systemctl &>/dev/null && [ -f /etc/systemd/system/conduit-telegram.service ]; then
|
||||||
|
systemctl stop conduit-telegram.service 2>/dev/null || true
|
||||||
|
systemctl disable conduit-telegram.service 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
show_about() {
|
show_about() {
|
||||||
clear
|
clear
|
||||||
echo -e "${CYAN}══════════════════════════════════════════════════════════════════${NC}"
|
echo -e "${CYAN}══════════════════════════════════════════════════════════════════${NC}"
|
||||||
@@ -3498,6 +3987,8 @@ show_settings_menu() {
|
|||||||
echo -e " 8. 📖 About Conduit"
|
echo -e " 8. 📖 About Conduit"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " 9. 🔄 Reset tracker data"
|
echo -e " 9. 🔄 Reset tracker data"
|
||||||
|
echo -e " t. 📲 Telegram Notifications"
|
||||||
|
echo -e ""
|
||||||
echo -e " u. 🗑️ Uninstall"
|
echo -e " u. 🗑️ Uninstall"
|
||||||
echo -e " 0. ← Back to main menu"
|
echo -e " 0. ← Back to main menu"
|
||||||
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
|
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
|
||||||
@@ -3570,6 +4061,10 @@ show_settings_menu() {
|
|||||||
read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true
|
read -n 1 -s -r -p "Press any key to return..." < /dev/tty || true
|
||||||
redraw=true
|
redraw=true
|
||||||
;;
|
;;
|
||||||
|
t)
|
||||||
|
show_telegram_menu
|
||||||
|
redraw=true
|
||||||
|
;;
|
||||||
u)
|
u)
|
||||||
uninstall_all
|
uninstall_all
|
||||||
exit 0
|
exit 0
|
||||||
@@ -3586,6 +4081,227 @@ show_settings_menu() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
show_telegram_menu() {
|
||||||
|
while true; do
|
||||||
|
# Reload settings from disk to reflect any changes
|
||||||
|
[ -f "$INSTALL_DIR/settings.conf" ] && source "$INSTALL_DIR/settings.conf"
|
||||||
|
clear
|
||||||
|
print_header
|
||||||
|
if [ "$TELEGRAM_ENABLED" = "true" ] && [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
|
||||||
|
# Already configured — show management menu
|
||||||
|
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
|
||||||
|
echo -e "${CYAN} TELEGRAM NOTIFICATIONS${NC}"
|
||||||
|
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e " Status: ${GREEN}✓ Enabled${NC} (every ${TELEGRAM_INTERVAL}h)"
|
||||||
|
echo ""
|
||||||
|
echo -e " 1. 📩 Send test message"
|
||||||
|
echo -e " 2. ⏱ Change interval"
|
||||||
|
echo -e " 3. ❌ Disable notifications"
|
||||||
|
echo -e " 4. 🔄 Reconfigure (new bot/chat)"
|
||||||
|
echo -e " 0. ← Back"
|
||||||
|
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
|
||||||
|
echo ""
|
||||||
|
read -p " Enter choice: " tchoice < /dev/tty || return
|
||||||
|
case "$tchoice" in
|
||||||
|
1)
|
||||||
|
echo ""
|
||||||
|
echo -ne " Sending test message... "
|
||||||
|
if telegram_test_message; then
|
||||||
|
echo -e "${GREEN}✓ Sent!${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Failed. Check your token/chat ID.${NC}"
|
||||||
|
fi
|
||||||
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
echo ""
|
||||||
|
echo -e " Select notification interval:"
|
||||||
|
echo -e " 1. Every 1 hour"
|
||||||
|
echo -e " 2. Every 3 hours"
|
||||||
|
echo -e " 3. Every 6 hours (recommended)"
|
||||||
|
echo -e " 4. Every 12 hours"
|
||||||
|
echo -e " 5. Every 24 hours"
|
||||||
|
echo ""
|
||||||
|
read -p " Choice [1-5]: " ichoice < /dev/tty || true
|
||||||
|
case "$ichoice" in
|
||||||
|
1) TELEGRAM_INTERVAL=1 ;;
|
||||||
|
2) TELEGRAM_INTERVAL=3 ;;
|
||||||
|
3) TELEGRAM_INTERVAL=6 ;;
|
||||||
|
4) TELEGRAM_INTERVAL=12 ;;
|
||||||
|
5) TELEGRAM_INTERVAL=24 ;;
|
||||||
|
*) echo -e " ${RED}Invalid choice${NC}"; read -n 1 -s -r -p " Press any key..." < /dev/tty || true; continue ;;
|
||||||
|
esac
|
||||||
|
save_settings
|
||||||
|
telegram_start_notify
|
||||||
|
echo -e " ${GREEN}✓ Interval set to every ${TELEGRAM_INTERVAL} hours${NC}"
|
||||||
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
|
;;
|
||||||
|
3)
|
||||||
|
TELEGRAM_ENABLED=false
|
||||||
|
save_settings
|
||||||
|
telegram_disable_service
|
||||||
|
echo -e " ${GREEN}✓ Telegram notifications disabled${NC}"
|
||||||
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
|
;;
|
||||||
|
4)
|
||||||
|
telegram_setup_wizard
|
||||||
|
;;
|
||||||
|
0) return ;;
|
||||||
|
esac
|
||||||
|
elif [ -n "$TELEGRAM_BOT_TOKEN" ] && [ -n "$TELEGRAM_CHAT_ID" ]; then
|
||||||
|
# Disabled but credentials exist — offer re-enable
|
||||||
|
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
|
||||||
|
echo -e "${CYAN} TELEGRAM NOTIFICATIONS${NC}"
|
||||||
|
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e " Status: ${RED}✗ Disabled${NC} (credentials saved)"
|
||||||
|
echo ""
|
||||||
|
echo -e " 1. ✅ Re-enable notifications (every ${TELEGRAM_INTERVAL:-6}h)"
|
||||||
|
echo -e " 2. 🔄 Reconfigure (new bot/chat)"
|
||||||
|
echo -e " 0. ← Back"
|
||||||
|
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
|
||||||
|
echo ""
|
||||||
|
read -p " Enter choice: " tchoice < /dev/tty || return
|
||||||
|
case "$tchoice" in
|
||||||
|
1)
|
||||||
|
TELEGRAM_ENABLED=true
|
||||||
|
save_settings
|
||||||
|
telegram_start_notify
|
||||||
|
echo -e " ${GREEN}✓ Telegram notifications re-enabled${NC}"
|
||||||
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
|
;;
|
||||||
|
2)
|
||||||
|
telegram_setup_wizard
|
||||||
|
;;
|
||||||
|
0) return ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
# Not configured — run wizard
|
||||||
|
telegram_setup_wizard
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
telegram_setup_wizard() {
|
||||||
|
# Save and restore variables on Ctrl+C
|
||||||
|
local _saved_token="$TELEGRAM_BOT_TOKEN"
|
||||||
|
local _saved_chatid="$TELEGRAM_CHAT_ID"
|
||||||
|
local _saved_interval="$TELEGRAM_INTERVAL"
|
||||||
|
local _saved_enabled="$TELEGRAM_ENABLED"
|
||||||
|
trap 'TELEGRAM_BOT_TOKEN="$_saved_token"; TELEGRAM_CHAT_ID="$_saved_chatid"; TELEGRAM_INTERVAL="$_saved_interval"; TELEGRAM_ENABLED="$_saved_enabled"; trap - SIGINT; echo; return' SIGINT
|
||||||
|
clear
|
||||||
|
echo -e "${CYAN}══════════════════════════════════════════════════════════════════${NC}"
|
||||||
|
echo -e " ${BOLD}TELEGRAM NOTIFICATIONS SETUP${NC}"
|
||||||
|
echo -e "${CYAN}══════════════════════════════════════════════════════════════════${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${BOLD}Step 1: Create a Telegram Bot${NC}"
|
||||||
|
echo -e " ${CYAN}─────────────────────────────${NC}"
|
||||||
|
echo -e " 1. Open Telegram and search for ${BOLD}@BotFather${NC}"
|
||||||
|
echo -e " 2. Send ${YELLOW}/newbot${NC}"
|
||||||
|
echo -e " 3. Choose a name (e.g. \"My Conduit Monitor\")"
|
||||||
|
echo -e " 4. Choose a username (e.g. \"my_conduit_bot\")"
|
||||||
|
echo -e " 5. BotFather will give you a token like:"
|
||||||
|
echo -e " ${YELLOW}123456789:ABCdefGHIjklMNOpqrsTUVwxyz${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${BOLD}Recommended:${NC} Send these commands to @BotFather:"
|
||||||
|
echo -e " ${YELLOW}/setjoingroups${NC} → Disable (prevents adding to groups)"
|
||||||
|
echo -e " ${YELLOW}/setprivacy${NC} → Enable (limits message access)"
|
||||||
|
echo ""
|
||||||
|
echo -e " ${YELLOW}⚠ OPSEC Note:${NC} Enabling Telegram notifications creates"
|
||||||
|
echo -e " outbound connections to api.telegram.org from this server."
|
||||||
|
echo -e " This traffic may be visible to your network provider."
|
||||||
|
echo ""
|
||||||
|
read -s -p " Enter your bot token: " TELEGRAM_BOT_TOKEN < /dev/tty || { trap - SIGINT; TELEGRAM_BOT_TOKEN="$_saved_token"; return; }
|
||||||
|
echo ""
|
||||||
|
# Trim whitespace
|
||||||
|
TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN## }"
|
||||||
|
TELEGRAM_BOT_TOKEN="${TELEGRAM_BOT_TOKEN%% }"
|
||||||
|
if [ -z "$TELEGRAM_BOT_TOKEN" ]; then
|
||||||
|
echo -e " ${RED}No token entered. Setup cancelled.${NC}"
|
||||||
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
|
trap - SIGINT; return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate token format
|
||||||
|
if ! echo "$TELEGRAM_BOT_TOKEN" | grep -qE '^[0-9]+:[A-Za-z0-9_-]+$'; then
|
||||||
|
echo -e " ${RED}Invalid token format. Should be like: 123456789:ABCdefGHI...${NC}"
|
||||||
|
TELEGRAM_BOT_TOKEN="$_saved_token"; TELEGRAM_CHAT_ID="$_saved_chatid"; TELEGRAM_INTERVAL="$_saved_interval"; TELEGRAM_ENABLED="$_saved_enabled"
|
||||||
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
|
trap - SIGINT; return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e " ${BOLD}Step 2: Get Your Chat ID${NC}"
|
||||||
|
echo -e " ${CYAN}────────────────────────${NC}"
|
||||||
|
echo -e " 1. Open your new bot in Telegram"
|
||||||
|
echo -e " 2. Send it the message: ${YELLOW}/start${NC}"
|
||||||
|
echo -e " 3. Press Enter here when done..."
|
||||||
|
echo ""
|
||||||
|
read -p " Press Enter after sending /start to your bot... " < /dev/tty || { trap - SIGINT; TELEGRAM_BOT_TOKEN="$_saved_token"; TELEGRAM_CHAT_ID="$_saved_chatid"; TELEGRAM_INTERVAL="$_saved_interval"; TELEGRAM_ENABLED="$_saved_enabled"; return; }
|
||||||
|
|
||||||
|
echo -ne " Detecting chat ID... "
|
||||||
|
local attempts=0
|
||||||
|
TELEGRAM_CHAT_ID=""
|
||||||
|
while [ $attempts -lt 3 ] && [ -z "$TELEGRAM_CHAT_ID" ]; do
|
||||||
|
if telegram_get_chat_id; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
attempts=$((attempts + 1))
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$TELEGRAM_CHAT_ID" ]; then
|
||||||
|
echo -e "${RED}✗ Could not detect chat ID${NC}"
|
||||||
|
echo -e " Make sure you sent /start to the bot and try again."
|
||||||
|
TELEGRAM_BOT_TOKEN="$_saved_token"; TELEGRAM_CHAT_ID="$_saved_chatid"; TELEGRAM_INTERVAL="$_saved_interval"; TELEGRAM_ENABLED="$_saved_enabled"
|
||||||
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
|
trap - SIGINT; return
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Chat ID: ${TELEGRAM_CHAT_ID}${NC}"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e " ${BOLD}Step 3: Notification Interval${NC}"
|
||||||
|
echo -e " ${CYAN}─────────────────────────────${NC}"
|
||||||
|
echo -e " 1. Every 1 hour"
|
||||||
|
echo -e " 2. Every 3 hours"
|
||||||
|
echo -e " 3. Every 6 hours (recommended)"
|
||||||
|
echo -e " 4. Every 12 hours"
|
||||||
|
echo -e " 5. Every 24 hours"
|
||||||
|
echo ""
|
||||||
|
read -p " Choice [1-5] (default 3): " ichoice < /dev/tty || true
|
||||||
|
case "$ichoice" in
|
||||||
|
1) TELEGRAM_INTERVAL=1 ;;
|
||||||
|
2) TELEGRAM_INTERVAL=3 ;;
|
||||||
|
4) TELEGRAM_INTERVAL=12 ;;
|
||||||
|
5) TELEGRAM_INTERVAL=24 ;;
|
||||||
|
*) TELEGRAM_INTERVAL=6 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -ne " Sending test message... "
|
||||||
|
if telegram_test_message; then
|
||||||
|
echo -e "${GREEN}✓ Success!${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Failed to send. Check your token.${NC}"
|
||||||
|
TELEGRAM_BOT_TOKEN="$_saved_token"; TELEGRAM_CHAT_ID="$_saved_chatid"; TELEGRAM_INTERVAL="$_saved_interval"; TELEGRAM_ENABLED="$_saved_enabled"
|
||||||
|
read -n 1 -s -r -p " Press any key..." < /dev/tty || true
|
||||||
|
trap - SIGINT; return
|
||||||
|
fi
|
||||||
|
|
||||||
|
TELEGRAM_ENABLED=true
|
||||||
|
save_settings
|
||||||
|
telegram_start_notify
|
||||||
|
|
||||||
|
trap - SIGINT
|
||||||
|
echo ""
|
||||||
|
echo -e " ${GREEN}${BOLD}✓ Telegram notifications enabled!${NC}"
|
||||||
|
echo -e " You'll receive reports every ${TELEGRAM_INTERVAL} hours."
|
||||||
|
echo ""
|
||||||
|
read -n 1 -s -r -p " Press any key to return..." < /dev/tty || true
|
||||||
|
}
|
||||||
|
|
||||||
show_menu() {
|
show_menu() {
|
||||||
# Auto-fix conduit.service if it's in failed state
|
# Auto-fix conduit.service if it's in failed state
|
||||||
if command -v systemctl &>/dev/null; then
|
if command -v systemctl &>/dev/null; then
|
||||||
@@ -3604,6 +4320,16 @@ show_menu() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Load settings (Telegram service is only started explicitly by the user via the Telegram menu)
|
||||||
|
[ -f "$INSTALL_DIR/settings.conf" ] && source "$INSTALL_DIR/settings.conf"
|
||||||
|
|
||||||
|
# If the Telegram service is already running, regenerate the script and restart
|
||||||
|
# so it picks up any code changes from a script upgrade
|
||||||
|
if command -v systemctl &>/dev/null && systemctl is-active conduit-telegram.service &>/dev/null; then
|
||||||
|
telegram_generate_notify_script
|
||||||
|
systemctl restart conduit-telegram.service 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
local redraw=true
|
local redraw=true
|
||||||
while true; do
|
while true; do
|
||||||
if [ "$redraw" = true ]; then
|
if [ "$redraw" = true ]; then
|
||||||
@@ -4369,6 +5095,9 @@ print_summary() {
|
|||||||
#═══════════════════════════════════════════════════════════════════════
|
#═══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
uninstall() {
|
uninstall() {
|
||||||
|
telegram_disable_service
|
||||||
|
rm -f /etc/systemd/system/conduit-telegram.service 2>/dev/null
|
||||||
|
systemctl daemon-reload 2>/dev/null || true
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════════╗${NC}"
|
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════════╗${NC}"
|
||||||
echo "║ ⚠️ UNINSTALL CONDUIT "
|
echo "║ ⚠️ UNINSTALL CONDUIT "
|
||||||
|
|||||||
Reference in New Issue
Block a user