feat: v1.3.4 — Shir o Khorshid client mode, dpkg lock fix, pipe install fix

Add Conduit client mode menu (s) to switch between serving official
Psiphon clients and Shir o Khorshid users via --compartment flag.
Supports global toggle or per-container configuration. Status dashboard
and JSON output show active client mode. Installer now waits for dpkg
lock and menu opens correctly when run via curl | bash.
This commit is contained in:
SamNet-dev
2026-02-14 17:48:29 -06:00
parent 784956796d
commit 880f3d18a9
2 changed files with 298 additions and 11 deletions

View File

@@ -10,7 +10,7 @@
M A N A G E R
```
![Version](https://img.shields.io/badge/version-1.3.3-blue)
![Version](https://img.shields.io/badge/version-1.3.4-blue)
![License](https://img.shields.io/badge/license-MIT-green)
![Platform](https://img.shields.io/badge/platform-Linux-orange)
![Docker](https://img.shields.io/badge/Docker-Required-2496ED?logo=docker&logoColor=white)
@@ -49,7 +49,13 @@ wget https://raw.githubusercontent.com/SamNet-dev/conduit-manager/main/conduit.s
sudo bash conduit.sh
```
## What's New in v1.3.3
## What's New in v1.3.4
- **Shir o Khorshid Client Mode** — New menu option (`s`) to switch your Conduit node between serving official Psiphon clients and [Shir o Khorshid](https://github.com/shirokhorshid/shirokhorshid-android/releases) users (an alternative Psiphon client for Iran). Supports global toggle or per-container configuration. Status dashboard and JSON output show the active client mode per container
- **dpkg Lock Handling** — Installer now waits up to 60 seconds for `unattended-upgrades` to release the dpkg lock instead of failing immediately
- **Piped Install Fix** — Fixed menu not opening when running via `curl | bash` (stdin redirect for terminal detection)
### v1.3.3
- **Iran Connectivity Status** — Real-time Iran internet monitoring dashboard with data from IODA (BGP reachability), OONI (censorship detection), irinter.net (connectivity score), and optional Cloudflare Radar. Auto-refresh every hour with 7-day charts, outage alerts, and circumvention tool reachability (Psiphon, Tor)
- **Iran Connectivity Test** — Comprehensive network diagnostics testing 88 servers across 24 Iranian cities. Includes Quick Test (latency to all servers), Full Report (detailed per-server analysis with quality grading), Stability Test (multi-round jitter analysis), and MTU Path Discovery (binary search across 10 networks)
@@ -186,6 +192,7 @@ conduit remove-server # Remove a remote server
### Configuration
```bash
conduit settings # Change max-clients, bandwidth, CPU, memory per container
conduit client-mode # Switch between Standard and Shir o Khorshid client mode
conduit menu # Open interactive management menu
```
@@ -223,6 +230,7 @@ The interactive menu (`conduit menu`) provides access to all features:
| **m** | Multi-server dashboard — manage up to 30 remote servers with live status |
| **f** | Snowflake proxy — status, start/stop, resource configuration |
| **p** | Telegram MTProto Proxy — setup, share link & QR, send to Telegram, resource config |
| **s** | Conduit Client Mode — switch between Standard (Psiphon) and Shir o Khorshid, per-container support |
| **n** | Psiphon Network Stats — global network analytics with charts and country rankings |
| **e** | Iran Connectivity Status — real-time internet monitoring with IODA, OONI, irinter.net data |
| **t** | Iran Connectivity Test — network diagnostics across 88 servers in 24 Iranian cities |
@@ -349,7 +357,13 @@ wget https://raw.githubusercontent.com/SamNet-dev/conduit-manager/main/conduit.s
sudo bash conduit.sh
```
## تازه‌های نسخه 1.3.3
## تازه‌های نسخه 1.3.4
- **حالت کلاینت شیر و خورشید** — گزینه جدید در منو (`s`) برای تغییر نود کاندوییت بین سرویس‌دهی به کلاینت‌های رسمی سایفون و کاربران [شیر و خورشید](https://github.com/shirokhorshid/shirokhorshid-android/releases) (کلاینت جایگزین سایفون برای ایران). پشتیبانی از تنظیم سراسری یا هر کانتینر به صورت جداگانه. داشبورد وضعیت و خروجی JSON حالت فعال هر کانتینر را نمایش می‌دهند
- **مدیریت قفل dpkg** — نصب‌کننده حالا تا ۶۰ ثانیه منتظر آزاد شدن قفل dpkg توسط `unattended-upgrades` می‌ماند
- **رفع مشکل نصب پایپ** — رفع مشکل باز نشدن منو هنگام اجرا با `curl | bash`
### نسخه 1.3.3
- **وضعیت اتصال ایران** — داشبورد مانیتورینگ لحظه‌ای اینترنت ایران با داده‌های IODA (دسترسی BGP)، OONI (تشخیص سانسور)، irinter.net (امتیاز اتصال) و Cloudflare Radar اختیاری. نمودارهای ۷ روزه، هشدارهای قطعی و نرخ موفقیت ابزارهای دور زدن (سایفون، تور) با بروزرسانی خودکار
- **تست اتصال ایران** — مجموعه تشخیص شبکه با ۸۸ سرور در ۲۴ شهر ایران. شامل تست سریع (اسکن موازی تاخیر)، گزارش کامل (رتبه‌بندی کیفیت A+ تا F هر سرور)، تست پایداری (تحلیل جیتر چند مرحله‌ای) و کشف MTU مسیر (جستجوی دودویی در ۱۰ شبکه)
@@ -473,6 +487,7 @@ conduit remove-server # حذف سرور ریموت
### پیکربندی
```bash
conduit settings # تغییر تنظیمات هر کانتینر
conduit client-mode # تغییر حالت کلاینت (استاندارد / شیر و خورشید)
conduit menu # منوی تعاملی
```
@@ -508,6 +523,7 @@ conduit help # راهنما
| **m** | داشبورد چند سرور — مدیریت تا ۳۰ سرور ریموت با وضعیت زنده |
| **f** | پروکسی اسنوفلیک — وضعیت، شروع/توقف، پیکربندی منابع |
| **p** | پروکسی MTProto تلگرام — راه‌اندازی، اشتراک لینک و QR، ارسال به تلگرام |
| **s** | حالت کلاینت — تغییر بین سایفون استاندارد و شیر و خورشید، پشتیبانی هر کانتینر |
| **n** | آمار شبکه سایفون — تحلیل شبکه جهانی با نمودار و رتبه‌بندی کشوری |
| **e** | وضعیت اتصال ایران — مانیتورینگ لحظه‌ای با داده‌های IODA، OONI و irinter.net |
| **t** | تست اتصال ایران — تشخیص شبکه در ۸۸ سرور ۲۴ شهر ایران |

View File

@@ -1,7 +1,7 @@
#!/bin/bash
#
# ╔═══════════════════════════════════════════════════════════════════╗
# ║ 🚀 PSIPHON CONDUIT MANAGER v1.3.3
# ║ 🚀 PSIPHON CONDUIT MANAGER v1.3.4
# ║ ║
# ║ One-click setup for Psiphon Conduit ║
# ║ ║
@@ -31,7 +31,7 @@ if [ -z "$BASH_VERSION" ]; then
exit 1
fi
VERSION="1.3.3"
VERSION="1.3.4"
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest"
INSTALL_DIR="${INSTALL_DIR:-/opt/conduit}"
BACKUP_DIR="$INSTALL_DIR/backups"
@@ -960,7 +960,7 @@ create_management_script() {
# Reference: https://github.com/ssmirr/conduit/releases/latest
#
VERSION="1.3.3"
VERSION="1.3.4"
INSTALL_DIR="REPLACE_ME_INSTALL_DIR"
BACKUP_DIR="$INSTALL_DIR/backups"
CONDUIT_IMAGE="ghcr.io/ssmirr/conduit/conduit:latest"
@@ -1112,6 +1112,19 @@ get_container_memory() {
echo "${val:-${DOCKER_MEMORY:-}}"
}
get_container_compartment() {
local idx=${1:-1}
local var="COMPARTMENT_${idx}"
local val="${!var}"
if [ "$val" = "none" ]; then
echo ""
elif [ -n "$val" ]; then
echo "$val"
else
echo "${COMPARTMENT:-}"
fi
}
run_conduit_container() {
local idx=${1:-1}
local name=$(get_container_name $idx)
@@ -1120,6 +1133,7 @@ run_conduit_container() {
local bw=$(get_container_bandwidth $idx)
local cpus=$(get_container_cpus $idx)
local mem=$(get_container_memory $idx)
local compartment=$(get_container_compartment $idx)
# Remove existing container if any
if docker ps -a 2>/dev/null | grep -q "[[:space:]]${name}$"; then
docker rm -f "$name" 2>/dev/null || true
@@ -1127,6 +1141,8 @@ run_conduit_container() {
local resource_args=""
[ -n "$cpus" ] && resource_args+="--cpus $cpus "
[ -n "$mem" ] && resource_args+="--memory $mem "
local compartment_args=""
[ -n "$compartment" ] && compartment_args="--compartment $compartment"
# shellcheck disable=SC2086
docker run -d \
--name "$name" \
@@ -1137,7 +1153,7 @@ run_conduit_container() {
--network host \
$resource_args \
"$CONDUIT_IMAGE" \
start --max-clients "$mc" --bandwidth "$bw" --stats-file
start --max-clients "$mc" --bandwidth "$bw" --stats-file $compartment_args
}
# ─── Snowflake Proxy Functions ─────────────────────────────────────────────────
@@ -4287,8 +4303,10 @@ status_json() {
printf '"tracker_in_bytes":%d,"tracker_out_bytes":%d,"unique_ips":%d,' \
"${data_in:-0}" "${data_out:-0}" "${unique_ips:-0}"
printf '"restarts":%d,' "$total_restarts"
printf '"settings":{"max_clients":%d,"bandwidth":"%s","container_count":%d,"data_cap_gb":%d,"data_cap_up_gb":%d,"data_cap_down_gb":%d},' \
"${MAX_CLIENTS:-200}" "${BANDWIDTH:-5}" "${CONTAINER_COUNT:-1}" "${DATA_CAP_GB:-0}" "${DATA_CAP_UP_GB:-0}" "${DATA_CAP_DOWN_GB:-0}"
local _json_cm="${COMPARTMENT:-standard}"
[ -z "${COMPARTMENT:-}" ] && _json_cm="standard"
printf '"settings":{"max_clients":%d,"bandwidth":"%s","container_count":%d,"data_cap_gb":%d,"data_cap_up_gb":%d,"data_cap_down_gb":%d,"client_mode":"%s"},' \
"${MAX_CLIENTS:-200}" "${BANDWIDTH:-5}" "${CONTAINER_COUNT:-1}" "${DATA_CAP_GB:-0}" "${DATA_CAP_UP_GB:-0}" "${DATA_CAP_DOWN_GB:-0}" "$_json_cm"
local sf_enabled="${SNOWFLAKE_ENABLED:-false}"
local sf_running=false
local sf_conn=0 sf_in=0 sf_out=0 sf_to=0
@@ -4589,7 +4607,11 @@ show_status() {
local bw=$(get_container_bandwidth $i)
local bw_d="Unlimited"
[ "$bw" != "-1" ] && bw_d="${bw} Mbps"
printf " %-12s clients: %-5s bw: %s${EL}\n" "$(get_container_name $i)" "$mc" "$bw_d"
local _comp=$(get_container_compartment $i)
local _comp_d=""
[ "$_comp" = "shirokhorshid" ] && _comp_d=" ${MAGENTA}[Shir o Khorshid]${NC}"
printf " %-12s clients: %-5s bw: %s" "$(get_container_name $i)" "$mc" "$bw_d"
echo -e "${_comp_d}${EL}"
done
else
echo -e " Max Clients: ${MAX_CLIENTS}${EL}"
@@ -4600,6 +4622,17 @@ show_status() {
fi
echo -e " Containers: ${CONTAINER_COUNT}${EL}"
fi
# Show client mode
local _cm_label="Standard"
[ "${COMPARTMENT:-}" = "shirokhorshid" ] && _cm_label="${MAGENTA}Shir o Khorshid${NC}"
# Check for per-container overrides
local _cm_mixed=false
for i in $(seq 1 $CONTAINER_COUNT); do
local _cmv="COMPARTMENT_${i}"
[ -n "${!_cmv}" ] && { _cm_mixed=true; break; }
done
[ "$_cm_mixed" = true ] && _cm_label="${YELLOW}Mixed${NC}"
echo -e " Client Mode: ${_cm_label}${EL}"
if _has_any_data_cap; then
local usage=$(get_data_usage)
local used_rx=$(echo "$usage" | awk '{print $1}')
@@ -6239,6 +6272,7 @@ MTPROTO_SECRET="${MTPROTO_SECRET:-}"
MTPROTO_DOMAIN="${MTPROTO_DOMAIN:-google.com}"
MTPROTO_CPUS="${MTPROTO_CPUS:-}"
MTPROTO_MEMORY="${MTPROTO_MEMORY:-}"
COMPARTMENT="${COMPARTMENT:-}"
EOF
# Save per-container overrides
for i in $(seq 1 "$CONTAINER_COUNT"); do
@@ -6246,10 +6280,12 @@ EOF
local bw_var="BANDWIDTH_${i}"
local cpu_var="CPUS_${i}"
local mem_var="MEMORY_${i}"
local comp_var="COMPARTMENT_${i}"
[ -n "${!mc_var}" ] && echo "${mc_var}=\"${!mc_var}\"" >> "$_tmp"
[ -n "${!bw_var}" ] && echo "${bw_var}=\"${!bw_var}\"" >> "$_tmp"
[ -n "${!cpu_var}" ] && echo "${cpu_var}=\"${!cpu_var}\"" >> "$_tmp"
[ -n "${!mem_var}" ] && echo "${mem_var}=\"${!mem_var}\"" >> "$_tmp"
[ -n "${!comp_var}" ] && echo "${comp_var}=\"${!comp_var}\"" >> "$_tmp"
done
chmod 600 "$_tmp" 2>/dev/null || true
if [ ! -s "$_tmp" ]; then
@@ -8964,6 +9000,218 @@ telegram_setup_wizard() {
read -n 1 -s -r -p " Press any key to return..." < /dev/tty || true
}
# ─── Client Mode (Compartment) ────────────────────────────────────────────────
_check_image_latest() {
local latest_id running_id
# Image must exist locally
latest_id=$(docker image inspect "$CONDUIT_IMAGE" --format='{{.Id}}' 2>/dev/null) || return 1
# If a container is running, verify it uses the latest pulled image
running_id=$(docker inspect conduit --format='{{.Image}}' 2>/dev/null) || return 0
[ "$latest_id" = "$running_id" ]
}
_compartment_label() {
local val="${1:-}"
if [ "$val" = "shirokhorshid" ]; then
echo -e "${MAGENTA}Shir o Khorshid${NC}"
else
echo "Standard"
fi
}
show_compartment_menu() {
while true; do
clear
echo ""
echo -e "${CYAN}${BOLD} CONDUIT CLIENT MODE${NC}"
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
echo ""
# Show current global mode
local _cur_mode="Standard (default Psiphon clients)"
[ "${COMPARTMENT:-}" = "shirokhorshid" ] && _cur_mode="${MAGENTA}Shir o Khorshid${NC}"
echo -e " Current mode: ${BOLD}${_cur_mode}${NC}"
echo ""
# Check for per-container overrides
local _has_overrides=false
if [ "${CONTAINER_COUNT:-1}" -gt 1 ]; then
for i in $(seq 1 "${CONTAINER_COUNT:-1}"); do
local _cvar="COMPARTMENT_${i}"
if [ -n "${!_cvar}" ]; then
_has_overrides=true
break
fi
done
fi
if [ "$_has_overrides" = true ]; then
echo -e " ${YELLOW}Per-container overrides active:${NC}"
for i in $(seq 1 "${CONTAINER_COUNT:-1}"); do
local _cval=$(get_container_compartment $i)
echo -e " Container $i: $(_compartment_label "$_cval")"
done
echo ""
fi
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
echo ""
echo -e " Shir o Khorshid is an alternative Psiphon client for Iran."
echo -e " Enabling this mode dedicates your node to its users."
echo -e " ${DIM}This requires the latest Conduit image.${NC}"
echo ""
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
echo ""
echo -e " 1. Standard (default Psiphon clients)"
echo -e " 2. Shir o Khorshid (Iranian client)"
if [ "${CONTAINER_COUNT:-1}" -gt 1 ]; then
echo -e " 3. Per-container setup"
fi
echo -e " i. Info — What is Shir o Khorshid?"
echo -e " 0. Back"
echo ""
read -p " Enter choice: " _comp_choice < /dev/tty || { return; }
case "$_comp_choice" in
1)
if [ "${COMPARTMENT:-}" = "" ] && [ "$_has_overrides" = false ]; then
echo -e "\n ${DIM}Already using Standard mode.${NC}"
sleep 1
continue
fi
COMPARTMENT=""
# Clear per-container overrides
for i in $(seq 1 "${CONTAINER_COUNT:-1}"); do
eval "COMPARTMENT_${i}="
done
save_settings
echo -e "\n ${GREEN}✓ Switched to Standard mode.${NC}"
echo ""
read -p " Recreate containers now to apply? [y/N]: " _rc < /dev/tty || true
if [[ "$_rc" =~ ^[Yy]$ ]]; then
recreate_containers
else
echo -e " ${CYAN}Setting saved. Restart containers to apply.${NC}"
fi
read -n 1 -s -r -p " Press any key to continue..." < /dev/tty || true
;;
2)
if [ "${COMPARTMENT:-}" = "shirokhorshid" ] && [ "$_has_overrides" = false ]; then
echo -e "\n ${DIM}Already using Shir o Khorshid mode.${NC}"
sleep 1
continue
fi
# Warn if image may be outdated
if ! _check_image_latest; then
echo ""
echo -e " ${YELLOW}Note: Your containers may not be running the latest image.${NC}"
echo -e " ${YELLOW}Consider running Update (option 8) for best results.${NC}"
echo ""
fi
COMPARTMENT="shirokhorshid"
# Clear per-container overrides
for i in $(seq 1 "${CONTAINER_COUNT:-1}"); do
eval "COMPARTMENT_${i}="
done
save_settings
echo -e "\n ${GREEN}✓ Switched to Shir o Khorshid mode.${NC}"
echo ""
read -p " Recreate containers now to apply? [y/N]: " _rc < /dev/tty || true
if [[ "$_rc" =~ ^[Yy]$ ]]; then
recreate_containers
else
echo -e " ${CYAN}Setting saved. Restart containers to apply.${NC}"
fi
read -n 1 -s -r -p " Press any key to continue..." < /dev/tty || true
;;
3)
if [ "${CONTAINER_COUNT:-1}" -le 1 ]; then
echo -e "\n ${RED}Invalid choice.${NC}"
sleep 1
continue
fi
# Warn if image may be outdated
if ! _check_image_latest; then
echo ""
echo -e " ${YELLOW}Note: Your containers may not be running the latest image.${NC}"
echo -e " ${YELLOW}Consider running Update (option 8) for best results.${NC}"
fi
echo ""
echo -e " ${BOLD}Per-container client mode:${NC}"
for i in $(seq 1 "${CONTAINER_COUNT:-1}"); do
local _cval=$(get_container_compartment $i)
echo -e " $i. Container $i: $(_compartment_label "$_cval")"
done
echo -e " 0. Back"
echo ""
read -p " Select container: " _cidx < /dev/tty || { continue; }
if [ "$_cidx" = "0" ]; then continue; fi
if ! [[ "$_cidx" =~ ^[0-9]+$ ]] || [ "$_cidx" -lt 1 ] || [ "$_cidx" -gt "${CONTAINER_COUNT:-1}" ]; then
echo -e " ${RED}Invalid container number.${NC}"
sleep 1
continue
fi
echo ""
echo -e " Set mode for container $_cidx:"
echo -e " 1. Standard"
echo -e " 2. Shir o Khorshid"
read -p " Choice: " _cmode < /dev/tty || { continue; }
case "$_cmode" in
1) eval "COMPARTMENT_${_cidx}=none" ;;
2) eval "COMPARTMENT_${_cidx}=shirokhorshid" ;;
*) echo -e " ${RED}Invalid choice.${NC}"; sleep 1; continue ;;
esac
save_settings
echo -e "\n ${GREEN}✓ Container $_cidx updated.${NC}"
echo ""
read -p " Recreate container $_cidx now to apply? [y/N]: " _rc < /dev/tty || true
if [[ "$_rc" =~ ^[Yy]$ ]]; then
local _cname=$(get_container_name $_cidx)
docker rm -f "$_cname" 2>/dev/null || true
run_conduit_container $_cidx
if docker ps 2>/dev/null | grep -q "[[:space:]]${_cname}$"; then
echo -e " ${GREEN}✓ Container $_cidx recreated.${NC}"
else
echo -e " ${RED}✗ Container $_cidx failed to start.${NC}"
fi
else
echo -e " ${CYAN}Setting saved. Restart container to apply.${NC}"
fi
read -n 1 -s -r -p " Press any key to continue..." < /dev/tty || true
;;
i|I)
clear
echo ""
echo -e "${CYAN}${BOLD} ABOUT SHIR O KHORSHID${NC}"
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
echo ""
echo -e " ${BOLD}Shir o Khorshid${NC} is an alternative Psiphon client built"
echo -e " specifically for users in Iran. It connects through the same"
echo -e " Conduit network but uses a dedicated compartment so that"
echo -e " volunteer nodes can choose to serve its users directly."
echo ""
echo -e " ${BOLD}How it works:${NC}"
echo -e " When you enable Shir o Khorshid mode, your Conduit container"
echo -e " starts with ${CYAN}--compartment shirokhorshid${NC}, which tells the"
echo -e " broker to route Shir o Khorshid client traffic to your node"
echo -e " instead of general Psiphon client traffic."
echo ""
echo -e " ${BOLD}The client app:${NC}"
echo -e " Currently available for Android as a direct APK download."
echo -e " A Play Store release is coming soon."
echo ""
echo -e " ${CYAN}Download:${NC}"
echo -e " ${DIM}https://github.com/shirokhorshid/shirokhorshid-android/releases${NC}"
echo ""
echo -e " ${BOLD}Developed by:${NC}"
echo -e " ${DIM}https://x.com/PawnToPromotion${NC}"
echo ""
echo -e "${CYAN}─────────────────────────────────────────────────────────────────${NC}"
echo ""
read -n 1 -s -r -p " Press any key to go back..." < /dev/tty || true
;;
0) return ;;
*) echo -e " ${RED}Invalid choice.${NC}"; sleep 1 ;;
esac
done
}
show_menu() {
# Fix outdated systemd service files
if command -v systemctl &>/dev/null; then
@@ -9122,6 +9370,22 @@ SVCEOF
echo -e " p. ✉️ Telegram MTProto Proxy"
fi
echo ""
# Client mode menu item
local _comp_label="Standard"
if [ "${COMPARTMENT:-}" = "shirokhorshid" ]; then
_comp_label="${MAGENTA}Shir o Khorshid${NC}"
fi
# Check for mixed per-container overrides
if [ "${CONTAINER_COUNT:-1}" -gt 1 ]; then
local _has_comp_override=false
for _ci in $(seq 1 "${CONTAINER_COUNT:-1}"); do
local _cv="COMPARTMENT_${_ci}"
[ -n "${!_cv}" ] && { _has_comp_override=true; break; }
done
[ "$_has_comp_override" = true ] && _comp_label="${YELLOW}Mixed${NC}"
fi
echo -e " ${CYAN}s${NC}. 🦁 Conduit Client Mode [${_comp_label}]"
echo ""
echo -e " ${CYAN}n${NC}. 📡 Psiphon Network Stats"
echo -e " ${CYAN}e${NC}. 📈 Iran Connectivity Status"
echo -e " ${CYAN}t${NC}. 🔗 Iran Connectivity Test"
@@ -9196,6 +9460,10 @@ SVCEOF
show_mtproto_menu
redraw=true
;;
s|S)
show_compartment_menu
redraw=true
;;
i)
show_info_menu
redraw=true
@@ -10250,6 +10518,7 @@ _info_cli_commands() {
echo -e " ${GREEN}network-stats${NC} Psiphon global network statistics"
echo -e " ${GREEN}iran-status${NC} Iran connectivity (IODA, OONI, RIPE)"
echo -e " ${GREEN}iran-test${NC} Iran connectivity test (ping, MTU, trace)"
echo -e " ${GREEN}client-mode${NC} Switch client mode (Standard/Shir o Khorshid)"
echo ""
echo -e " Press ${BOLD}any key${NC} for page 2..."
read -n 1 -s -r < /dev/tty || true
@@ -14208,6 +14477,7 @@ show_help() {
echo " network-stats Show Psiphon network statistics"
echo " iran-status Iran connectivity status (IODA, OONI)"
echo " iran-test Iran connectivity test (ping, traceroute, MTR)"
echo " client-mode Switch Conduit client mode (Standard/Shir o Khorshid)"
echo " uninstall Remove everything (container, data, service)"
echo " menu Open interactive menu (default)"
echo " version Show version information"
@@ -14829,6 +15099,7 @@ case "${1:-menu}" in
network-stats) show_psiphon_stats ;;
iran-status) show_iran_connectivity ;;
iran-test) show_iran_test ;;
client-mode) show_compartment_menu ;;
add-server|deploy) add_server_interactive ;;
edit-server) edit_server_interactive ;;
remove-server) remove_server_interactive ;;
@@ -15238,7 +15509,7 @@ SVCEOF
fi
}
#
# REACHED END OF SCRIPT - VERSION 1.3.3
# REACHED END OF SCRIPT - VERSION 1.3.4
# ###############################################################################
main "$@"