ZeroVPN - Full Setup, Bot Commands & Multi-Account Notification
apt update && apt upgrade -y
apt install -y python3 python3-pip python3-venv nano curl tmux unzip
mkdir -p /opt/xd-test && cd /opt/xd-test
python3 -m venv venv && source venv/bin/activate
pip install pycryptodome requests
nano /opt/xd-test/XD-Tools.py
#Python By Bekar VPN Team š
#Channel ā https://t.me/bypassfor
from __future__ import annotations
import argparse
import base64
import json
import os
import re
import sys
import time
import urllib.error
import urllib.request
from Crypto.Cipher import AES
def _qaaa7b7(_v):
return bytes((_c ^ 73 for _c in _v)).decode()
_q8c737d = _qaaa7b7([33, 61, 61, 57, 58, 115, 102, 102, 49, 45, 100, 57, 58, 100, 40, 57, 32, 100, 58, 57, 32, 39, 39, 44, 59, 103, 63, 44, 59, 42, 44, 37, 103, 40, 57, 57, 102, 44, 121, 121, 125, 61, 33, 103, 35, 58])
_qcd4c4b = _qaaa7b7([33, 61, 61, 57, 58, 115, 102, 102, 49, 45, 100, 57, 58, 100, 40, 57, 32, 100, 44, 39, 51, 103, 63, 44, 59, 42, 44, 37, 103, 40, 57, 57, 102, 49, 45, 36, 40, 58, 61, 44, 59, 45, 44, 42, 38, 45, 44])
_qa9a3ec = _qaaa7b7([33, 61, 61, 57, 115, 102, 102, 49, 45, 100, 57, 58, 100, 40, 57, 32, 100, 61, 49, 61, 103, 63, 44, 59, 42, 44, 37, 103, 40, 57, 57, 102, 49, 45, 32, 36, 57, 38, 59, 22, 45, 44, 42, 44, 48, 57, 61])
_q788f19 = _qaaa7b7([57, 38, 32, 60, 48, 61, 59, 44, 62, 56, 40, 58, 98, 116, 55, 103]).encode()
_q2e62bd = _qaaa7b7([59, 125, 61, 46, 63, 122, 43, 123, 51, 42, 36, 45, 30, 127, 19, 103]).encode()
_q692502 = _qaaa7b7([13, 40, 37, 63, 32, 34, 102, 123, 103, 120, 103, 121, 105, 97, 5, 32, 39, 60, 49, 114, 105, 8, 39, 45, 59, 38, 32, 45, 105, 120, 121, 96])
_qf6fd44 = _qaaa7b7([102, 58, 61, 38, 59, 40, 46, 44, 102, 44, 36, 60, 37, 40, 61, 44, 45, 102, 121, 102, 31, 25, 7, 58, 102, 15, 60, 42, 34, 100, 17, 13, 100, 29, 38, 38, 37, 58, 102])
def _qd771f5(_q3e40b2, _q1c1dff=None, _q91f4db=90):
_q57804d = {_qaaa7b7([28, 58, 44, 59, 100, 8, 46, 44, 39, 61]): _q692502, _qaaa7b7([8, 42, 42, 44, 57, 61]): _qaaa7b7([40, 57, 57, 37, 32, 42, 40, 61, 32, 38, 39, 102, 35, 58, 38, 39])}
if _q1c1dff is not None:
_q57804d[_qaaa7b7([10, 38, 39, 61, 44, 39, 61, 100, 29, 48, 57, 44])] = _qaaa7b7([40, 57, 57, 37, 32, 42, 40, 61, 32, 38, 39, 102, 35, 58, 38, 39])
_q1c1dff = json.dumps(_q1c1dff).encode()
_q0f5da9 = urllib.request.Request(_q3e40b2, data=_q1c1dff, headers=_q57804d)
with urllib.request.urlopen(_q0f5da9, timeout=_q91f4db) as _q586035:
return _q586035.read().decode(_qaaa7b7([60, 61, 47, 100, 113]), _qaaa7b7([59, 44, 57, 37, 40, 42, 44]))
def _qc5930d(_qd4bd3f: str) -> bytes:
_q5c608c = base64.b64decode(_qd4bd3f.strip())
_qb89ed0 = AES.new(_q788f19, AES.MODE_CBC, _q2e62bd).decrypt(_q5c608c)
_q6db680 = _qb89ed0[-1]
if 1 <= _q6db680 <= 16 and _qb89ed0[-_q6db680:] == bytes([_q6db680]) * _q6db680:
_qb89ed0 = _qb89ed0[:-_q6db680]
return _qb89ed0
def _q54df72(_q1c1dff: bytes) -> str:
_q6db680 = 16 - len(_q1c1dff) % 16
_q1c1dff = _q1c1dff + bytes([_q6db680]) * _q6db680
_q4b9ad9 = AES.new(_q788f19, AES.MODE_CBC, _q2e62bd).encrypt(_q1c1dff)
return base64.b64encode(_q4b9ad9).decode()
def _q50d85d():
_q2e6e33 = json.loads(_qd771f5(_qcd4c4b, {_qaaa7b7([63, 57, 39, 22, 39, 40, 36, 44]): _qaaa7b7([22, 22, 49, 45, 22, 37, 32, 58, 61, 22, 22])}))
_q2178f3 = [_q56c648.strip() for _q56c648 in _q2e6e33.get(_qaaa7b7([58, 60, 57, 57, 38, 59, 61, 44, 45, 22, 63, 57, 39, 58]), []) if _q56c648.strip()]
if not _q2178f3:
raise ValueError(_qaaa7b7([58, 60, 57, 57, 38, 59, 61, 44, 45, 22, 63, 57, 39, 58, 105, 44, 36, 57, 61, 48]))
return _q2178f3
def _qa51ef9():
_qbabf80 = _qd771f5(_q8c737d)
_q41c8e3, _q2e6e33 = (_qbabf80.find(_qaaa7b7([18])), _qbabf80.rfind(_qaaa7b7([20])))
if _q41c8e3 < 0 or _q2e6e33 <= _q41c8e3:
return {}
return {_q3f3d38.get(_qaaa7b7([39, 40, 36, 44]), _qaaa7b7([])): _q3f3d38.get(_qaaa7b7([32, 42, 38, 39]), _qaaa7b7([])) for _q3f3d38 in json.loads(_qbabf80[_q41c8e3:_q2e6e33 + 1])}
def _q46d242(_q8d2bd3: str) -> bytes:
_qbc08a7 = _qd771f5(_qcd4c4b, {_qaaa7b7([63, 57, 39, 22, 39, 40, 36, 44]): _q8d2bd3})
try:
_q2e6e33 = json.loads(_qbc08a7)
except json.JSONDecodeError:
raise RuntimeError(_qaaa7b7([43, 40, 45, 105, 59, 44, 58, 57, 38, 39, 58, 44, 115, 105]) + _qbc08a7[:200])
if _qaaa7b7([44, 59, 59, 38, 59]) in _q2e6e33:
raise RuntimeError(_q2e6e33[_qaaa7b7([44, 59, 59, 38, 59])])
_q294a2d = _q2e6e33.get(_qaaa7b7([44, 39, 42, 59, 48, 57, 61, 44, 45, 22, 59, 44, 58, 60, 37, 61]))
if not _q294a2d:
raise RuntimeError(_qaaa7b7([44, 39, 42, 59, 48, 57, 61, 44, 45, 22, 59, 44, 58, 60, 37, 61, 105, 36, 32, 58, 58, 32, 39, 46]))
return _qc5930d(_q294a2d)
def _qd16aba(_q8cb9bb: str, _qf6b73d: str=_qaaa7b7([61, 44, 49, 61]), _q424f77: str=_qaaa7b7([47, 32, 37, 44])) -> bytes:
_q07fe7c = {_qaaa7b7([42, 38, 39, 61, 44, 39, 61]): _q8cb9bb, _qaaa7b7([47, 32, 37, 44, 22, 61, 48, 57, 44]): _qf6b73d, _qaaa7b7([58, 38, 60, 59, 42, 44]): _qaaa7b7([40, 60, 61, 38, 22, 45, 44, 63, 32, 42, 44]), _qaaa7b7([61, 32, 36, 44, 58, 61, 40, 36, 57]): str(int(time.time() * 1000)), _qaaa7b7([47, 32, 37, 44, 39, 40, 36, 44]): _q424f77}
_qbc08a7 = _qd771f5(_qa9a3ec, _q07fe7c)
_q2e6e33 = json.loads(_qbc08a7)
if _qaaa7b7([44, 59, 59, 38, 59]) in _q2e6e33:
raise RuntimeError(_q2e6e33[_qaaa7b7([44, 59, 59, 38, 59])])
return _qc5930d(_q2e6e33[_qaaa7b7([44, 39, 42, 59, 48, 57, 61, 44, 45, 22, 59, 44, 58, 60, 37, 61])])
def _q2ecdf7(_q1ea519: str) -> str:
_q1ea519 = re.sub(_qaaa7b7([18, 21, 21, 102, 115, 99, 118, 107, 117, 119, 53, 21, 49, 121, 121, 100, 21, 49, 120, 47, 20]), _qaaa7b7([22]), _q1ea519).strip()
return _q1ea519 or _qaaa7b7([60, 39, 39, 40, 36, 44, 45])
def _q3d8aa3(_q1c1dff: bytes) -> str:
_q17fd91 = _q1c1dff.lstrip()[:1]
if _q17fd91 == _qaaa7b7([50]).encode():
return _qaaa7b7([103, 35, 58, 38, 39])
if _q17fd91 == _qaaa7b7([18]).encode():
return _qaaa7b7([103, 35, 58, 38, 39])
return _qaaa7b7([103, 61, 49, 61])
def _q554bcd():
_q4681cb = argparse.ArgumentParser(description=_qaaa7b7([17, 13, 105, 29, 38, 38, 37, 58, 105, 42, 38, 39, 47, 32, 46, 105, 45, 44, 42, 59, 48, 57, 61, 38, 59]))
_q4681cb.add_argument(_qaaa7b7([100, 100, 39, 40, 36, 44]), help=_qaaa7b7([45, 44, 42, 59, 48, 57, 61, 105, 58, 32, 39, 46, 37, 44, 105, 63, 57, 39, 105, 43, 48, 105, 39, 40, 36, 44]))
_q4681cb.add_argument(_qaaa7b7([100, 100, 37, 32, 58, 61]), action=_qaaa7b7([58, 61, 38, 59, 44, 22, 61, 59, 60, 44]), help=_qaaa7b7([58, 33, 38, 62, 105, 58, 60, 57, 57, 38, 59, 61, 44, 45, 105, 63, 57, 39, 105, 39, 40, 36, 44, 58]))
_q4681cb.add_argument(_qaaa7b7([100, 100, 47, 32, 37, 44]), help=_qaaa7b7([45, 44, 42, 59, 48, 57, 61, 105, 37, 38, 42, 40, 37, 105, 44, 39, 42, 59, 48, 57, 61, 44, 45, 105, 97, 43, 40, 58, 44, 127, 125, 96, 105, 47, 32, 37, 44]))
_q4681cb.add_argument(_qaaa7b7([100, 100, 38, 60, 61]), default=_qf6fd44, help=_qaaa7b7([38, 60, 61, 57, 60, 61, 105, 45, 32, 59, 44, 42, 61, 38, 59, 48]))
_q4681cb.add_argument(_qaaa7b7([100, 100, 37, 32, 36, 32, 61]), type=int, default=0, help=_qaaa7b7([36, 40, 49, 105, 42, 38, 39, 47, 32, 46, 58, 105, 97, 121, 116, 40, 37, 37, 96]))
_q80a28d = _q4681cb.parse_args()
if _q80a28d.file:
_q1c1dff = _qc5930d(open(_q80a28d.file, encoding=_qaaa7b7([60, 61, 47, 100, 113])).read())
_q1cb7c0 = os.path.join(_q80a28d.out, _q2ecdf7(os.path.basename(_q80a28d.file)) + _qaaa7b7([103, 45, 44, 42]))
os.makedirs(_q80a28d.out, exist_ok=True)
open(_q1cb7c0, _qaaa7b7([62, 43])).write(_q1c1dff)
print(_qaaa7b7([18, 98, 20, 105, 58, 40, 63, 44, 45, 115]), _q1cb7c0)
return
try:
_qd0881d = _q50d85d()
except Exception as _q3f3d38:
print(_qaaa7b7([18, 100, 20, 105, 37, 32, 58, 61, 105, 47, 44, 61, 42, 33, 105, 47, 40, 32, 37, 44, 45, 115]), _q3f3d38, file=sys.stderr)
sys.exit(1)
if _q80a28d.list:
for _q56c648 in _qd0881d:
print(_q56c648)
print(_qaaa7b7([67, 18, 98, 20, 105, 61, 38, 61, 40, 37, 115, 105]) + str(len(_qd0881d)))
return
os.makedirs(_q80a28d.out, exist_ok=True)
_q8ac657 = [_q80a28d.name] if _q80a28d.name else _qd0881d
if _q80a28d.limit:
_q8ac657 = _q8ac657[:_q80a28d.limit]
_q2c85d4 = _q113fa2 = 0
for _q207d90, _q8d2bd3 in enumerate(_q8ac657, 1):
_qefcd5b = _qaaa7b7([18]) + str(_q207d90) + _qaaa7b7([102]) + str(len(_q8ac657)) + _qaaa7b7([20, 105]) + str(_q8d2bd3)
try:
_q1c1dff = _q46d242(_q8d2bd3)
except Exception as _q3f3d38:
print(_qaaa7b7([18, 100, 20, 105]) + str(_qefcd5b) + _qaaa7b7([105, 100, 119, 105]) + str(_q3f3d38))
_q113fa2 += 1
continue
_q0e20ec = os.path.join(_q80a28d.out, _q2ecdf7(_q8d2bd3) + _q3d8aa3(_q1c1dff))
with open(_q0e20ec, _qaaa7b7([62, 43])) as _q26ba0a:
_q26ba0a.write(_q1c1dff)
print(_qaaa7b7([18, 98, 20, 105]) + str(_qefcd5b) + _qaaa7b7([105, 100, 119, 105]) + str(os.path.basename(_q0e20ec)) + _qaaa7b7([105, 97]) + str(len(_q1c1dff)) + _qaaa7b7([105, 43, 48, 61, 44, 58, 96]))
_q2c85d4 += 1
print(_qaaa7b7([67, 18, 98, 20, 105, 45, 38, 39, 44, 115, 105]) + str(_q2c85d4) + _qaaa7b7([105, 38, 34, 101, 105]) + str(_q113fa2) + _qaaa7b7([105, 47, 40, 32, 37, 44, 45, 105, 100, 119, 105]) + str(_q80a28d.out))
if __name__ == _qaaa7b7([22, 22, 36, 40, 32, 39, 22, 22]):
_q554bcd()
nano /opt/xd-test/bot.py
#!/usr/bin/env python3
import os, sys, zipfile, subprocess, requests, time
# ===== įį®įį±įø į”įį»įįŗį”įįįŗ =====
BOT_TOKEN = "8764708526:AAEn-tq7zy1AUdGn8USzl8Eh6ssc6YlY4eU"
# įį®įį±įį¬įį¾į¬ įį®įį±įø įįÆį¶įøįį»įįŗįį²į· į”įį±į¬įį·įŗįį½į±įį²į· ID įį½į±įįᯠįįį·įŗįį«
ALLOWED_USERS = [
7576434717, # įį°į į”įį±į¬įį·įŗ (įį±į¬įįŗįįÆį)
# 123456789, # įį±į¬įįŗįįįŗ į”įį±į¬įį·įŗ ID įį½į±įįᯠįį®įįᯠįįį·įŗįį«
]
# ==============================
WORK_DIR = "/opt/xd-test"
OUT_DIR = os.path.join(WORK_DIR, "output")
ZIP_PATH = os.path.join(WORK_DIR, "vpn_configs.zip")
TOOL = os.path.join(WORK_DIR, "XD-Tools.py")
PYTHON = os.path.join(WORK_DIR, "venv", "bin", "python3")
OFFSET = 0
def tg_api(method, data=None, files=None):
url = f"https://api.telegram.org/bot{BOT_TOKEN}/{method}"
try:
r = requests.post(url, data=data, files=files, timeout=60)
return r.json()
except Exception as e:
print(f"[!] API Error: {e}", file=sys.stderr)
return {"ok": False}
def send_message(chat_id, text):
res = tg_api("sendMessage", data={"chat_id": chat_id, "text": text, "parse_mode": "HTML"})
if res.get("ok"):
return res["result"]["message_id"]
return None
def delete_message(chat_id, msg_id):
if msg_id:
tg_api("deleteMessage", data={"chat_id": chat_id, "message_id": msg_id})
def send_document(chat_id, path, caption=""):
with open(path, "rb") as f:
tg_api("sendDocument", data={"chat_id": chat_id, "caption": caption}, files={"document": f})
def get_names():
res = subprocess.run([PYTHON, TOOL, "--list"], capture_output=True, text=True)
if res.returncode != 0: return []
names = []
for line in res.stdout.splitlines():
line = line.strip()
if not line or line.startswith("["): continue
names.append(line)
return names
def do_zip(chat_id):
wait_id = send_message(chat_id, "ā³ Downloading all configs to ZIP...\nPlease wait...")
names = get_names()
os.makedirs(OUT_DIR, exist_ok=True)
for f in os.listdir(OUT_DIR): os.remove(os.path.join(OUT_DIR, f))
ok, fail = 0, 0
for i, name in enumerate(names, 1):
r = subprocess.run([PYTHON, TOOL, "--name", name, "--out", OUT_DIR], capture_output=True, text=True)
if r.returncode == 0: ok += 1
else: fail += 1
if os.path.exists(ZIP_PATH): os.remove(ZIP_PATH)
with zipfile.ZipFile(ZIP_PATH, "w", zipfile.ZIP_DEFLATED) as zf:
for root, _, files in os.walk(OUT_DIR):
for fn in files:
full = os.path.join(root, fn)
zf.write(full, os.path.relpath(full, OUT_DIR))
delete_message(chat_id, wait_id)
size_mb = os.path.getsize(ZIP_PATH) / (1024 * 1024)
caption = f"ā
VPN Configs ZIP\nš¦ {ok} ok, {fail} failed\nš¾ {size_mb:.2f} MB"
if size_mb > 50:
send_message(chat_id, "ā ļø ZIP > 50MB, splitting...")
part_size = 45 * 1024 * 1024
with open(ZIP_PATH, "rb") as f:
idx = 1
while True:
chunk = f.read(part_size)
if not chunk: break
pp = f"{ZIP_PATH}.part{idx:02d}"
with open(pp, "wb") as pf: pf.write(chunk)
send_document(chat_id, pp, f"Part {idx}\n{caption}")
os.remove(pp)
idx += 1
else:
send_document(chat_id, ZIP_PATH, caption)
send_message(chat_id, "ā
Done!")
def get_single(chat_id, name):
wait_id = send_message(chat_id, f"ā³ Fetching: {name}...")
os.makedirs(OUT_DIR, exist_ok=True)
r = subprocess.run([PYTHON, TOOL, "--name", name, "--out", OUT_DIR], capture_output=True, text=True)
delete_message(chat_id, wait_id)
if r.returncode != 0:
send_message(chat_id, f"ā Failed: {r.stderr[:200]}")
return
files = os.listdir(OUT_DIR)
if not files:
send_message(chat_id, "ā Config file not created.")
return
latest = max([os.path.join(OUT_DIR, f) for f in files], key=os.path.getctime)
ext = os.path.splitext(latest)[1]
new_path = os.path.join(WORK_DIR, f"{name}{ext}")
os.rename(latest, new_path)
send_document(chat_id, new_path, f"ā
{name}")
os.remove(new_path)
def main():
global OFFSET
print("[*] Bot Started!")
# į
įįįŗįįįÆįįŗįø ALLOWED_USERS įį²į į”į¬įøįįÆį¶įøįį® Noti įįįÆį·įįįŗ
for user in ALLOWED_USERS:
send_message(user, "š Decrypt-Tools Bot is Online!")
time.sleep(0.5) # Telegram API limit įįįįŗį”į±į¬įįŗ įįį
į±į¬įį·įŗįįįŗ
while True:
try:
res = tg_api("getUpdates", data={"offset": OFFSET, "timeout": 30})
if res.get("ok") and res.get("result"):
for update in res["result"]:
OFFSET = update["update_id"] + 1
if "message" not in update or "text" not in update["message"]: continue
msg = update["message"]["text"].strip()
chat_id = update["message"]["chat"]["id"]
if int(chat_id) not in ALLOWED_USERS:
print(f"[!] Unauthorized access attempt by ID: {chat_id}")
continue
if msg in ["/start", "/help"]:
help_txt = (
"š¤ Decrypt-Tools Commands\n\n"
"š /list - View all config names\n"
"š¦ /zip - Get all configs as a ZIP file\n"
"š /get <name> - Get a single config (e.g., /get SIAM VPN)\n"
"š /check - Check if bot is online\n\n"
"Example:\n/get SIAM VPN"
)
send_message(chat_id, help_txt)
elif msg == "/list":
wait_id = send_message(chat_id, "ā³ Fetching list...")
names = get_names()
delete_message(chat_id, wait_id)
if not names:
send_message(chat_id, "ā No configs found.")
else:
text = "š Available Configs:\n" + "\n".join([f"⢠{n}" for n in names])
if len(text) > 4000: text = text[:4000] + "\n\n... (truncated)"
send_message(chat_id, text)
elif msg == "/zip":
do_zip(chat_id)
elif msg.startswith("/get"):
parts = msg.split(" ", 1)
if len(parts) < 2:
send_message(chat_id, "ā ļø Usage: /get SIAM VPN")
else:
get_single(chat_id, parts[1].strip())
elif msg == "/check":
send_message(chat_id, "ā
Bot is running perfectly in the background.")
else:
send_message(chat_id, "ā Unknown command. Type /help")
except Exception as e:
print(f"[!] Loop Error: {e}", file=sys.stderr)
time.sleep(3)
time.sleep(1)
if __name__ == "__main__":
main()
/setcommands
start - Start the bot and show help help - Show available commands list - View all available VPN config names zip - Download all configs as a ZIP file get - Get a single config file (e.g. /get SIAM VPN) check - Check bot status
nano /etc/systemd/system/xdbot.service
[Unit] Description=XD-Tools Telegram Bot After=network.target [Service] Type=simple User=root WorkingDirectory=/opt/xd-test ExecStart=/opt/xd-test/venv/bin/python3 /opt/xd-test/bot.py Restart=always RestartSec=5 [Install] WantedBy=multi-user.target
systemctl daemon-reload systemctl start xdbot systemctl enable xdbot
systemctl restart xdbot
systemctl stop xdbot
journalctl -u xdbot -f