نصب و راه‌اندازی

استقرار روی VPS یا سرور اختصاصی

راه‌اندازی پیشنهادی WZML-X با Docker Compose، پیدا کردن آدرس تونل Cloudflare و آنچه هنگام شروع ربات اتفاق می‌افتد.

این روش پیشنهادی خود پروژه است: ربات و یک تونل Cloudflare در دو کانتینر با Docker Compose اجرا می‌شوند و رابط وب بدون باز کردن هیچ پورتی روی سرور، از طریق یک آدرس https://….trycloudflare.com در دسترس قرار می‌گیرد.

پیش از شروع، موارد صفحهٔ پیش‌نیازها را آماده کنید.

۱. دریافت کد

git clone https://github.com/SilentDemonSD/WZML-X.git
cd WZML-X

۲. ساختن config.py

از روی نمونه یک کپی بسازید و آن را ویرایش کنید:

cp config_sample.py config.py
nano config.py

دست‌کم این پنج متغیر را پر کنید:

BOT_TOKEN = "1234567890:AA..."
OWNER_ID = 123456789
TELEGRAM_API = 1234567
TELEGRAM_HASH = "0123456789abcdef0123456789abcdef"
DATABASE_URL = "mongodb+srv://USERNAME:PASSWORD@CLUSTER.mongodb.net/?retryWrites=true&w=majority"

BASE_URL را می‌توانید خالی بگذارید؛ در این روش ربات آدرس تونل را خودش پیدا می‌کند. توضیح بقیهٔ متغیرها در نحوهٔ پیکربندی و مرجع متغیرها آمده است.

۳. اجرا

ایمیج‌ها را بسازید و ربات را اجرا کنید:

docker compose up -d --build

این دستور دو ایمیج می‌سازد (یکی برای ربات و یکی برای تونل) و هر دو سرویس را در پس‌زمینه اجرا می‌کند. اولین اجرا به خاطر ساخت ایمیج و نصب بسته‌ها کمی طول می‌کشد.

۴. پیدا کردن آدرس تونل

ربات به‌طور پیش‌فرض پشت یک «تونل سریع» (quick tunnel) Cloudflare اجرا می‌شود. آدرس آن را در لاگ سرویس tunnel ببینید:

docker compose logs tunnel

دنبال یک آدرس به شکل https://….trycloudflare.com بگردید. اسکریپت tunnel.sh هر بار که آدرس جدیدی پیدا کند، یک خط جداگانه با پیشوند tunnel_url: هم چاپ می‌کند، پس می‌توانید فقط همان را جدا کنید:

docker compose logs tunnel | grep tunnel_url

این آدرس، آدرس رابط وب ربات شماست. لازم نیست آن را جایی وارد کنید: ربات آن را از فایل مشترک می‌خواند و خودکار در BASE_URL می‌گذارد (در لاگ ربات خطی مثل tunnel_monitor: initial BASE_URL = … می‌بینید).

۵. بررسی اینکه ربات بالا آمده است

لاگ ربات را دنبال کنید:

docker compose logs -f app

وقتی همه چیز آماده باشد، خط WZ Client(s) & Services Started ! را می‌بینید. حالا در تلگرام به ربات /start بفرستید. چون شما مالک ربات هستید، پیام خوش‌آمد و راهنما نمایش داده می‌شود.

۶. توقف، ری‌استارت و لاگ‌ها

توقف و حذف کانتینرها:

docker compose down

دیدن لاگ زندهٔ ربات (با Ctrl+C از آن خارج می‌شوید و ربات متوقف نمی‌شود):

docker compose logs -f app

ری‌استارت کانتینر ربات، مثلاً بعد از ویرایش config.py:

docker compose restart app

دیدن وضعیت سرویس‌ها:

docker compose ps

داخل تلگرام هم دستور /log (برای مالک و سودو) فایل log.txt را می‌فرستد.

پشت صحنه چه اتفاقی می‌افتد؟

سرویس‌ها و والیوم‌ها در docker-compose.yml

سرویسساخته‌شده ازتوضیح
appDockerfileخود ربات. با bash start.sh اجرا می‌شود و سیاست ری‌استارت آن unless-stopped است. پورت 8080 را فقط expose می‌کند و هیچ پورتی روی سرور باز نمی‌کند.
tunneltunnel.Dockerfileیک ایمیج کوچک Alpine با فایل اجرایی cloudflared. با network_mode: "service:app" در شبکهٔ همان کانتینر app اجرا می‌شود و http://localhost:8080 را تونل می‌کند.

مسیرهایی که به کانتینر app وصل می‌شوند:

روی سرورداخل کانتینرکاربرد
./config.py/usr/src/app/config.py (فقط‌خواندنی، :ro)پیکربندی
./accounts/usr/src/app/accountsسرویس‌اکانت‌های گوگل
./downloads/usr/src/app/downloadsفایل‌های در حال دانلود و آپلود
والیوم tunnel_data/data (فقط‌خواندنی)فایل آدرس تونل

سرویس tunnel همان والیوم tunnel_data را با دسترسی نوشتن دارد. اسکریپت tunnel.sh دستور cloudflared tunnel --no-autoupdate --protocol http2 --url http://localhost:8080 را اجرا می‌کند، خروجی را دنبال می‌کند و آدرس trycloudflare.com را در فایل /data/tunnel_url.txt می‌نویسد (مسیر با متغیر محیطی TUNNEL_URL_FILE قابل تغییر است). ربات این فایل را هنگام شروع و بعد از آن هر ۵ ثانیه یک بار می‌خواند و اگر آدرس عوض شده باشد، BASE_URL را به‌روز می‌کند.

Dockerfile

ایمیج ربات بر پایهٔ mysterysd/wzmlx:wzadv ساخته می‌شود؛ بسته‌های requirements.txt با uv در محیط /wzvenv نصب می‌شوند، کل کد در /usr/src/app کپی می‌شود و نقطهٔ ورود bash start.sh است.

ترتیب شروع

start.sh فقط دو کار می‌کند:

python update.py
exec python -m bot

مرحلهٔ اول، update.py:

  1. config.py را می‌خواند. اگر این فایل نباشد، پیام Config.py file is not Added! Checking ENVs.. را ثبت می‌کند و سراغ متغیرهای محیطی می‌رود.
  2. اگر BOT_TOKEN خالی باشد، با پیام BOT_TOKEN variable is missing! Exiting now متوقف می‌شود.
  3. اگر DATABASE_URL داشته باشید، تنظیمات ذخیره‌شده در MongoDB را هم در نظر می‌گیرد.
  4. اگر UPSTREAM_REPO تنظیم شده باشد، کد را از آن مخزن و شاخهٔ UPSTREAM_BRANCH (پیش‌فرض wzv3) به‌روز می‌کند؛ وگرنه No UPSTREAM_REPO set, skipping git update را ثبت می‌کند. جزئیات در به‌روزرسانی.
  5. چند فایل غیرضروری (مثل gen_scripts و README.md) را از داخل کانتینر پاک می‌کند و بسته‌های پایتون را با uv pip install -U -r requirements.txt به‌روز می‌کند.

مرحلهٔ دوم، python -m bot:

  1. پیکربندی از config.py و متغیرهای محیطی بارگذاری می‌شود و بعد تنظیمات و فایل‌های خصوصی ذخیره‌شده در MongoDB روی آن اعمال می‌شوند.
  2. ربات اصلی و در صورت تنظیم، حساب کاربری (USER_SESSION_STRING) و ربات‌های کمکی (HELPER_TOKENS، STREAM_TOKENS) به تلگرام وصل می‌شوند.
  3. اسکریپت setpkgs.sh اجرا می‌شود: Aria2 را به‌صورت سرویس پس‌زمینه با RPC روی پورت 6800 بالا می‌آورد، فهرست ترکرهای عمومی را از ngosang/trackerslist می‌گیرد و به Aria2 می‌دهد، و اگر DISABLE_NZB خاموش باشد، SABnzbd را روی پورت 8070 اجرا می‌کند.
  4. اگر accounts.zip وجود داشته باشد، استخراج می‌شود؛ اگر پوشهٔ accounts نباشد، USE_SERVICE_ACCOUNTS خاموش می‌شود.
  5. qBittorrent (مگر اینکه DISABLE_TORRENTS روشن باشد) با پروفایل configs/qbittorrent اجرا می‌شود.
  6. وب‌سرور (gunicorn با FastAPI) روی پورت متغیر محیطی PORT یا در نبود آن روی 8080 بالا می‌آید و سرور پخش (مگر اینکه DISABLE_STREAM روشن باشد) روی 127.0.0.1:8091 اجرا می‌شود.
  7. آدرس تونل خوانده و در BASE_URL گذاشته می‌شود، تنظیمات در MongoDB ذخیره می‌شوند، JDownloader (اگر DISABLE_JD خاموش باشد) بوت می‌شود، پوشهٔ دانلودها خالی می‌شود (Cleaning Download Directory) و در آخر پلاگین‌ها بارگذاری می‌شوند.
  8. آدرس پنل‌های qBittorrent و SABnzbd به شکل Web UI: qBittorrent: /qbit/?pass=… و Web UI: SABnzbd: /nzb/?pass=… در لاگ چاپ می‌شود.

پورت‌های داخل کانتینر

هیچ‌کدام از این پورت‌ها در docker-compose.yml روی سرور منتشر نمی‌شوند؛ همه داخل کانتینر هستند و دسترسی بیرونی فقط از طریق تونل و رابط وب است.

پورتسرویس
8080رابط وب (قابل تغییر با متغیر محیطی PORT)
6800RPC برنامهٔ Aria2
8090رابط وب qBittorrent (از مسیر /qbit/ رابط وب در دسترس است)
8070SABnzbd (از مسیر /nzb/ رابط وب در دسترس است)
8091سرور پخش، فقط روی 127.0.0.1 (قابل تغییر با متغیر محیطی STREAM_PORT)
8081rclone serve (پیش‌فرض RCLONE_SERVE_PORT)؛ فقط وقتی RCLONE_SERVE_URL تنظیم شده و rclone.conf وجود دارد.

تونل نام‌دار: آدرس ثابت با دامنهٔ خودتان

اگر دامنه‌ای دارید که DNS آن در Cloudflare است، می‌توانید به‌جای تونل سریع از تونل نام‌دار استفاده کنید تا آدرس رابط وب با هر ری‌استارت عوض نشود. مراحل از توضیحات داخل خود docker-compose.yml:

  1. در داشبورد Cloudflare به Networking ← Tunnels ← Create a tunnel بروید.
  2. نوع اتصال Cloudflared را انتخاب کنید، برای تونل نام بگذارید و ذخیره کنید.
  3. در بخش Connectors، توکن داخل دستور نصب (رشته‌ای که با eyJ شروع می‌شود) را کپی کنید.
  4. در بخش Public Hostname یک آدرس مثل subdomain.yourdomain.com بسازید که با نوع HTTP به localhost:8080 اشاره کند.
  5. در docker-compose.yml، سرویس tunnel فعلی را کامنت کنید و بلوک تونل نام‌دار را از حالت کامنت خارج کنید و توکن را جایگزین <YOUR_TOKEN> کنید:
  tunnel:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel --no-autoupdate run --token <YOUR_TOKEN>
    network_mode: "service:app"

در این حالت فایل آدرس تونل نوشته نمی‌شود، پس BASE_URL را خودتان در config.py (یا از /bsetting) برابر آدرس دامنه‌تان قرار دهید، مثلاً https://subdomain.yourdomain.com.

قدم بعدی

مثلاً LEECH_SPLIT_SIZE، /mirror، -up یا «تامبنیل»