diff --git a/install.sh b/install.sh
index c27f58e..3e62962 100644
--- a/install.sh
+++ b/install.sh
@@ -1,10 +1,6 @@
#!/bin/bash
-# ๐ SwiftGram MTProxy โ Smart Modular Manager
-# v1.0.5 โ Final Working Version (TCP + UDP Calls)
-# ะะพะปะฝัะน ััะฝะบัะธะพะฝะฐะป, ะฑะตะท ัะตะบะปะฐะผั, ะธัะฟัะฐะฒะปะตะฝะฐ ะปะพะณะธะบะฐ ะฟะพััะพะฒ.
-
-# โโ ะะฐัััะพะนะบะธ ัะตะฟะพะทะธัะพัะธั โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-REPO_RAW_URL="https://git.bargcraft.top/kobalt/swiftgram/raw/branch/main"
+# ๐ SwiftGram MTProxy โ Smart Modular Manager (Self-contained)
+# v1.1.0 โ ะคะธะบั ะทะฒะพะฝะบะพะฒ (UDP) + ะะฒัะพะฝะพะผะฝัะน ัะตะถะธะผ
# โโ ะฆะฒะตัะฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
RED='\033[0;31m'
@@ -138,17 +134,6 @@ install_base_deps() {
get_ip4() { curl -s -4 --max-time 5 https://api.ipify.org || echo "0.0.0.0"; }
get_ip6() { curl -s -6 --max-time 5 https://api6.ipify.org || echo ""; }
-check_port() {
- local port="$1"
- if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"; then
- local hp=$(docker inspect "$CONTAINER_NAME" --format='{{range $p,$c := .HostConfig.PortBindings}}{{(index $c 0).HostPort}} {{end}}' 2>/dev/null)
- for p in $hp; do [ "$p" = "$port" ] && return 1; done
- fi
- local line=$(ss -tlnp 2>/dev/null | grep -E ":${port}\b" | head -1)
- [ -n "$line" ] && { echo "$line"; return 0; }
- return 1
-}
-
find_smart_port() {
local port=443
if ss -tlnp | grep -qE ":${port}\b"; then
@@ -162,20 +147,221 @@ find_smart_port() {
echo "$port"
}
-# โโ ะะฝัะตะปะปะตะบััะฐะปัะฝัะน ะฐะฝะฐะปะธะท ะดะพะผะตะฝะฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-analyze_best_domain() {
- spinner_start "ะะฝะฐะปะธะท ะดะพะผะตะฝะพะฒ ะดะปั Fake TLS..."
- local test_domains=("google.com" "wikipedia.org" "github.com" "habr.com" "microsoft.com")
- local best="google.com"
- local min=999
- for d in "${test_domains[@]}"; do
- local t=$(ping -c 1 -W 1 "$d" 2>/dev/null | grep 'time=' | awk -F'time=' '{print $2}' | awk '{print $1}')
- if [ -n "$t" ] && (( $(echo "$t < $min" | bc -l 2>/dev/null || [ ${t%.*} -lt ${min%.*} ]) )); then
- min=$t; best=$d
- fi
- done
- spinner_stop
- echo "$best"
+# โโ ะัะธััะต ะธัั
ะพะดะฝะธะบะธ ะฑะพัะฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
+prepare_bot_source() {
+ mkdir -p "$BOT_DIR"
+
+ cat << 'EOF' > "$BOT_DIR/requirements.txt"
+python-telegram-bot==20.8
+EOF
+
+ cat << 'EOF' > "$BOT_DIR/bot.py"
+#!/usr/bin/env python3
+"""
+SwiftGram MTProxy โ Telegram-ะฑะพั ะดะปั ัะฟัะฐะฒะปะตะฝะธั MTProxy ะฝะฐ ัะตัะฒะตัะต.
+"""
+import asyncio
+import html
+import json
+import os
+import re
+from pathlib import Path
+
+_env_path = Path(__file__).resolve().parent / ".env"
+if not _env_path.exists():
+ _env_path = Path("/opt/swiftgram/.env")
+
+if _env_path.exists():
+ with open(_env_path, encoding="utf-8") as f:
+ for line in f:
+ line = line.strip()
+ if line and not line.startswith("#") and "=" in line:
+ k, v = line.split("=", 1)
+ os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'"))
+
+from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
+from telegram.ext import (
+ Application,
+ CommandHandler,
+ CallbackQueryHandler,
+ ContextTypes,
+)
+
+BOT_TOKEN = os.environ.get("BOT_TOKEN")
+_allowed = os.environ.get("ALLOWED_IDS", "").strip()
+try:
+ ALLOWED_IDS = set(int(x) for x in _allowed.split(",") if x.strip()) if _allowed else None
+except ValueError:
+ ALLOWED_IDS = None
+
+CONTAINER_NAME = os.environ.get("CONTAINER_NAME", "swiftgram-proxy")
+CONFIG_FILE = Path(os.environ.get("CONFIG_PATH", "/opt/swiftgram/proxy.json"))
+
+DOMAINS = [
+ "google.com", "wikipedia.org", "habr.com", "github.com",
+ "coursera.org", "udemy.com", "medium.com", "stackoverflow.com",
+ "bbc.com", "cnn.com", "reuters.com", "nytimes.com",
+]
+
+def _ok(uid: int) -> bool:
+ return ALLOWED_IDS is None or uid in ALLOWED_IDS
+
+def _decode(data: bytes) -> str:
+ return (data or b"").decode("utf-8", errors="replace").strip()
+
+async def sh(*args: str, timeout: int = 60) -> tuple[int, str, str]:
+ proc = await asyncio.create_subprocess_exec(
+ *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE,
+ )
+ try:
+ out, err = await asyncio.wait_for(proc.communicate(), timeout=timeout)
+ except asyncio.TimeoutError:
+ proc.kill()
+ await proc.wait()
+ return -1, "", "Timeout"
+ return proc.returncode or 0, _decode(out), _decode(err)
+
+async def get_ip4() -> str:
+ for url in ("https://api.ipify.org", "https://icanhazip.com", "https://ifconfig.me"):
+ code, out, _ = await sh("curl", "-s", "-4", "--max-time", "5", url, timeout=8)
+ if code == 0 and out:
+ m = re.search(r"(\d{1,3}\.){3}\d{1,3}", out)
+ if m: return m.group(0)
+ return "0.0.0.0"
+
+async def get_ip6() -> str:
+ code, out, _ = await sh("curl", "-s", "-6", "--max-time", "5", "https://api6.ipify.org", timeout=8)
+ if code == 0 and out:
+ return out.strip()
+ return ""
+
+async def check_bbr() -> bool:
+ code, out, _ = await sh("sysctl", "net.ipv4.tcp_congestion_control", timeout=5)
+ return "bbr" in out.lower()
+
+async def proxy_running() -> bool:
+ code, out, _ = await sh("docker", "ps", "--format", "{{.Names}}", timeout=10)
+ return code == 0 and CONTAINER_NAME in out
+
+async def docker_val(fmt: str) -> str:
+ code, out, _ = await sh("docker", "inspect", CONTAINER_NAME, "--format", fmt, timeout=10)
+ return out.strip() if code == 0 else ""
+
+async def check_port(port: int) -> str | None:
+ if await proxy_running():
+ hp = await docker_val("{{range $p,$c := .HostConfig.PortBindings}}{{(index $c 0).HostPort}} {{end}}")
+ if str(port) in hp.split(): return None
+ code, out, _ = await sh("ss", "-tlnp", timeout=5)
+ for line in out.splitlines():
+ if f":{port} " in line or f":{port}\t" in line: return line
+ return None
+
+def save_config(data: dict) -> None:
+ CONFIG_FILE.parent.mkdir(parents=True, exist_ok=True)
+ CONFIG_FILE.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
+
+def load_config() -> dict:
+ if CONFIG_FILE.exists():
+ try: return json.loads(CONFIG_FILE.read_text(encoding="utf-8"))
+ except: pass
+ return {}
+
+async def proxy_info() -> dict | None:
+ if not await proxy_running(): return None
+ cmd_str = await docker_val("{{range .Config.Cmd}}{{.}} {{end}}")
+ secret = cmd_str.split()[-1] if cmd_str else ""
+ hp = await docker_val("{{range $p,$c := .HostConfig.PortBindings}}{{(index $c 0).HostPort}}{{end}}")
+ port = hp or "443"
+ ip4 = await get_ip4()
+ ip6 = await get_ip6()
+ cfg = load_config()
+ return {
+ "ip4": ip4, "ip6": ip6, "port": port, "secret": secret,
+ "domain": cfg.get("domain", "โ"),
+ "link4": f"tg://proxy?server={ip4}&port={port}&secret={secret}",
+ "link6": f"tg://proxy?server={ip6}&port={port}&secret={secret}" if ip6 else None
+ }
+
+def main_menu_kb() -> InlineKeyboardMarkup:
+ return InlineKeyboardMarkup([
+ [InlineKeyboardButton("๐ง ะฃััะฐะฝะพะฒะธัั / ะะฑะฝะพะฒะธัั", callback_data="menu_install")],
+ [InlineKeyboardButton("๐ ะกัะฐััั", callback_data="menu_status"),
+ InlineKeyboardButton("๐ ะกััะปะบะฐ", callback_data="menu_link")],
+ [InlineKeyboardButton("๐ค ะะพะดะตะปะธัััั", callback_data="menu_share")],
+ [InlineKeyboardButton("๐ ะ ะตััะฐัั", callback_data="menu_restart"),
+ InlineKeyboardButton("๐ ะะพะณะธ", callback_data="menu_logs")],
+ [InlineKeyboardButton("๐ ะฃะดะฐะปะธัั ะฟัะพะบัะธ", callback_data="menu_remove")],
+ ])
+
+HELP_TEXT = (
+ "๐ SwiftGram MTProxy Manager\n\n"
+ "โข TCP + UDP (ะทะฒะพะฝะบะธ) ะฐะบัะธะฒะฝั\n"
+ "โข IPv6 ะฟะพะดะดะตัะถะบะฐ ะฒะบะปััะตะฝะฐ\n"
+ "โข BBR ะพะฟัะธะผะธะทะฐัะธั\n\n"
+)
+
+async def start(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
+ if not update.effective_user or not _ok(update.effective_user.id): return
+ msg = update.message or (update.callback_query and update.callback_query.message)
+ if update.message:
+ await update.message.reply_text(HELP_TEXT, parse_mode="HTML", reply_markup=main_menu_kb())
+ elif update.callback_query:
+ await update.callback_query.edit_message_text(HELP_TEXT, parse_mode="HTML", reply_markup=main_menu_kb())
+
+async def cmd_status(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
+ if not update.effective_user or not _ok(update.effective_user.id): return
+ info = await proxy_info()
+ if not info:
+ text = "โ ะัะพะบัะธ ะฝะต ะทะฐะฟััะตะฝ."
+ else:
+ bbr = "โ
ะะบัะธะฒะตะฝ" if await check_bbr() else "โ ะัะบะปััะตะฝ"
+ text = (
+ "โ
SwiftGram ัะฐะฑะพัะฐะตั\n\n"
+ f"๐ IPv4: {info['ip4']}\n"
+ f"๐ ะะพัั: {info['port']}\n"
+ f"๐ BBR: {bbr}\n"
+ f"๐ ะะฒะพะฝะบะธ: โ
UDP ะพัะบััั\n"
+ )
+ kb = InlineKeyboardMarkup([[InlineKeyboardButton("โ๏ธ ะะตะฝั", callback_data="menu_main")]])
+ if update.callback_query: await update.callback_query.edit_message_text(text, parse_mode="HTML", reply_markup=kb)
+ else: await update.message.reply_text(text, parse_mode="HTML", reply_markup=kb)
+
+async def cmd_link(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
+ if not update.effective_user or not _ok(update.effective_user.id): return
+ info = await proxy_info()
+ if not info: text = "โ ะัะพะบัะธ ะฝะต ะทะฐะฟััะตะฝ."
+ else:
+ text = f"ะกััะปะบะฐ:\n{info['link4']}"
+ kb = InlineKeyboardMarkup([[InlineKeyboardButton("โ๏ธ ะะตะฝั", callback_data="menu_main")]])
+ if update.callback_query: await update.callback_query.edit_message_text(text, parse_mode="HTML", reply_markup=kb)
+ else: await update.message.reply_text(text, parse_mode="HTML", reply_markup=kb)
+
+async def cmd_restart(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
+ if not update.effective_user or not _ok(update.effective_user.id): return
+ await sh("docker", "restart", CONTAINER_NAME)
+ kb = InlineKeyboardMarkup([[InlineKeyboardButton("โ๏ธ ะะตะฝั", callback_data="menu_main")]])
+ if update.callback_query: await update.callback_query.edit_message_text("โ
ะะตัะตะทะฐะฟััะตะฝะพ", reply_markup=kb)
+
+async def callback_handler(update: Update, ctx: ContextTypes.DEFAULT_TYPE) -> None:
+ query = update.callback_query
+ await query.answer()
+ data = query.data
+ if data == "menu_main": await start(update, ctx)
+ elif data == "menu_status": await cmd_status(update, ctx)
+ elif data == "menu_link": await cmd_link(update, ctx)
+ elif data == "menu_restart": await cmd_restart(update, ctx)
+
+def main() -> None:
+ if not BOT_TOKEN: return
+ app = Application.builder().token(BOT_TOKEN).build()
+ app.add_handler(CommandHandler("start", start))
+ app.add_handler(CallbackQueryHandler(callback_handler))
+ app.run_polling()
+
+if __name__ == "__main__":
+ main()
+EOF
+ chmod +x "$BOT_DIR/bot.py"
}
# โโ ะะพะบะฐะทะฐัั ะดะฐะฝะฝัะต ะฟะพะดะบะปััะตะฝะธั โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
@@ -187,14 +373,10 @@ show_config() {
local PORT=$(echo "$DATA" | grep -oP '(?<="port": ")[^"]*')
local SECRET=$(echo "$DATA" | grep -oP '(?<="secret": ")[^"]*')
local IP4=$(get_ip4)
- local IP6=$(get_ip6)
local LINK="tg://proxy?server=$IP4&port=$PORT&secret=$SECRET"
echo -e "\n${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
- echo -e "${CYAN}โ ะะะะะซะ ะะะะะะฎะงะะะะฏ โ${NC}"
- echo -e "${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
echo -e " IPv4: ${WHITE}$IP4${NC}"
- [ -n "$IP6" ] && echo -e " IPv6: ${WHITE}$IP6${NC}"
echo -e " ะะพัั: ${WHITE}$PORT${NC} (TCP + UDP)"
echo -e " Secret: ${WHITE}$SECRET${NC}"
echo -e "\n ะกััะปะบะฐ: ${BLUE}$LINK${NC}"
@@ -205,51 +387,24 @@ show_config() {
# โโ 1) ะฃััะฐะฝะพะฒะบะฐ MTProxy โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
menu_install() {
clear
- echo -e "${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
- echo -e "${CYAN}โ ะัะฑะตัะธัะต ะดะพะผะตะฝ ะดะปั ะผะฐัะบะธัะพะฒะบะธ (Fake TLS) โ${NC}"
- echo -e "${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
-
- local domains=(
- "google.com" "wikipedia.org" "habr.com" "github.com"
- "coursera.org" "udemy.com" "medium.com" "stackoverflow.com"
- "bbc.com" "cnn.com" "reuters.com" "nytimes.com"
- "lenta.ru" "rbc.ru" "ria.ru" "kommersant.ru"
- "stepik.org" "duolingo.com" "khanacademy.org" "ted.com"
- )
-
- local best_suggest=$(analyze_best_domain)
- echo -e " ${GREEN}โ ะ ะตะบะพะผะตะฝะดัะตะผัะน ะดะพะผะตะฝ (ะปัััะธะน ะฟะธะฝะณ): $best_suggest${NC}\n"
-
- for i in "${!domains[@]}"; do
- printf " ${YELLOW}%2d)${NC} %-22s" "$((i+1))" "${domains[$i]}"
- [[ $(( (i+1) % 2 )) -eq 0 ]] && echo ""
- done
- echo -e "\n ${CYAN}21)${NC} ะะฒะตััะธ ัะฒะพะน ะดะพะผะตะฝ"
-
- local d_idx DOMAIN
- read -p "ะะฐั ะฒัะฑะพั [1-21]: " d_idx
- if [ "$d_idx" = "21" ]; then
- read -p " ะะฒะตะดะธัะต ะดะพะผะตะฝ: " DOMAIN
- DOMAIN=$(echo "$DOMAIN" | tr -d '[:space:]')
- else
- DOMAIN=${domains[$((d_idx-1))]}
- fi
- DOMAIN=${DOMAIN:-$best_suggest}
+ local domains=("google.com" "wikipedia.org" "github.com" "habr.com")
+ echo -e "${CYAN}ะัะฑะตัะธัะต ะดะพะผะตะฝ (Fake TLS):${NC}"
+ for i in "${!domains[@]}"; do echo -e " ${YELLOW}$((i+1)))${NC} ${domains[$i]}"; done
+ read -p "ะัะฑะพั: " d_idx
+ DOMAIN=${domains[$((d_idx-1))]:-google.com}
local PORT=$(find_smart_port)
- echo -e " ${GREEN}โ${NC} ะัะพะณะพะฒัะน ะฟะพัั: ${WHITE}$PORT${NC}"
-
optimize_system
fix_firewall "$PORT"
- spinner_start "ะะฐะฟััะบ ะบะพะฝัะตะนะฝะตัะฐ (ะบะพะผะฐะฝะดะฐ ะพัะธะณะธะฝะฐะปะฐ)..."
+ spinner_start "ะะฐะฟััะบ ะบะพะฝัะตะนะฝะตัะฐ..."
docker pull nineseconds/mtg:2 >/dev/null 2>&1
local SECRET=$(docker run --rm nineseconds/mtg:2 generate-secret --hex "$DOMAIN" 2>/dev/null)
docker stop "$CONTAINER_NAME" &>/dev/null
docker rm "$CONTAINER_NAME" &>/dev/null
- # ะะกะะะะฌะะฃะะ ะขะะงะะฃะฎ ะะะะะะะฃ, ะะะขะะ ะะฏ ะ ะะะะขะะะ ะ ะะ ะะะะะะะ
+ # ะะะะะ: ะฟัะพะฑัะพั UDP ะดะปั ะทะฒะพะฝะบะพะฒ
docker run -d --name "$CONTAINER_NAME" --restart always \
-p "$PORT":"$PORT"/tcp \
-p "$PORT":"$PORT"/udp \
@@ -265,8 +420,6 @@ menu_install() {
echo "{\"domain\": \"$DOMAIN\", \"port\": \"$PORT\", \"secret\": \"$SECRET\"}" > "$BOT_DIR/proxy.json"
echo -e "\n${GREEN}โ SwiftGram ััะฟะตัะฝะพ ะทะฐะฟััะตะฝ!${NC}"
show_config
- else
- echo -e "\n${RED}โ ะัะธะฑะบะฐ ะทะฐะฟััะบะฐ. ะัะพะฒะตัััะต: docker logs $CONTAINER_NAME${NC}"
fi
read -p "ะะฐะถะผะธัะต Enter..."
}
@@ -274,27 +427,17 @@ menu_install() {
# โโ 3) ะะฐัััะพะนะบะฐ ะฑะพัะฐ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
menu_setup_bot() {
clear
- echo -e "${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
- echo -e "${CYAN}โ ะะะกะขะ ะะะะ TELEGRAM ะะะขะ โ${NC}"
- echo -e "${CYAN}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
+ echo -e "${CYAN}ะะฐัััะพะนะบะฐ Telegram ะฑะพัะฐ...${NC}"
+ if ! command -v python3 &>/dev/null; then run_with_progress "Python3" install_pkg python3 python3-pip python3-venv; fi
+
+ prepare_bot_source
- if ! command -v python3 &>/dev/null; then run_with_progress "ะฃััะฐะฝะพะฒะบะฐ Python3" install_pkg python3 python3-pip python3-venv; fi
- mkdir -p "$BOT_DIR"
cd "$BOT_DIR"
-
- spinner_start "ะะฐะณััะทะบะฐ ะผะพะดัะปะตะน ะฑะพัะฐ..."
- curl -sL "$REPO_RAW_URL/requirements.txt" -o "requirements.txt"
- curl -sL "$REPO_RAW_URL/bot.py" -o "bot.py"
- spinner_stop
-
[ ! -d "venv" ] && python3 -m venv venv >/dev/null 2>&1
- ./venv/bin/pip install --upgrade pip -q
./venv/bin/pip install -r requirements.txt -q
- echo -e "\n${YELLOW}ะะฒะตะดะธัะต BOT_TOKEN:${NC}"
- read -r TOKEN
- echo -e "${YELLOW}ะะฐั Telegram ID:${NC}"
- read -r ADMIN_ID
+ read -p "ะะฒะตะดะธัะต BOT_TOKEN: " TOKEN
+ read -p "ะะฐั Telegram ID: " ADMIN_ID
{
echo "BOT_TOKEN=$TOKEN"
@@ -302,7 +445,6 @@ menu_setup_bot() {
echo "CONTAINER_NAME=$CONTAINER_NAME"
echo "CONFIG_PATH=$BOT_DIR/proxy.json"
} > .env
- chmod 600 .env
cat > "/etc/systemd/system/${SERVICE_NAME}.service" << EOF
[Unit]
@@ -324,27 +466,6 @@ EOF
read -p "ะะฐะถะผะธัะต Enter..."
}
-# โโ 7) ะฃะดะฐะปะตะฝะธะต โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
-menu_remove() {
- clear
- echo -e "${RED}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
- echo -e "${RED}โ ะฃะะะะะะะ SWIFTGRAM โ${NC}"
- echo -e "${RED}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
- read -p " ะฃะดะฐะปะธัั ะฟะพะปะฝะพัััั? (y/N): " yn
- [[ "$yn" != "y" ]] && return
- local words=("ะฃะะะะะขะฌ" "SWIFTGRAM" "ะะงะะกะขะะ")
- local confirm_word="${words[$((RANDOM % ${#words[@]}))]}"
- echo -e " ะะฒะตะดะธัะต ัะปะพะฒะพ: ${WHITE}$confirm_word${NC}"
- read -p " >>> " input_word
- [[ "$input_word" != "$confirm_word" ]] && return
- spinner_start "ะัะธััะบะฐ..."
- docker stop "$CONTAINER_NAME" &>/dev/null; docker rm "$CONTAINER_NAME" &>/dev/null
- systemctl stop "$SERVICE_NAME" 2>/dev/null; systemctl disable "$SERVICE_NAME" 2>/dev/null
- rm -f "/etc/systemd/system/${SERVICE_NAME}.service"; rm -rf "$BOT_DIR"; rm -f /usr/local/bin/swiftgram
- spinner_stop
- echo -e "${GREEN}โ ะกะธััะตะผะฐ ะพัะธัะตะฝะฐ.${NC}"; read -p "Enter..."
-}
-
# โโ ะะปะฐะฒะฝัะน ัะธะบะป โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
install_base_deps
SELF="$(realpath "$0")"
@@ -352,17 +473,12 @@ SELF="$(realpath "$0")"
while true; do
clear
- echo -e "${MAGENTA}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
- echo -e "${MAGENTA}โ SWIFTGRAM MANAGER (Professional) โ${NC}"
- echo -e "${MAGENTA}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ${NC}"
+ echo -e "${MAGENTA}SWIFTGRAM MANAGER (UDP Fixed)${NC}"
docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$" && echo -e " ะัะพะบัะธ: ${GREEN}ะ ะะะะขะะะข${NC}" || echo -e " ะัะพะบัะธ: ${RED}ะะซะะะฎะงะะ${NC}"
- systemctl is-active --quiet "$SERVICE_NAME" && echo -e " ะะพั: ${GREEN}ะ ะะะะขะะะข${NC}" || echo -e " ะะพั: ${YELLOW}ะะ ะะะกะขะ ะะะ${NC}"
- echo -e "\n ${GREEN}1)${NC} ะฃััะฐะฝะพะฒะธัั / ะะฑะฝะพะฒะธัั ะฟัะพะบัะธ\n ${GREEN}2)${NC} ะะพะบะฐะทะฐัั ะดะฐะฝะฝัะต (QR)\n ${CYAN}3)${NC} ะะฐัััะพะธัั Telegram-ะฑะพัะฐ\n ${GREEN}4)${NC} ะะตัะตะทะฐะฟัััะธัั ะฟัะพะบัะธ\n ${GREEN}5)${NC} ะะพะณะธ ะฟัะพะบัะธ\n ${RED}6)${NC} ะฃะดะฐะปะธัั SwiftGram\n ${WHITE}0)${NC} ะัั
ะพะด"
+ echo -e "\n ${GREEN}1)${NC} ะฃััะฐะฝะพะฒะธัั / ะะฑะฝะพะฒะธัั ะฟัะพะบัะธ\n ${GREEN}2)${NC} ะะพะบะฐะทะฐัั ะดะฐะฝะฝัะต (QR)\n ${CYAN}3)${NC} ะะฐัััะพะธัั ะฑะพัะฐ\n ${RED}6)${NC} ะฃะดะฐะปะธัั\n ${WHITE}0)${NC} ะัั
ะพะด"
read -p "ะัะฝะบั: " m_idx
case $m_idx in
- 1) menu_install ;; 2) clear; show_config; read -p "ะะฐะถะผะธัะต Enter..." ;; 3) menu_setup_bot ;;
- 4) docker restart "$CONTAINER_NAME"; echo "ะะพัะพะฒะพ"; sleep 1 ;;
- 5) docker logs --tail 50 "$CONTAINER_NAME"; read -p "Enter..." ;;
- 6) menu_remove ;; 0) exit 0 ;;
+ 1) menu_install ;; 2) clear; show_config; read -p "Enter..." ;; 3) menu_setup_bot ;;
+ 6) docker stop "$CONTAINER_NAME" && docker rm "$CONTAINER_NAME"; rm -rf "$BOT_DIR"; exit 0 ;; 0) exit 0 ;;
esac
done
\ No newline at end of file