From 2d27411f5408405fa2cad9a8d4f1d8d224b7f2d4 Mon Sep 17 00:00:00 2001
From: niraj
Date: Fri, 1 Dec 2023 23:26:22 +0530
Subject: [PATCH] upgrade
---
.env.example | 10 +-
.github/workflows/build-dev.yml | 4 +-
.github/workflows/build.yml | 8 +-
CONTRIBUTING.md | 68 ---
Dockerfile | 8 +-
LICENSE | 2 +-
README-fa.md | 370 ----------------
README-ru.md | 397 ------------------
README-zh-cn.md | 340 ---------------
README.md | 141 +++----
app/__init__.py | 2 +-
app/dashboard/README.md | 6 +-
app/dashboard/build/404.html | 6 +-
app/dashboard/build/assets/index.ebbb3e66.js | 2 +-
app/dashboard/build/index.html | 6 +-
app/dashboard/build/locales/en.json | 6 +-
app/dashboard/build/locales/fa.json | 4 +-
app/dashboard/build/locales/ru.json | 6 +-
app/dashboard/build/locales/zh.json | 6 +-
app/dashboard/index.html | 6 +-
app/dashboard/package-lock.json | 4 +-
app/dashboard/package.json | 2 +-
app/dashboard/public/locales/en.json | 6 +-
app/dashboard/public/locales/fa.json | 4 +-
app/dashboard/public/locales/ru.json | 6 +-
app/dashboard/public/locales/zh.json | 6 +-
app/dashboard/src/components/Footer.tsx | 4 +-
app/dashboard/src/components/Header.tsx | 4 +-
app/dashboard/src/components/NodesModal.tsx | 4 +-
app/dashboard/src/constants/Project.ts | 6 +-
.../src/utils/userPreferenceStorage.ts | 2 +-
app/telegram/handlers/admin.py | 2 +-
app/utils/crypto.py | 2 +-
app/views/admin.py | 4 +-
app/xray/node.py | 2 +-
cli/README.md | 2 +-
cli/admin.py | 2 +-
cli/utils.py | 2 +-
docker-compose.yml | 6 +-
marzban-cli.py => infinity-cli.py | 0
install_service.sh | 6 +-
marzban.code-workspace | 8 -
42 files changed, 137 insertions(+), 1345 deletions(-)
delete mode 100644 CONTRIBUTING.md
delete mode 100755 README-fa.md
delete mode 100644 README-ru.md
delete mode 100644 README-zh-cn.md
rename marzban-cli.py => infinity-cli.py (100%)
mode change 100755 => 100644
delete mode 100644 marzban.code-workspace
diff --git a/.env.example b/.env.example
index dc7938beb..a6ac25e37 100644
--- a/.env.example
+++ b/.env.example
@@ -2,14 +2,14 @@ UVICORN_HOST = "0.0.0.0"
UVICORN_PORT = 8000
-## We highly recommend add admin using `marzban cli` tool and do not use
+## We highly recommend add admin using `infinity cli` tool and do not use
## the following variables which is somehow hard codded infrmation.
# SUDO_USERNAME = "admin"
# SUDO_PASSWORD = "admin"
-# UVICORN_UDS: "/run/marzban.socket"
-# UVICORN_SSL_CERTFILE = "/var/lib/marzban/certs/example.com/fullchain.pem"
-# UVICORN_SSL_KEYFILE = "/var/lib/marzban/certs/example.com/key.pem"
+# UVICORN_UDS: "/run/infinity.socket"
+# UVICORN_SSL_CERTFILE = "/var/lib/infinity/certs/example.com/fullchain.pem"
+# UVICORN_SSL_KEYFILE = "/var/lib/infinity/certs/example.com/key.pem"
# XRAY_JSON = "xray_config.json"
@@ -28,7 +28,7 @@ UVICORN_PORT = 8000
# DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/xxxxxxx"
-# CUSTOM_TEMPLATES_DIRECTORY="/var/lib/marzban/templates/"
+# CUSTOM_TEMPLATES_DIRECTORY="/var/lib/infinity/templates/"
# CLASH_SUBSCRIPTION_TEMPLATE="clash/my-custom-template.yml"
# SUBSCRIPTION_PAGE_TEMPLATE="subscription/index.html"
# HOME_PAGE_TEMPLATE="home/index.html"
diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml
index c089bc1e2..e8287a640 100644
--- a/.github/workflows/build-dev.yml
+++ b/.github/workflows/build-dev.yml
@@ -55,5 +55,5 @@ jobs:
platforms: linux/amd64,linux/arm64
push: true
tags: |
- gozargah/marzban:${{github.ref_name}}
- ghcr.io/gozargah/marzban:${{github.ref_name}}
+ Niraj-Dilshan/infinity:${{github.ref_name}}
+ ghcr.io/Niraj-Dilshan/infinity:${{github.ref_name}}
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ea4f20449..dc7cbe46f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -38,7 +38,7 @@ jobs:
platforms: linux/amd64,linux/arm64
push: true
tags: |
- gozargah/marzban:latest
- gozargah/marzban:${{github.ref_name}}
- ghcr.io/gozargah/marzban:latest
- ghcr.io/gozargah/marzban:${{github.ref_name}}
+ Niraj-Dilshan/infinity:latest
+ Niraj-Dilshan/infinity:${{github.ref_name}}
+ ghcr.io/Niraj-Dilshan/infinity:latest
+ ghcr.io/Niraj-Dilshan/infinity:${{github.ref_name}}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 79150ff20..000000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,68 +0,0 @@
-# Contribute to Marzban
-Thanks for considering contributing to Marzban!
-
-## Questions
-
-Please don't ask your questions in issues. Instead, use one of the following ways to ask:
-- Ask on our telegram group: [@Gozargah_Marzban](https://t.me/gozargah_marzban)
-- Ask on our [GitHub Discussions](https://github.com/gozargah/marzban/discussions) for long term discussion or larger questions.
-
-
-## Reporting issues
-
-Include the following information in your post:
-- Describe what you expected to happen.
-- Describe what actually happened. Include server logs or any error that browser shows.
-- If possible, post your xray json config file and what you have set in env (by censoring critical information).
-- Also tell the version of Marzban, Xray and docker (if you use docker) you are using.
-
-
-# Submitting a Pull Request
-If there is not an open issue for what you want to submit, prefer opening one for discussion before working on a PR. You can work on any issue that doesn't have an open PR linked to it or a maintainer assigned to it. These show up in the sidebar. No need to ask if you can work on an issue that interests you.
-
-## Branches
-When starting development on this project, please make sure to create a new branch off the `dev` branch. This helps to keep the `master` branch stable and free of any development work that may not be complete or fully tested.
-
-## Project Structure
-```
-.
-├── app # Backend code (FastAPI - Python)
-│ └── dashboard # Frontend code (React - Typescript)
-├── cli # CLI code (Typer - Python)
-└── xray_api # Client of Xray's gRPC API
-```
-
-## Backend
-Backend is built using FastAPI and uses SQLAlchemy as the ORM for database operations. All Pydantic models can be found in the `app/models` directory, while all database-related operations and models are in the `app/db` directory. The migration scripts for the database (Alembic) can be found in the `app/db/migrations` directory.
-
-### Python Code Formatting
-To maintain consistency in the codebase, we require all code to be formatted using
-```bash
-autopep8 --max-line-length 120
-```
-
-## Frontend
-Frontend is pre-built and served by FastAPI from the `app/dashboard/build` directory. To rebuild the frontend, first make sure you have the necessary dependencies installed by running `npm install` in the `app/dashboard` directory. Then, simply remove the `app/dashboard/build` directory and run the Python code again, and it will rebuild the frontend automatically.
-
-### Components Library
-Frontend uses `Chakra-UI` as the component library, so please adhere to the Chakra-UI approach when contributing. Strive to create components that are cohesive and serve a single purpose. Keep in mind that readability and maintainability are more important than brevity, so prioritize those factors when writing your code.
-
-## Marzban CLI
-Marzban CLI is built using [Typer](https://typer.tiangolo.com/), and its commands' code can be found in `cli` directory. Its documentation is generated using [Typer CLI](https://typer.tiangolo.com/typer-cli/) which can be re-generated by navigating to project's root directory and running the following command:
-
-```bash
-$ PYTHONPATH=$(pwd) typer marzban-cli.py utils docs --name "marzban-cli" --output ./cli/README.md
-```
-
-## Debug Mode
-To run the project in debug mode with auto-reload, you can set the environment variable `DEBUG` to `true`. then by running the `main.py`, the backend and frontend will run separately on different ports.
-
-Note that you must first install the necessary npm packages by running npm install inside the app/dashboard directory before running in debug mode.
-```bash
-cd app/dashboard
-npm install
-cd ../..
-```
-
-If you run the project with debug mode off and delete the `app/dashboard/build` directory, the frontend will be rebuilt automatically on the next run. However, no rebuild will occur while inside debug mode."
-
diff --git a/Dockerfile b/Dockerfile
index 34bc14a40..84a184249 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,7 +8,7 @@ RUN apt-get update \
&& apt-get install -y curl unzip gcc python3-dev \
&& rm -rf /var/lib/apt/lists/*
-RUN bash -c "$(curl -L https://github.com/Gozargah/Marzban-scripts/raw/master/install_latest_xray.sh)"
+RUN bash -c "$(curl -L https://github.com/Niraj-Dilshan/infinity-script/raw/master/install_latest_xray.sh)"
COPY ./requirements.txt /code/
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
@@ -17,8 +17,8 @@ COPY . /code
RUN apt-get remove -y curl unzip gcc python3-dev
-RUN ln -s /code/marzban-cli.py /usr/bin/marzban-cli \
- && chmod +x /usr/bin/marzban-cli \
- && marzban-cli completion install --shell bash
+RUN ln -s /code/infinity-cli.py /usr/bin/infinity-cli \
+ && chmod +x /usr/bin/infinity-cli \
+ && infinity-cli completion install --shell bash
CMD ["bash", "-c", "alembic upgrade head; python main.py"]
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 425d0879d..5c0e71ef1 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 21 January 2023
- Copyright (C) 2023 Gozargah organization.
+ Copyright (C) 2023 Niraj-Dilshan organization.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
diff --git a/README-fa.md b/README-fa.md
deleted file mode 100755
index b92fe6223..000000000
--- a/README-fa.md
+++ /dev/null
@@ -1,370 +0,0 @@
-
-
-
-## فهرست مطالب
-- [بررسی اجمالی](#بررسی-اجمالی)
- - [چرا مرزبان؟](#چرا-مرزبان)
- - [امکانات](#امکانات)
-- [راهنمای نصب](#راهنمای-نصب)
-- [تنظیمات](#تنظیمات)
-- [استفاده از API](#استفاده-از-api)
-- [پشتیبان گیری از مرزبان](#پشتیبان-گیری-از-مرزبان)
-- [ربات تلگرام](#ربات-تلگرام)
-- [رابط خط فرمان (CLI) مرزبان](#رابط-خط-فرمان-cli-مرزبان)
-- [ارسال اعلانها به آدرس وبهوک](#ارسال-اعلانها-به-آدرس-وبهوک)
-- [کمک مالی](#کمک-مالی)
-- [لایسنس](#لایسنس)
-- [مشارکت در توسعه](#مشارکت-در-توسعه)
-
-
-# بررسی اجمالی
-
-مرزبان یک نرم افزار (وب اپلیکیشن) مدیریت پروکسی است که امکان مدیریت چند صد حساب پروکسی را با قدرت و دسترسی بالا فراهم میکند. مرزبان از [Xray-core](https://github.com/XTLS/Xray-core) قدرت گرفته و با Python و React پیاده سازی شده است.
-
-## چرا مرزبان؟
-
-مرزبان دارای یک رابط کاربری ساده است که قابلیت های زیادی دارد. مرزبان امکان ایجاد چند نوع پروکسی برای کاربر ها را فراهم میکند بدون اینکه به تنظیمات پیچیده ای نیاز داشته باشید. به کمک رابط کاربری تحت وب مرزبان، شما میتوانید کاربران را مانیتور، ویرایش و در صورت نیاز، محدود کنید.
-
-### امکانات
-
-- **رابط کاربری تحت وب** آماده
-- به صورت **REST API** پیاده سازی شده
-- پشتیبانی از پروتکل های **Vmess**, **VLESS**, **Trojan** و **Shadowsocks**
-- امکان فعالسازی **چندین پروتکل** برای هر یوزر
-- امکان ساخت **چندین کاربر** بر روی یک inbound
-- پشتیبانی از **چندین inbound** بر روی **یک port** (به کمک fallbacks)
-- محدودیت بر اساس مصرف **ترافیک** و **تاریخ انقضا**
-- محدودیت **ترافیک دوره ای** (به عنوان مثال روزانه، هفتگی و غیره)
-- پشتیبانی از **Subscription link** سازگار با **V2ray** _(مثل نرم افزار های V2RayNG, OneClick, Nekoray و...)_ و **Clash**
-- ساخت **لینک اشتراک گذاری** و **QRcode** به صورت خودکار
-- مانیتورینگ منابع سرور و **مصرف ترافیک**
-- پشتیبانی از تنظیمات xray
-- پشتیبانی از **TLS**
-- **ربات تلگرام**
-- **رابط خط فرمان (CLI)** داخلی
-- قابلیت ایجاد **چندین مدیر** (تکمیل نشده است)
-
-# راهنمای نصب
-
-برای نصب کافیه دستور زیر رو اجرا کنید
-
-```bash
-sudo bash -c "$(curl -sL https://github.com/Gozargah/Marzban-scripts/raw/master/marzban.sh)" @ install
-```
-
-وقتی نصب تمام شد:
-
-- شما لاگ های مرزبان رو مشاهده میکنید که میتوانید با بستن ترمینال یا فشار دادن `Ctrl+C` از آن خارج شوید
-- فایل های مرزبان در پوشه `/opt/marzban` قرار میگیرند
-- فایل تنظیمات در مسیر `/opt/marzban/.env` قرار میگیرد ([تنظیمات](#تنظیمات) را مشاهده کنید)
-- فایل های مهم (اطلاعات) مرزبان در مسیر `/usr/lib/marzban` قرار میگیرند
-- شما از طریق آدرس `http://YOUR_SERVER_IP:8000/dashboard/` میتوانید وارد داشبورد مرزبان شوید (YOUR_SERVER_IP را با آیپی سرور خود عوض کنید)
-
-در مرحله بعد, باید یک ادمین سودو بسازید
-
-```bash
-marzban cli admin create --sudo
-```
-
-تمام! حالا با این اطلاعات میتوانید وارد مرزبان شوید
-
-برای مشاهده راهنمای اسکریپت مرزبان دستور زیر را اجرا کنید
-
-```bash
-marzban --help
-```
-
-اگر مشتاق هستید که مرزبان رو با پایتون و به صورت دستی اجرا کنید، مراحل زیر را مشاهده کنید
-
-
نصب به صورت دستی (پیچیده)
-
-لطفا xray را نصب کنید.
-شما میتواند به کمک [Xray-install](https://github.com/XTLS/Xray-install) این کار را انجام دهید.
-
-```bash
-bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
-```
-
-پروژه را clone کنید و dependency ها را نصب کنید. دقت کنید که نسخه پایتون شما Python>=3.8 باشد.
-
-```bash
-git clone https://github.com/Gozargah/Marzban.git
-cd Marzban
-wget -qO- https://bootstrap.pypa.io/get-pip.py | python3 -
-python3 -m pip install -r requirements.txt
-```
-
-همچنین میتواند از , [Python Virtualenv](https://pypi.org/project/virtualenv/) هم استفاده کنید.
-
-سپس کامند زیر را اجرا کنید تا دیتابیس تنظیم شود.
-
-```bash
-alembic upgrade head
-```
-
-اگر می خواهید از `marzban-cli` استفاده کنید، باید آن را به یک فایل در `$PATH` خود لینک و قابل اجرا (executable) کنید. سپس تکمیل خودکار (auto-completion) آن را نصب کنید:
-
-```bash
-sudo ln -s $(pwd)/marzban-cli.py /usr/bin/marzban-cli
-sudo chmod +x /usr/bin/marzban-cli
-marzban-cli completion install
-```
-
-حالا یک کپی از `.env.example` با نام `.env` بسازید و با یک ادیتور آن را باز کنید و تنظیمات دلخواه خود را انجام دهید. یه عنوان مثال نام کاربری و رمز عبور را می توانید در این فایل تغییر دهید.
-
-```bash
-cp .env.example .env
-nano .env
-```
-
-> برای اطلاعات بیشتر بخش [تنظیمات](#تنظیمات) را مطالعه کنید.
-
-در انتها, مرزبان را به کمک دستور زیر اجرا کنید.
-
-```bash
-python3 main.py
-```
-
-اجرا با استفاده از systemctl در لینوکس
-```
-systemctl enable /var/lib/marzban/marzban.service
-systemctl start marzban
-```
-
-اجرا با nginx
-```
-server {
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
- server_name example.com;
-
- ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
-
- location ~* /(dashboard|api|docs|redoc|openapi.json) {
- proxy_pass http://0.0.0.0:8000;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
-}
-```
-or
-```
-server {
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
- server_name marzban.example.com;
-
- ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
-
- location / {
- proxy_pass http://0.0.0.0:8000;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
-}
-```
-
-به صورت پیشفرض مرزبان در آدرس `http://localhost:8000/dashboard` اجرا میشود. شما میتوانید با تغییر `UVICORN_HOST` و `UVICORN_PORT`، هاست و پورت را تغییر دهید.
-
-
-# تنظیمات
-
-> متغیر های زیر در فایل `env` یا `.env` استفاده میشوند. شما می توانید با تعریف و تغییر آن ها، تنظیمات مرزبان را تغییر دهید.
-
-| توضیحات | متغیر |
-| ----------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------: |
-| نام کاربری مدیر کل | SUDO_USERNAME |
-| رمز عبور مدیر کل | SUDO_PASSWORD |
-| آدرس دیتابیس ([بر اساس مستندات SQLAlchemy](https://docs.sqlalchemy.org/en/20/core/engines.html#database-urls)) | SQLALCHEMY_DATABASE_URL |
-| آدرس هاستی که مرزبان روی آن اجرا میشود (پیشفرض: `0.0.0.0`) | UVICORN_HOST |
-| پورتی که مرزبان روی آن اجرا میشود (پیشفرض: `8000`) | UVICORN_PORT |
-| اجرای مرزبان بر روی یک Unix domain socket | UVICORN_UDS |
-| آدرس گواهی SSL به جهت ایمن کردن پنل مرزبان | UVICORN_SSL_CERTFILE |
-| آدرس کلید گواهی SSL | UVICORN_SSL_KEYFILE |
-| مسیر فایل json تنظیمات xray (پیشفرض: `xray_config.json`) | XRAY_JSON |
-| مسیر باینری xray (پیشفرض: `/usr/local/bin/xray`) | XRAY_EXECUTABLE_PATH |
-| مسیر asset های xray (پیشفرض: `/usr/local/share/xray`) | XRAY_ASSETS_PATH |
-| پیشوند (یا هاست) آدرس های اشتراکی (زمانی کاربرد دارد که نیاز دارید دامنه subscription link ها با دامنه پنل متفاوت باشد) | XRAY_SUBSCRIPTION_URL_PREFIX |
-| تگ inboundای که به عنوان fallback استفاده میشود. | XRAY_FALLBACKS_INBOUND_TAG |
-| تگ های inbound ای که لازم نیست در کانفیگ های ساخته شده وجود داشته باشند. | XRAY_EXCLUDE_INBOUND_TAGS |
-| آدرس محل template های شخصی سازی شده کاربر | CUSTOM_TEMPLATES_DIRECTORY |
-| تمپلیت مورد استفاده برای تولید کانفیگ های Clash (پیشفرض: `clash/default.yml`) | CLASH_SUBSCRIPTION_TEMPLATE |
-| تمپلیت صفحه اطلاعات اشتراک کاربر (پیشفرض `subscription/index.html`) | SUBSCRIPTION_PAGE_TEMPLATE |
-| تمپلیت صفحه اول (پیشفرض: `home/index.html`) | HOME_PAGE_TEMPLATE |
-| توکن ربات تلگرام (دریافت از [@botfather](https://t.me/botfather)) | TELEGRAM_API_TOKEN |
-| آیدی عددی ادمین در تلگرام (دریافت از [@userinfobot](https://t.me/userinfobot)) | TELEGRAM_ADMIN_ID |
-| اجرای ربات از طریق پروکسی | TELEGRAM_PROXY_URL |
-| مدت زمان انقضا توکن دسترسی به پنل مرزبان, `0` به معنای بدون تاریخ انقضا است (پیشفرض: `1440`) | JWT_ACCESS_TOKEN_EXPIRE_MINUTES |
-| فعال سازی داکیومنتیشن به آدرس `/docs` و `/redoc`(پیشفرض: `False`) | DOCS |
-| فعالسازی حالت توسعه (development) (پیشفرض: `False`) | DEBUG |
-| WEBHOOK_ADDRESS | آدرس webhook که تغییرات حالت یک کاربر به آن ارسال میشوند. اگر این متغیر مقدار داشته باشد، ارسال پیامها انجام میشوند. |
-| WEBHOOK_SECRET | متغیری که به عنوان `x-webhook-secret` در header ارسال میشود. (پیشفرض: `None`) |
-| تعداد دفعاتی که برای ارسال یک پیام، در صورت تشخیص خطا در ارسال تلاش دوباره شود (پیشفرض `3`) | NUMBER_OF_RECURRENT_NOTIFICATIONS |
-| مدت زمان بین هر ارسال دوباره پیام در صورت تشخیص خطا در ارسال به ثانیه (پیشفرض: `180`) | RECURRENT_NOTIFICATIONS_TIMEOUT |
-| هنگام رسیدن مصرف کاربر به چه درصدی پیام اخطار به آدرس وبهوک ارسال شود (پیشفرض: `80`) | NOTIFY_REACHED_USAGE_PERCENT |
-| چند روز مانده به انتهای سرویس پیام اخطار به آدرس وبهوک ارسال شود (پیشفرض: `3`) | NOTIFY_DAYS_LEFT |
-
-
-# استفاده از API
-مرزبان به توسعه دهندگانAPI REST ارائه می دهد. برای مشاهده اسناد API در قالب Swagger UI یا ReDoc، متغیر `DOCS=True` را در تنظیمات خود ست کنید و در مرورگر به مسیر `/docs` و `/redoc` بروید.
-
-
-# پشتیبان گیری از مرزبان
-بهتر است همیشه از فایل های مرزبان خود نسخه پشتیبان تهیه کنید تا در صورت خرابی سیستم یا حذف تصادفی اطلاعات از دست نروند. مراحل تهیه نسخه پشتیبان از مرزبان به شرح زیر است:
-
-1. به طور پیش فرض، تمام فایل های مهم مرزبان در `/var/lib/marzban` ذخیره می شوند (در نسخه داکر). کل پوشه `/var/lib/marzban` را در یک مکان پشتیبان مورد نظر خود، مانند هارد دیسک خارجی یا فضای ذخیره سازی ابری کپی کنید.
-2. علاوه بر این، مطمئن شوید که از فایل env خود که حاوی متغیرهای تنظیمات شما است و همچنین فایل پیکربندی Xray خود نسخه پشتیبان تهیه کنید.
-
-با انجام این مراحل، می توانید اطمینان حاصل کنید که از تمام فایل ها و داده های مرزبان خود یک نسخه پشتیبان تهیه کرده اید. به خاطر داشته باشید که نسخه های پشتیبان خود را به طور مرتب به روز کنید تا آنها را به روز نگه دارید.
-
-
-# ربات تلگرام
-مرزبان دارای یک ربات تلگرام داخلی است که می تواند مدیریت سرور، ایجاد و حذف کاربر و ارسال نوتیفیکیشن را انجام دهد. این ربات را می توان با انجام چند مرحله ساده به راحتی فعال کرد
-
-برای فعال کردن ربات تلگرام:
-
-1. در تنظیمات، متغیر`TELEGRAM_API_TOKEN` را به API TOKEN ربات تلگرام خود تنظیم کنید.
-2. همینطور، متغیر`TELEGRAM_ADMIN_ID` را به شناسه عددی حساب تلگرام خود تنظیم کنید. شما میتوانید شناسه خود را از [@userinfobot](https://t.me/userinfobot) دریافت کنید.
-
-
-# رابط خط فرمان (CLI) مرزبان
-مرزبان دارای یک رابط خط فرمان (Command Line Interface / CLI) داخلی است که به مدیران اجازه می دهد با مرزبان ارتباط مستقیم داشته باشند.
-
-اگر از Docker برای مرزبان استفاده می کنید، بهتر است از دستور های `docker exec` یا `docker-compose exec` استفاده کنید تا به پوسته (shell) تعاملی کانتینر مرزبان دسترسی پیدا کنید.
-
-برای مثال، به پوشه ی `docker-compose.yml` مرزبان بروید و دستور زیر را اجرا کنید:
-
-```bash
-$ sudo docker-compose exec -it marzban bash
-```
-
-رابط خط فرمان (CLI) مرزبان از طریق دستور `marzban-cli` هرکجا در دسترس خواهد بود!
-
-برای کسب اطلاعات بیشتر می توانید [مستندات CLI مرزبان](./cli/README.md) را مطالعه کنید.
-
-
-# ارسال اعلانها به آدرس وبهوک
-شما میتوانید آدرسی را برای مرزبان فراهم کنید تا تغییرات کاربران را به صورت اعلان برای شما ارسال کند.
-
-اعلانها به صورت یک درخواست POST به آدرسی که در `WEBHOOK_ADDRESS` فراهم شده به همراه مقدار تعیین شده در `WEBHOOK_SECRET` به عنوان `x-webhook-secret` در header درخواست ارسال میشوند.
-
-نمونهای از درخواست ارسال شده توسط مرزبان:
-
-```
-Headers:
-Host: 0.0.0.0:9000
-User-Agent: python-requests/2.28.1
-Accept-Encoding: gzip, deflate
-Accept: */*
-Connection: keep-alive
-x-webhook-secret: something-very-very-secret
-Content-Length: 107
-Content-Type: application/json
-
-
-
-Body:
-{"username": "marzban_test_user", "action": "user_updated", "enqueued_at": 1680506457.636369, "tries": 0}
-```
-
-انواع مختلف actionهایی که مرزبان ارسال میکند: `user_created`, `user_updated`, `user_deleted`, `user_limited`, `user_expired`, `user_disabled`, `user_enabled`
-
-
-# کمک مالی
-اگر مرزبان را برای شما مفید بوده و میخواهید از توسعه آن حمایت کنید، میتوانید در یکی از طریق یکی از شبکه های کریپتو زیر کمک مالی کنید:
-
-- شبکه TRON (TRX): `TX8kJoDcowQPBFTYHAJR36GyoUKP1Xwzkb`
-- شبکه ETH، BNB، MATIC: `0xFdc9ad32454FA4fc4733270FCc12ddBFb68b83F7`
-- شبکه بیت کوین: `bc1qpys2nefgsjjgae3g3gqy9crsv3h3rm96tlkz0v`
-- شبکه Dogecoin: `DJAocBAu8y6LwhDKUktLAyzV8xyoFeHH6R`
-- شبکه TON: `EQAVf-7hAXHlF-jmrKE44oBwN7HGQFVBLAtrOsev5K4qR4P8`
-
-
-از حمایت شما متشکرم!
-
-
-# لایسنس
-
-توسعه یافته شده در [ناشناس!] و منتشر شده تحت لایسنس [AGPL-3.0](./LICENSE).
-
-
-# مشارکت در توسعه
-این ❤️🔥 تقدیم به همهی کسایی که در توسعه مرزبان مشارکت میکنند! اگر میخواهید مشارکت داشته باشید، لطفاً [دستورالعملهای مشارکت](CONTRIBUTING.md) ما را بررسی کنید و در صورت تمایل Pull Request ارسال کنید یا یک Issue باز کنید. همچنین از شما برای پیوستن به گروه [تلگرام](https://t.me/gozargah_marzban) ما برای حمایت یا کمک به راهنمایی استقبال می کنیم.
-
-لطفا اگر امکانش رو دارید، با بررسی [لیست کار ها](https://github.com/gozargah/marzban/issues) به ما در بهبود مرزبان کمک کنید. کمک های شما با آغوش باز پذیرفته میشه.
-
-
-با تشکر از همه همکارانی که به بهبود مرزبان کمک کردند:
-
-
-## Оглавление
-
-- [Введение](#введение)
- - [Почему Marzban](#почему-marzban)
- - [Функции](#функции)
-- [Руководство по установке](#руководство-по-установке)
-- [Конфигурация](#конфигурация)
-- [API](#api)
-- [Backup](#backup)
-- [Telegram бот](#telegram-bot)
-- [Marzban CLI](#marzban-cli)
-- [Marzban Node](#marzban-node)
-- [Webhook уведомления](#webhook-уведомления)
-- [Поддержка](#поддержка)
-- [Лицензия](#лицензия)
-- [Участники](#участники)
-
-# Введение
-
-Marzban (Персидское слово "Пограничник" - произносится /mærz'ban/) — это инструмент управления прокси-серверами, который предоставляет простой и удобный пользовательский интерфейс для управления сотнями учетных записей прокси на базе [Xray-core](https://github.com/XTLS/Xray-core) и созданный с использованием Python и ReactJS.
-
-## Почему Marzban?
-
-Marzban удобен в использовании, многофункционален и надежен. Он позволяет создавать различные прокси для пользователей без сложной настройки. С помощью встроенного веб-интерфейса можно контролировать, изменять и ограничивать пользователей.
-
-### Функции
-
-- Готовый **Web UI**
-- **REST API** бэкэнд
-- Поддержка [**множества узлов**](#marzban-node) (для распределения инфраструктуры и масштабируемости)
-- Поддержка протоколов **Vmess**, **VLESS**, **Trojan** и **Shadowsocks**
-- Возможность активации **нескольких протоколов** для каждого пользователя
-- **Несколько пользователей** на одном inbound
-- **Несколько inbound** на **одном порту** (поддержка fallbacks)
-- Ограничения на основе **количества трафика** и **срока действия**
-- Ограничение трафика по **периодам** (например выдавать трафик на день, неделю и т. д.)
-- Поддержка **ссылок-подписок** совместимых с **V2ray** _(такие как V2RayNG, OneClick, Nekoray, и др.)_, **Clash** и **ClashMeta**
-- Автоматическая генерация **Ссылок** и **QRcode**
-- Мониторинг ресурсов сервера и **использования трафика**
-- Настраиваемые конфигурации xray
-- Поддержка **TLS** и **REALITY**
-- Встроенный **Telegram Bot**
-- Встроенный **Command Line Interface (CLI)**
-- **Несколько языков**
-- Поддержка **Нескольких администраторов** (WIP)
-
-# Руководство по установке
-
-Выполните быструю установку с помощью следующей команды:
-
-```bash
-sudo bash -c "$(curl -sL https://github.com/Gozargah/Marzban-scripts/raw/master/marzban.sh)" @ install
-```
-
-Когда установка будет завершена:
-- Вы увидите логи, которые можно остановить, нажав `Ctrl+C` или закрыв терминал.
-- Файлы Marzban будут размещены по адресу `/opt/marzban`.
-- Файл конфигурации будет размещен по адресу `/opt/marzban/.env` (см. [Конфигурация](#конфигурация)).
-- Файлы с данными будут размещены по адресу `/var/lib/marzban`.
-- Вы можете получить доступ к панели управления, введя в адресной строке `http://YOUR_SERVER_IP:8000/dashboard/` (заменив YOUR_SERVER_IP на актуальный IP адрес вашего сервера).
-
-Далее, Вам нужно создать главного администратора для входа в панель управления Marzban, выполнив следующую команду:
-
-```bash
-marzban cli admin create --sudo
-```
-
-Готово! Теперь Вы можете войти, используя данные своей учетной записи.
-
-Для того, чтобы увидеть справочное сообщение от скрипта Marzban, выполните команду:
-
-```bash
-marzban --help
-```
-
-Если Вы хотите запустить проект, используя его исходный код, обратитесь к разделу ниже
-
-
Ручная установка
-
-Установите xray на Ваш сервер.
-
-Вы можете сделать это, используя [Xray-install](https://github.com/XTLS/Xray-install):
-
-```bash
-bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
-```
-
-Клонируйте этот проект и установите зависимости (Вам нужен Python >= 3.8):
-
-```bash
-git clone https://github.com/Gozargah/Marzban.git
-cd Marzban
-wget -qO- https://bootstrap.pypa.io/get-pip.py | python3 -
-python3 -m pip install -r requirements.txt
-```
-
-В качестве альтернативы для создания виртуальной среды можно использовать [Python Virtualenv](https://pypi.org/project/virtualenv/).
-
-Затем выполните следующую команду для запуска скрипта миграции базы данных:
-
-```bash
-alembic upgrade head
-```
-
-Если Вы хотите использовать `marzban-cli`, необходимо связать его с файлом в `$PATH`, сделать его исполняемым и установить:
-
-```bash
-sudo ln -s $(pwd)/marzban-cli.py /usr/bin/marzban-cli
-sudo chmod +x /usr/bin/marzban-cli
-marzban-cli completion install
-```
-
-Теперь настало время настройки.
-
-Создайте копию файла `.env.example`, посмотрите его и отредактируйте с помощью текстового редактора,например `nano`.
-
-Возможно, вам захочется изменить учетные данные администратора.
-
-```bash
-cp .env.example .env
-nano .env
-```
-
-> Проверьте раздел [Конфигурации](#конфигурация) для получения большей информации.
-
-В завершение запустите приложение с помощью следующей команды:
-
-```bash
-python3 main.py
-```
-
-Для запуска с помощью linux systemctl (скопируйте файл marzban.service в `/var/lib/marzban/marzban.service`):
-
-```
-systemctl enable /var/lib/marzban/marzban.service
-systemctl start marzban
-```
-
-Для использования с nginx:
-
-```
-server {
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
- server_name example.com;
-
- ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
-
- location ~* /(dashboard|api|docs|redoc|openapi.json) {
- proxy_pass http://0.0.0.0:8000;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
-
- # xray-core ws-path: /
- # client ws-path: /marzban/me/2087
- #
- # All traffic is proxed through port 443, and send to the xray port(2087, 2088 etc.).
- # The '/marzban' in location regex path can changed any characters by yourself.
- #
- # /${path}/${username}/${xray-port}
- location ~* /marzban/.+/(.+)$ {
- proxy_redirect off;
- proxy_pass http://127.0.0.1:$1/;
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
- proxy_set_header Host $http_host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
-}
-```
-
-или:
-
-```
-server {
- listen 443 ssl http2;
- listen [::]:443 ssl http2;
- server_name marzban.example.com;
-
- ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
- ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
-
- location / {
- proxy_pass http://0.0.0.0:8000;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
-}
-```
-
-По умолчанию приложение будет запускаться на `http://localhost:8000/dashboard`. Вы можете настроить его, изменив переменные окружения `UVICORN_HOST` и `UVICORN_PORT`.
-
-
-# Конфигурация
-
-> Ниже приведены настройки, которые можно задать с помощью переменных окружения поместив их в файл `.env`.
-
-| Перменная | Описание |
-| --------------------------------- | ----------------------------------------------------------------------------------------------------- |
-| SUDO_USERNAME | Имя пользователя главного администратора |
-| SUDO_PASSWORD | Пароль главного администратора |
-| SQLALCHEMY_DATABASE_URL | Путь к файлу БД ([SQLAlchemy's docs](https://docs.sqlalchemy.org/en/20/core/engines.html#database-urls)) |
-| UVICORN_HOST | Привязка приложения к хосту (по умолчанию: `0.0.0.0`) |
-| UVICORN_PORT | Привязка приложения к порту (по умолчанию: `8000`) |
-| UVICORN_UDS | Привязка приложения к UNIX domain socket |
-| UVICORN_SSL_CERTFILE | Адрес файла сертификата SSL |
-| UVICORN_SSL_KEYFILE | Адрес файла ключа SSL |
-| XRAY_JSON | Адрес файла JSON конфигурации Xray. (по умолчанию: `xray_config.json`) |
-| XRAY_EXECUTABLE_PATH | Путь к бинарникам Xray (по умолчанию: `/usr/local/bin/xray`) |
-| XRAY_ASSETS_PATH | Путь к папке с рессурсными файлами для Xray (файлы geoip.dat и geosite.dat) (по умолчанию: `/usr/local/share/xray`) |
-| XRAY_SUBSCRIPTION_URL_PREFIX | Префикс адреса подписки |
-| XRAY_FALLBACKS_INBOUND_TAG | Если вы используете входящее соединение с несколькими резервными вариантами, укажите здесь его тег
-| XRAY_EXCLUDE_INBOUND_TAGS | Теги входящих соединений, которые не требуют управления и не должны быть включены в список прокси
-| CUSTOM_TEMPLATES_DIRECTORY | Путь к папке с пользовательскими шаблонами (по умолчанию: `app/templates`) |
-| CLASH_SUBSCRIPTION_TEMPLATE | Шаблон для создания конфигурации Clash (по умолчанию: `clash/default.yml`) |
-| SUBSCRIPTION_PAGE_TEMPLATE | Шаблон для страницы подписки (по умолчанию: `subscription/index.html`) |
-| HOME_PAGE_TEMPLATE | Шаблон главной страницы (по умолчанию: `home/index.html`) |
-| TELEGRAM_API_TOKEN | Токен Telegram-бота (полученный от [@botfather](https://t.me/botfather)) |
-| TELEGRAM_ADMIN_ID | Числовой идентификатор администратора в Telegram (полученный от [@userinfobot](https://t.me/userinfobot)) |
-| TELEGRAM_PROXY_URL | URL прокси для запуска Telegram-бота (если серверы Telegram заблокированы на вашем сервере). |
-| JWT_ACCESS_TOKEN_EXPIRE_MINUTES | Время истечения срока действия доступного токена в минутах, `0` означает "без истечения срока действия" (по умолчанию: `1440`) |
-| DOCS | Активация документации API по адресам `/docs` и `/redoc`. (по умолчанию: `False`) |
-| DEBUG | Активация режима разработки (development) (по умолчанию: `False`) |
-| WEBHOOK_ADDRESS | Адрес Webhook для отправки уведомлений. Уведомления Webhook будут отправляться, если это значение было установлено |
-| WEBHOOK_SECRET | Webhook secret будет передаваться с каждым запросом в виде `x-webhook-secret` в заголовке (по умолчанию: `None`) |
-| NUMBER_OF_RECURRENT_NOTIFICATIONS | Сколько раз повторять попытку отправки уведомления при обнаружении ошибки (по умолчанию: `3`) |
-| RECURRENT_NOTIFICATIONS_TIMEOUT | Тайм-аут между каждым повторным запросом при обнаружении ошибки в секундах (по умолчанию: `180`) |
-| NOTIFY_REACHED_USAGE_PERCENT | При каком проценте использования отправлять предупреждение (по умолчанию: `80`) |
-| NOTIFY_DAYS_LEFT | Когда отправлять предупреждение об истечении срока действия (по умолчанию: `3`) |
-
-# API
-
-Marzban предоставляет REST API, позволяющий разработчикам программно взаимодействовать с сервисами Marzban. Для просмотра документации по API в Swagger UI или ReDoc установите переменную `DOCS=True` и перейдите по ссылкам `/docs` и `/redoc`.
-
-# Backup
-
-Всегда полезно регулярно создавать резервные копии файлов Marzban, чтобы предотвратить потерю данных в случае системных сбоев или случайного удаления. Ниже приведены шаги для создания резервной копии Marzban:
-
-1. По умолчанию все важные файлы Marzban сохраняются в папке `/var/lib/marzban` (в версиях Docker). Скопируйте весь каталог `/var/lib/marzban` в выбранное вами место резервного копирования, например на внешний жесткий диск или в облачное хранилище.
-2. Кроме того, не забудьте сделать резервную копию файла env, содержащего переменные конфигурации, а также файла конфигурации Xray. Если вы устанавливали Marzban с помощью marzban-scripts (рекомендуемый подход к установке), то env и другие конфигурации должны находиться в каталоге `/opt/marzban/`.
-
-Выполнив эти действия, вы сможете обеспечить резервное копирование всех файлов и данных Marzban, а также переменных конфигурации и конфигурации Xray на случай, если в будущем потребуется их восстановить. Не забывайте регулярно обновлять резервные копии, чтобы поддерживать их в актуальном состоянии.
-
-# Telegram Bot
-
-Marzban поставляется с встроенным ботом Telegram, который может управлять сервером, создавать и удалять пользователей, а также отправлять уведомления. Этот бот можно легко включить, выполнив несколько простых шагов, и он предоставляет удобный способ взаимодействия с Marzban без необходимости каждый раз заходить на сервер.
-
-Чтобы включить Telegram-бота, выполните следующие действия:
-
-1. установите `TELEGRAM_API_TOKEN` в качестве API-токена вашего бота.
-2. установите `TELEGRAM_ADMIN_ID` в качестве цифрового ID вашего Telegram-аккаунта, который вы можете получить от [@userinfobot](https://t.me/userinfobot)
-
-# Marzban CLI
-
-Marzban поставляется с встроенным CLI под названием `marzban-cli`, который позволяет администраторам напрямую взаимодействовать с ним.
-
-Если вы установили Marzban с помощью скрипта установки, то доступ к командам cli можно получить, выполнив команду:
-
-```bash
-marzban cli [OPTIONS] COMMAND [ARGS]...
-```
-
-Для получения дополнительной информации можно ознакомиться с [документацией по Marzban CLI](./cli/README.md).
-
-# Marzban Node
-
-Проект Marzban представляет [Marzban-node](https://github.com/gozargah/marzban-node), который помогает Вам в распределении инфраструктуры. С помощью Marzban-node можно распределить инфраструктуру по нескольким узлам, получив такие преимущества, как высокая доступность, масштабируемость и гибкость. Marzban-node позволяет пользователям подключаться к различным серверам, предоставляя им гибкость в выборе, а не ограничиваться только одним сервером.
-Более подробная информация и инструкции по установке приведены в [официальной документации Marzban-node](https://github.com/gozargah/marzban-node).
-
-
-# Webhook уведомления
-
-Вы можете задать адрес webhook, и Marzban будет отправлять уведомления на этот адрес.
-
-Запросы будут отправляться в виде POST-запроса на адрес, указанный в `WEBHOOK_ADDRESS`, с `WEBHOOK_SECRET` в качестве `x-webhook-secret` в заголовках.
-
-Пример запроса, отправленного Marzban:
-
-```
-Headers:
-Host: 0.0.0.0:9000
-User-Agent: python-requests/2.28.1
-Accept-Encoding: gzip, deflate
-Accept: */*
-Connection: keep-alive
-x-webhook-secret: something-very-very-secret
-Content-Length: 107
-Content-Type: application/json
-
-
-
-Body:
-{"username": "marzban_test_user", "action": "user_updated", "enqueued_at": 1680506457.636369, "tries": 0}
-```
-
-Различные типы действий: `user_created`, `user_updated`, `user_deleted`, `user_limited`, `user_expired`, `user_disabled`, `user_enabled`
-
-# Поддержка
-
-Если вы нашли Marzban полезным и хотели бы поддержать его развитие, вы можете сделать пожертвование в одной из следующих криптовалютных сетей:
-
-- TRON network (TRC20): `TX8kJoDcowQPBFTYHAJR36GyoUKP1Xwzkb`
-- ETH, BNB, MATIC network (ERC20, BEP20): `0xFdc9ad32454FA4fc4733270FCc12ddBFb68b83F7`
-- Bitcoin network: `bc1qpys2nefgsjjgae3g3gqy9crsv3h3rm96tlkz0v`
-- Dogecoin network: `DJAocBAu8y6LwhDKUktLAyzV8xyoFeHH6R`
-- TON network: `EQAVf-7hAXHlF-jmrKE44oBwN7HGQFVBLAtrOsev5K4qR4P8`
-
-Спасибо за поддержку!
-
-# Лицензия
-
-Сделано в [Unknown!] и опубликовано под [AGPL-3.0](./LICENSE).
-
-# Участники
-
-Мы ❤️🔥 участников проекта! Если вы хотите внести свой вклад, пожалуйста, ознакомьтесь с нашим [Contributing Guidelines](CONTRIBUTING.md) и не стесняйтесь отправлять запросы на исправление ошибок или сообщить о проблеме. Мы также приглашаем вас присоединиться к нашей группе [Telegram](https://t.me/gozargah_marzban) для получения поддержки.
-
-Проверьте [open issues](https://github.com/gozargah/marzban/issues), чтобы помочь развитию этого проекта.
-
-
-Спасибо всем участникам, благодаря которым Marzban становится лучше:
-
-
-
-## 目录
-- [概览](#概览)
- - [为什么要使用 Marzban?](#为什么要使用-marzban)
- - [特性](#特性)
-- [安装指南](#安装指南)
-- [配置](#配置)
-- [如何使用 API](#如何使用-api)
-- [如何备份 Marzban](#如何备份-marzban)
-- [Telegram bot](#telegram-bot)
-- [捐赠](#捐赠)
-- [许可](#许可)
-- [贡献者](#贡献者)
-
-
-# 概览
-
-Marzban(Marzban一词源自波斯语,意为“边境警卫”,发音为 /mærz'ban/)是一个代理管理工具,提供简单易用的用户界面,可管理数百个代理账户,由 [Xray-core](https://github.com/XTLS/Xray-core) 提供支持,使用 Python 和 Reactjs 构建。
-
-
-
-## 为什么要使用 Marzban?
-
-Marzban 是一个用户友好、功能丰富且可靠的工具。它让您可以为用户创建不同的代理,无需进行任何复杂的配置。通过其内置的 Web 界面,您可以监视、修改和限制用户。
-
-### 特性
-
-- 内置 **Web 界面**
-- 完全支持 **REST API** 的后端
-- 支持 **Vmess**、**VLESS**、**Trojan** 和 **Shadowsocks** 协议
-- 单用户的**多协议**支持
-- 单入站的**多用户**支持
-- 单端口的**多入站**支持(使用 fallbacks)
-- **流量**和**过期日期**限制
-- 周期性的流量限制(例如每天、每周等)
-- 兼容 **V2ray** 的**订阅链接**(例如 V2RayNG、OneClick、Nekoray 等)和 **Clash**
-- 自动化的**分享链接**和**二维码**生成器
-- 系统监控和**流量统计**
-- 可自定义的 xray 配置
-- **TLS** 支持
-- 集成的 **Telegram Bot**
-- **多管理员**支持(WIP)
-
-
-# 安装指南
-Run the following command
-
-```bash
-sudo bash -c "$(curl -sL https://github.com/Gozargah/Marzban-scripts/raw/master/marzban.sh)" @ install
-```
-
-Once the installation is complete:
-
-- You will see the logs that you can stop watching them by closing the terminal or pressing `Ctrl+C`
-- The Marzban files will be located at `/opt/marzban`
-- The configuration file can be found at `/opt/marzban/.env` (refer to [configurations](#configuration) section to see variables)
-- The data files will be placed at `/usr/lib/marzban`
-- You can access the Marzban dashboard by opening a web browser and navigating to `http://YOUR_SERVER_IP:8000/dashboard/` (replace YOUR_SERVER_IP with the actual IP address of your server)
-
-Next, you need to create a sudo admin for logging into the Marzban dashboard by the following command
-
-```bash
-marzban cli admin create --sudo
-```
-
-That's it! You can login to your dashboard using these credentials
-
-To see the help message of the Marzban script, run the following command
-
-```bash
-marzban --help
-```
-
-If you are eager to run the project using the source code, check the section below
-
-
## Table of Contents
- [Overview](#overview)
- - [Why using Marzban?](#why-using-marzban)
+ - [Why using infinity?](#why-using-infinity)
- [Features](#features)
- [Installation guide](#installation-guide)
- [Configuration](#configuration)
- [API](#api)
- [Backup](#backup)
- [Telegram Bot](#telegram-bot)
-- [Marzban CLI](#marzban-cli)
-- [Marzban Node](#marzban-node)
+- [infinity CLI](#infinity-cli)
+- [infinity Node](#infinity-node)
- [Webhook notifications](#webhook-notifications)
- [Donation](#donation)
- [License](#license)
@@ -78,17 +78,17 @@
# Overview
-Marzban (the Persian word for "border guard" - pronounced /mærz'ban/) is a proxy management tool that provides a simple and easy-to-use user interface for managing hundreds of proxy accounts powered by [Xray-core](https://github.com/XTLS/Xray-core) and built using Python and Reactjs.
+infinity (the Persian word for "border guard" - pronounced /mærz'ban/) is a proxy management tool that provides a simple and easy-to-use user interface for managing hundreds of proxy accounts powered by [Xray-core](https://github.com/XTLS/Xray-core) and built using Python and Reactjs.
-## Why using Marzban?
+## Why using infinity?
-Marzban is user-friendly, feature-rich and reliable. It lets you to create different proxies for your users without any complicated configuration. Using its built-in web UI, you are able to monitor, modify and limit users.
+infinity is user-friendly, feature-rich and reliable. It lets you to create different proxies for your users without any complicated configuration. Using its built-in web UI, you are able to monitor, modify and limit users.
### Features
- Built-in **Web UI**
- Fully **REST API** backend
-- [**Multiple Nodes**](#marzban-node) support (for infrastructure distribution & scalability)
+- [**Multiple Nodes**](#infinity-node) support (for infrastructure distribution & scalability)
- Supports protocols **Vmess**, **VLESS**, **Trojan** and **Shadowsocks**
- **Multi-protocol** for a single user
- **Multi-user** on a single inbound
@@ -110,29 +110,29 @@ Marzban is user-friendly, feature-rich and reliable. It lets you to create diffe
Run the following command
```bash
-sudo bash -c "$(curl -sL https://github.com/Gozargah/Marzban-scripts/raw/master/marzban.sh)" @ install
+sudo bash -c "$(curl -sL https://github.com/Niraj-Dilshan/infinity-scripts/raw/master/infinity.sh)" @ install
```
Once the installation is complete:
- You will see the logs that you can stop watching them by closing the terminal or pressing `Ctrl+C`
-- The Marzban files will be located at `/opt/marzban`
-- The configuration file can be found at `/opt/marzban/.env` (refer to [configurations](#configuration) section to see variables)
-- The data files will be placed at `/var/lib/marzban`
-- You can access the Marzban dashboard by opening a web browser and navigating to `http://YOUR_SERVER_IP:8000/dashboard/` (replace YOUR_SERVER_IP with the actual IP address of your server)
+- The infinity files will be located at `/opt/infinity`
+- The configuration file can be found at `/opt/infinity/.env` (refer to [configurations](#configuration) section to see variables)
+- The data files will be placed at `/var/lib/infinity`
+- You can access the infinity dashboard by opening a web browser and navigating to `http://YOUR_SERVER_IP:8000/dashboard/` (replace YOUR_SERVER_IP with the actual IP address of your server)
-Next, you need to create a sudo admin for logging into the Marzban dashboard by the following command
+Next, you need to create a sudo admin for logging into the infinity dashboard by the following command
```bash
-marzban cli admin create --sudo
+infinity cli admin create --sudo
```
That's it! You can login to your dashboard using these credentials
-To see the help message of the Marzban script, run the following command
+To see the help message of the infinity script, run the following command
```bash
-marzban --help
+infinity --help
```
If you are eager to run the project using the source code, check the section below
@@ -150,8 +150,8 @@ bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release
Clone this project and install the dependencies (you need Python >= 3.8)
```bash
-git clone https://github.com/Gozargah/Marzban.git
-cd Marzban
+git clone https://github.com/Niraj-Dilshan/infinity.git
+cd infinity
wget -qO- https://bootstrap.pypa.io/get-pip.py | python3 -
python3 -m pip install -r requirements.txt
```
@@ -164,12 +164,12 @@ Then run the following command to run the database migration scripts
alembic upgrade head
```
-If you want to use `marzban-cli`, you should link it to a file in your `$PATH`, make it executable, and install the auto-completion:
+If you want to use `infinity-cli`, you should link it to a file in your `$PATH`, make it executable, and install the auto-completion:
```bash
-sudo ln -s $(pwd)/marzban-cli.py /usr/bin/marzban-cli
-sudo chmod +x /usr/bin/marzban-cli
-marzban-cli completion install
+sudo ln -s $(pwd)/infinity-cli.py /usr/bin/infinity-cli
+sudo chmod +x /usr/bin/infinity-cli
+infinity-cli completion install
```
Now it's time to configuration
@@ -191,11 +191,11 @@ Eventually, launch the application using command below
python3 main.py
```
-To launch with linux systemctl (copy marzban.service file to `/var/lib/marzban/marzban.service`)
+To launch with linux systemctl (copy infinity.service file to `/var/lib/infinity/infinity.service`)
```
-systemctl enable /var/lib/marzban/marzban.service
-systemctl start marzban
+systemctl enable /var/lib/infinity/infinity.service
+systemctl start infinity
```
To use with nginx
@@ -217,13 +217,13 @@ server {
}
# xray-core ws-path: /
- # client ws-path: /marzban/me/2087
+ # client ws-path: /infinity/me/2087
#
# All traffic is proxed through port 443, and send to the xray port(2087, 2088 etc.).
- # The '/marzban' in location regex path can changed any characters by yourself.
+ # The '/infinity' in location regex path can changed any characters by yourself.
#
# /${path}/${username}/${xray-port}
- location ~* /marzban/.+/(.+)$ {
+ location ~* /infinity/.+/(.+)$ {
proxy_redirect off;
proxy_pass http://127.0.0.1:$1/;
proxy_http_version 1.1;
@@ -242,7 +242,7 @@ or
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
- server_name marzban.example.com;
+ server_name infinity.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
@@ -298,50 +298,50 @@ By default the app will be run on `http://localhost:8000/dashboard`. You can con
# API
-Marzban provides a REST API that enables developers to interact with Marzban services programmatically. To view the API documentation in Swagger UI or ReDoc, set the configuration variable `DOCS=True` and navigate to the `/docs` and `/redoc`.
+infinity provides a REST API that enables developers to interact with infinity services programmatically. To view the API documentation in Swagger UI or ReDoc, set the configuration variable `DOCS=True` and navigate to the `/docs` and `/redoc`.
# Backup
-It's always a good idea to backup your Marzban files regularly to prevent data loss in case of system failures or accidental deletion. Here are the steps to backup Marzban:
+It's always a good idea to backup your infinity files regularly to prevent data loss in case of system failures or accidental deletion. Here are the steps to backup infinity:
-1. By default, all Marzban important files are saved in `/var/lib/marzban` (Docker versions). Copy the entire `/var/lib/marzban` directory to a backup location of your choice, such as an external hard drive or cloud storage.
-2. Additionally, make sure to backup your env file, which contains your configuration variables, and also, your Xray config file. If you installed Marzban using marzban-scripts (recommended installation approach), the env and other configurations should be inside `/opt/marzban/` directory.
+1. By default, all infinity important files are saved in `/var/lib/infinity` (Docker versions). Copy the entire `/var/lib/infinity` directory to a backup location of your choice, such as an external hard drive or cloud storage.
+2. Additionally, make sure to backup your env file, which contains your configuration variables, and also, your Xray config file. If you installed infinity using infinity-scripts (recommended installation approach), the env and other configurations should be inside `/opt/infinity/` directory.
-By following these steps, you can ensure that you have a backup of all your Marzban files and data, as well as your configuration variables and Xray configuration, in case you need to restore them in the future. Remember to update your backups regularly to keep them up-to-date.
+By following these steps, you can ensure that you have a backup of all your infinity files and data, as well as your configuration variables and Xray configuration, in case you need to restore them in the future. Remember to update your backups regularly to keep them up-to-date.
# Telegram Bot
-Marzban comes with an integrated Telegram bot that can handle server management, user creation and removal, and send notifications. This bot can be easily enabled by following a few simple steps, and it provides a convenient way to interact with Marzban without having to log in to the server every time.
+infinity comes with an integrated Telegram bot that can handle server management, user creation and removal, and send notifications. This bot can be easily enabled by following a few simple steps, and it provides a convenient way to interact with infinity without having to log in to the server every time.
To enable Telegram Bot:
1. set `TELEGRAM_API_TOKEN` to your bot's API Token
2. set `TELEGRAM_ADMIN_ID` to your Telegram account's numeric ID, you can get your ID from [@userinfobot](https://t.me/userinfobot)
-# Marzban CLI
+# infinity CLI
-Marzban comes with an integrated CLI named `marzban-cli` which allows administrators to have direct interaction with it.
+infinity comes with an integrated CLI named `infinity-cli` which allows administrators to have direct interaction with it.
-If you've installed Marzban using easy install script, you can access the cli commands by running
+If you've installed infinity using easy install script, you can access the cli commands by running
```bash
-marzban cli [OPTIONS] COMMAND [ARGS]...
+infinity cli [OPTIONS] COMMAND [ARGS]...
```
-For more information, You can read [Marzban CLI's documentation](./cli/README.md).
+For more information, You can read [infinity CLI's documentation](./cli/README.md).
-# Marzban Node
+# infinity Node
-The Marzban project introduces the [Marzban-node](https://github.com/gozargah/marzban-node), which revolutionizes infrastructure distribution. With Marzban-node, you can distribute your infrastructure across multiple locations, unlocking benefits such as redundancy, high availability, scalability, flexibility. Marzban-node empowers users to connect to different servers, offering them the flexibility to choose and connect to multiple servers instead of being limited to only one server.
-For more detailed information and installation instructions, please refer to the [Marzban-node official documentation](https://github.com/gozargah/marzban-node)
+The infinity project introduces the [infinity-node](https://github.com/Niraj-Dilshan/infinity-node), which revolutionizes infrastructure distribution. With infinity-node, you can distribute your infrastructure across multiple locations, unlocking benefits such as redundancy, high availability, scalability, flexibility. infinity-node empowers users to connect to different servers, offering them the flexibility to choose and connect to multiple servers instead of being limited to only one server.
+For more detailed information and installation instructions, please refer to the [infinity-node official documentation](https://github.com/Niraj-Dilshan/infinity-node)
# Webhook notifications
-You can set a webhook address and Marzban will send the notifications to that address.
+You can set a webhook address and infinity will send the notifications to that address.
the requests will be sent as a post request to the adress provided by `WEBHOOK_ADDRESS` with `WEBHOOK_SECRET` as `x-webhook-secret` in the headers.
-Example request sent from Marzban:
+Example request sent from infinity:
```
Headers:
@@ -357,41 +357,16 @@ Content-Type: application/json
Body:
-{"username": "marzban_test_user", "action": "user_updated", "enqueued_at": 1680506457.636369, "tries": 0}
+{"username": "infinity_test_user", "action": "user_updated", "enqueued_at": 1680506457.636369, "tries": 0}
```
Different action typs are: `user_created`, `user_updated`, `user_deleted`, `user_limited`, `user_expired`, `user_disabled`, `user_enabled`
# Donation
-If you found Marzban useful and would like to support its development, you can make a donation in one of the following crypto networks:
-
-- TRON network (TRC20): `TX8kJoDcowQPBFTYHAJR36GyoUKP1Xwzkb`
-- ETH, BNB, MATIC network (ERC20, BEP20): `0xFdc9ad32454FA4fc4733270FCc12ddBFb68b83F7`
-- Bitcoin network: `bc1qpys2nefgsjjgae3g3gqy9crsv3h3rm96tlkz0v`
-- Dogecoin network: `DJAocBAu8y6LwhDKUktLAyzV8xyoFeHH6R`
-- TON network: `EQAVf-7hAXHlF-jmrKE44oBwN7HGQFVBLAtrOsev5K4qR4P8`
-
-Thank you for your support!
# License
Made in [Unknown!] and Published under [AGPL-3.0](./LICENSE).
# Contributors
-
-We ❤️🔥 contributors! If you'd like to contribute, please check out our [Contributing Guidelines](CONTRIBUTING.md) and feel free to submit a pull request or open an issue. We also welcome you to join our [Telegram](https://t.me/gozargah_marzban) group for either support or contributing guidance.
-
-Check [open issues](https://github.com/gozargah/marzban/issues) to help the progress of this project.
-
-
-Thanks to the all contributors who have helped improve Marzban:
-
diff --git a/app/__init__.py b/app/__init__.py
index fb3b9fea2..9490715bf 100755
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -14,7 +14,7 @@
app = FastAPI(
- title="MarzbanAPI",
+ title="infinityAPI",
description="Unified GUI Censorship Resistant Solution Powered by Xray",
version=__version__,
docs_url='/docs' if DOCS else None,
diff --git a/app/dashboard/README.md b/app/dashboard/README.md
index 819e840a1..c2545c703 100644
--- a/app/dashboard/README.md
+++ b/app/dashboard/README.md
@@ -1,4 +1,4 @@
-# Dashboard UI for marzban
+# Dashboard UI for infinity
## Requirements
@@ -11,7 +11,7 @@ This project has been developed on the Nodejs v16.17.0 so if you faced any issue
## Install
- git clone https://github.com/gozargah/marz-manager.git
+ git clone https://github.com/Niraj-Dilshan/marz-manager.git
cd marz-manager
yarn install
@@ -25,7 +25,7 @@ Copy `example.env` to `.env` then set the backend api address:
| Name | Description |
| ------------- | ------------------------------------------------------------------------------------ |
-| VITE_BASE_API | The api url of the deployed backend ([Marzban](https://github.com/gozargah/Marzban)) |
+| VITE_BASE_API | The api url of the deployed backend ([infinity](https://github.com/Niraj-Dilshan/infinity)) |
## Start development server
diff --git a/app/dashboard/build/404.html b/app/dashboard/build/404.html
index 001387209..b74707501 100644
--- a/app/dashboard/build/404.html
+++ b/app/dashboard/build/404.html
@@ -3,7 +3,7 @@
- Marzban
+ infinity
-
-
+
+
diff --git a/app/dashboard/build/assets/index.ebbb3e66.js b/app/dashboard/build/assets/index.ebbb3e66.js
index c8d66f98a..7fa09c52b 100644
--- a/app/dashboard/build/assets/index.ebbb3e66.js
+++ b/app/dashboard/build/assets/index.ebbb3e66.js
@@ -1,4 +1,4 @@
-import{i as Ct,B as to,a as ro,b as oo,j as yr,d as j,U as Dt,z as no,r as so,f as io,Q as ao,e as lo,$ as co,c as ht,g as x,h as uo,C as ho,k as pt,u as zt,l as O,m as r,H as w,n as e,T as h,o as po,p as I,s as mo,q as g,t as Qe,J as go,v as Sr,A as mt,w as fo,x as bo,M as re,y as oe,D as ne,E as se,F as ie,G as he,I as Oe,K as Cr,L as xo,N as Ge,O as ae,P as A,R as X,S as wr,V as te,W as E,X as ye,Y as $,Z as fe,_ as N,a0 as gt,a1 as He,a2 as yo,a3 as ge,a4 as ke,a5 as So,a6 as kr,a7 as _r,a8 as $e,a9 as it,aa as Co,ab as Ne,ac as at,ad as Zt,ae as wo,af as vr,ag as Ir,ah as Dr,ai as de,aj as ko,ak as _o,al as vo,am as Io,an as Do,ao as Ut,ap as zr,aq as Ur,ar as ue,as as Yt,at as zo,au as Uo,av as Eo,aw as wt,ax as Lo,ay as Ro,az as To,aA as Ao,aB as Mo,aC as No,aD as lt,aE as Fo,aF as we,aG as Po,aH as k,aI as qe,aJ as Er,aK as Xe,aL as M,aM as Et,aN as Wo,aO as Fe,aP as Pe,aQ as kt,aR as We,aS as ze,aT as Ue,aU as Ee,aV as Le,aW as Re,aX as Te,aY as Qt,aZ as Lt,a_ as Oo,a$ as jo,b0 as Ho,b1 as Lr,b2 as Bo,b3 as Ze,b4 as ct,b5 as Rr,b6 as $o,b7 as Vo,b8 as Tr,b9 as Ar,ba as Mr,bb as Se,bc as Go,bd as Zo,be as Yo,bf as Rt,bg as bt,bh as qt,bi as Nr,bj as Qo,bk as qo,bl as Xt,bm as Xo,bn as Jt,bo as Fr,bp as Jo,bq as Pr,br as Ko,bs as en,bt as Wr,bu as tn,bv as rn,bw as Or,bx as jr,by as Hr,bz as q,bA as on,bB as Br,bC as nn,bD as sn,bE as an,bF as ln,bG as cn,bH as dn,bI as un,bJ as $r,bK as hn,bL as Kt,bM as er,bN as Ae,bO as me,bP as tr,bQ as ce,bR as rr,bS as pn,bT as mn,bU as gn,bV as fn,bW as bn,bX as xn,bY as yn,bZ as Sn,b_ as Cn,b$ as wn,c0 as kn,c1 as _n,c2 as vn,c3 as In,c4 as Dn,c5 as zn,c6 as Un}from"./vendor.11357817.js";(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))i(s);new MutationObserver(s=>{for(const a of s)if(a.type==="childList")for(const l of a.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&i(l)}).observe(document,{childList:!0,subtree:!0});function n(s){const a={};return s.integrity&&(a.integrity=s.integrity),s.referrerpolicy&&(a.referrerPolicy=s.referrerpolicy),s.crossorigin==="use-credentials"?a.credentials="include":s.crossorigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function i(s){if(s.ep)return;s.ep=!0;const a=n(s);fetch(s.href,a)}})();Ct.use(to).use(ro).use(oo).init({debug:{}.NODE_ENV==="development",returnNull:!1,fallbackLng:"en",interpolation:{escapeValue:!1},react:{useSuspense:!1},load:"languageOnly",detection:{caches:["localStorage","sessionStorage","cookie"]},backend:{loadPath:yr(["/dashboard/","locales/{{lng}}.json"])}},function(t,o){j.locale(Ct.language)});Ct.on("languageChanged",t=>{j.locale(t)});Dt("zh-cn",no);Dt("ru",so);Dt("fa",io);const _t=new ao,Vr=t=>{const o=document.querySelector('meta[name="theme-color"]');o==null||o.setAttribute("content",t=="dark"?"#1A202C":"#3B81F6")},En=lo({shadows:{outline:"0 0 0 2px var(--chakra-colors-primary-200)"},fonts:{body:"Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif"},colors:{"light-border":"#d2d2d4",primary:{50:"#9cb7f2",100:"#88a9ef",200:"#749aec",300:"#618ce9",400:"#4d7de7",500:"#396fe4",600:"#3364cd",700:"#2e59b6",800:"#284ea0",900:"#224389"},gray:{750:"#222C3B"}},components:{Alert:{baseStyle:{container:{borderRadius:"6px",fontSize:"sm"}}},Select:{baseStyle:{field:{_dark:{borderColor:"gray.600",borderRadius:"6px"},_light:{borderRadius:"6px"}}}},FormHelperText:{baseStyle:{fontSize:"xs"}},FormLabel:{baseStyle:{fontSize:"sm",fontWeight:"medium",mb:"1",_dark:{color:"gray.300"}}},Input:{baseStyle:{addon:{_dark:{borderColor:"gray.600",_placeholder:{color:"gray.500"}}},field:{_focusVisible:{boxShadow:"none",borderColor:"primary.200",outlineColor:"primary.200"},_dark:{borderColor:"gray.600",_disabled:{color:"gray.400",borderColor:"gray.500"},_placeholder:{color:"gray.500"}}}}},Table:{baseStyle:{table:{borderCollapse:"separate",borderSpacing:0},thead:{borderBottomColor:"light-border"},th:{background:"#F9FAFB",borderColor:"light-border !important",borderBottomColor:"light-border !important",borderTop:"1px solid ",borderTopColor:"light-border !important",_first:{borderLeft:"1px solid",borderColor:"light-border !important"},_last:{borderRight:"1px solid",borderColor:"light-border !important"},_dark:{borderColor:"gray.600 !important",background:"gray.750"}},td:{transition:"all .1s ease-out",borderColor:"light-border",borderBottomColor:"light-border !important",_first:{borderLeft:"1px solid",borderColor:"light-border",_dark:{borderColor:"gray.600"}},_last:{borderRight:"1px solid",borderColor:"light-border",_dark:{borderColor:"gray.600"}},_dark:{borderColor:"gray.600",borderBottomColor:"gray.600 !important"}},tr:{"&.interactive":{cursor:"pointer",_hover:{"& > td":{bg:"gray.200"},_dark:{"& > td":{bg:"gray.750"}}}},_last:{"& > td":{_first:{borderBottomLeftRadius:"8px"},_last:{borderBottomRightRadius:"8px"}}}}}}}});const dt=()=>localStorage.getItem("token"),Ln=t=>{localStorage.setItem("token",t)},Rn=()=>{localStorage.removeItem("token")},Tn=co.create({baseURL:"/api/"}),An=(t,o={})=>(dt()&&(o.headers={...(o==null?void 0:o.headers)||{},Authorization:`Bearer ${dt()}`}),Tn(t,o)),W=An,Mn=ht(t=>({isLoading:!0,isPostLoading:!1,version:null,started:!1,logs_websocket:null,config:"",fetchCoreSettings:()=>{t({isLoading:!0}),Promise.all([W("/core").then(({version:o,started:n,logs_websocket:i})=>t({version:o,started:n,logs_websocket:i})),W("/core/config").then(o=>t({config:o}))]).finally(()=>t({isLoading:!1}))},updateConfig:o=>(t({isPostLoading:!0}),W("/core/config",{method:"PUT",body:o}).finally(()=>{t({isPostLoading:!1})})),restartCore:()=>W("/core/restart",{method:"POST"})}));function ee(t,o=2,n=!1){if(!+t)return"0 B";const i=1024,s=o<0?0:o,a=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],l=Math.floor(Math.log(t)/Math.log(i));return n?[parseFloat((t/Math.pow(i,l)).toFixed(s)),a[l]]:`${parseFloat((t/Math.pow(i,l)).toFixed(s))} ${a[l]}`}const or=t=>{if(t!==null)return t.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")},Nn=x(uo,{baseStyle:{w:5,h:5,position:"relative",zIndex:"2"}}),Fn=x(ho,{baseStyle:{w:5,h:5,position:"relative",zIndex:"2"}}),Pn=x(pt,{baseStyle:{w:5,h:5,position:"relative",zIndex:"2"}}),xt=({title:t,content:o,icon:n})=>r(po,{p:6,borderWidth:"1px",borderColor:"light-border",bg:"#F9FAFB",_dark:{borderColor:"gray.600",bg:"gray.750"},borderStyle:"solid",boxShadow:"none",borderRadius:"12px",width:"full",display:"flex",justifyContent:"space-between",flexDirection:"row",children:[r(w,{alignItems:"center",columnGap:"4",children:[e(I,{p:"2",position:"relative",color:"white",_before:{content:'""',position:"absolute",top:0,left:0,bg:"primary.400",display:"block",w:"full",h:"full",borderRadius:"5px",opacity:".5",z:"1"},_after:{content:'""',position:"absolute",top:"-5px",left:"-5px",bg:"primary.400",display:"block",w:"calc(100% + 10px)",h:"calc(100% + 10px)",borderRadius:"8px",opacity:".4",z:"1"},children:n}),e(h,{color:"gray.600",_dark:{color:"gray.300"},fontWeight:"medium",textTransform:"capitalize",fontSize:"sm",children:t})]}),e(I,{fontSize:"3xl",fontWeight:"semibold",mt:"2",children:o})]}),vt="statistics-query-key",Wn=t=>{const{version:o}=v(),{data:n}=zt({queryKey:vt,queryFn:()=>W("/system"),refetchInterval:5e3,onSuccess:({version:s})=>{o!==s&&v.setState({version:s})}}),{t:i}=O();return r(w,{justifyContent:"space-between",gap:0,columnGap:{lg:4,md:0},rowGap:{lg:0,base:4},display:"flex",flexDirection:{lg:"row",base:"column"},...t,children:[e(xt,{title:i("activeUsers"),content:n&&r(w,{alignItems:"flex-end",children:[e(h,{children:or(n.users_active)}),r(h,{fontWeight:"normal",fontSize:"lg",as:"span",display:"inline-block",pb:"5px",children:["/ ",or(n.total_user)]})]}),icon:e(Nn,{})}),e(xt,{title:i("dataUsage"),content:n&&ee(n.incoming_bandwidth+n.outgoing_bandwidth),icon:e(Fn,{})}),e(xt,{title:i("memoryUsage"),content:n&&r(w,{alignItems:"flex-end",children:[e(h,{children:ee(n.mem_used,1,!0)[0]}),r(h,{fontWeight:"normal",fontSize:"lg",as:"span",display:"inline-block",pb:"5px",children:[ee(n.mem_used,1,!0)[1]," /"," ",ee(n.mem_total,1)]})]}),icon:e(Pn,{})})]})},Gr="marzban-num-users-per-page",nr=10,On=()=>{const t=localStorage.getItem(Gr)||nr.toString();return parseInt(t)||nr},jn=t=>localStorage.setItem(Gr,t),Hn=t=>{for(const o in t)t[o]||delete t[o];return v.setState({loading:!0}),W("/users",{query:t}).then(o=>(v.setState({users:o}),o)).finally(()=>{v.setState({loading:!1})})},Bn=()=>W("/inbounds").then(t=>{v.setState({inbounds:new Map(Object.entries(t))})}).finally(()=>{v.setState({loading:!1})}),v=ht(mo((t,o)=>({version:null,editingUser:null,deletingUser:null,isCreatingNewUser:!1,QRcodeLinks:null,subscribeUrl:null,users:{users:[],total:0},loading:!0,isResetingAllUsage:!1,isEditingHosts:!1,isEditingNodes:!1,isShowingNodesUsage:!1,resetUsageUser:null,revokeSubscriptionUser:null,filters:{username:"",limit:On(),sort:"-created_at"},inbounds:new Map,isEditingCore:!1,refetchUsers:()=>{Hn(o().filters)},resetAllUsage:()=>W("/users/reset",{method:"POST"}).then(()=>{o().onResetAllUsage(!1),o().refetchUsers()}),onResetAllUsage:n=>t({isResetingAllUsage:n}),onCreateUser:n=>t({isCreatingNewUser:n}),onEditingUser:n=>{t({editingUser:n})},onDeletingUser:n=>{t({deletingUser:n})},onFilterChange:n=>{t({filters:{...o().filters,...n}}),o().refetchUsers()},setQRCode:n=>{t({QRcodeLinks:n})},deleteUser:n=>(t({editingUser:null}),W(`/user/${n.username}`,{method:"DELETE"}).then(()=>{t({deletingUser:null}),o().refetchUsers(),_t.invalidateQueries(vt)})),createUser:n=>W("/user",{method:"POST",body:n}).then(()=>{t({editingUser:null}),o().refetchUsers(),_t.invalidateQueries(vt)}),editUser:n=>W(`/user/${n.username}`,{method:"PUT",body:n}).then(()=>{o().onEditingUser(null),o().refetchUsers()}),fetchUserUsage:(n,i)=>{for(const s in i)i[s]||delete i[s];return W(`/user/${n.username}/usage`,{method:"GET",query:i})},onEditingHosts:n=>{t({isEditingHosts:n})},onEditingNodes:n=>{t({isEditingNodes:n})},onShowingNodesUsage:n=>{t({isShowingNodesUsage:n})},setSubLink:n=>{t({subscribeUrl:n})},resetDataUsage:n=>W(`/user/${n.username}/reset`,{method:"POST"}).then(()=>{t({resetUsageUser:null}),o().refetchUsers()}),revokeSubscription:n=>W(`/user/${n.username}/revoke_sub`,{method:"POST"}).then(i=>{t({revokeSubscriptionUser:null,editingUser:i}),o().refetchUsers()})}))),le=({children:t,color:o})=>e(I,{position:"relative",width:"36px",height:"36px",display:"flex",justifyContent:"center",alignItems:"center",_before:{content:'""',display:"block",position:"absolute",top:"0",left:"0",width:"calc(100%)",height:"calc(100%)",bg:`${o}.400`,opacity:".5",borderRadius:"5px",zIndex:"1",_dark:{bg:`${o}.400`}},_after:{content:'""',display:"block",position:"absolute",top:"0",left:"0",width:"calc(100% + 10px)",height:"calc(100% + 10px)",transform:"translate(-5px, -5px)",bg:`${o}.400`,opacity:".4",borderRadius:"8px",zIndex:"1",_dark:{bg:`${o}.400`}},children:e(h,{color:`${o}.500`,_dark:{color:`${o}.900`},position:"relative",zIndex:"2",children:t})});window.ace.define("ace/theme/nord_dark",["require","exports","module","ace/lib/dom"],(t,o,n)=>{o.isDark=!0,o.cssClass="ace-nord-dark",t("../lib/dom").importCssString(o.cssText,o.cssClass)});window.ace.define("ace/theme/dawn",["require","exports","module","ace/lib/dom"],(t,o,n)=>{o.isDark=!1,o.cssClass="ace-dawn",t("../lib/dom").importCssString(o.cssText,o.cssClass)});const $n=g.exports.forwardRef(({json:t,onChange:o,mode:n="code"},i)=>{const{colorMode:s}=Qe(),a={mode:n,onChangeText:o,statusBar:!1,mainMenuBar:!1,theme:s==="dark"?"ace/theme/nord_dark":"ace/theme/dawn"},l=g.exports.useRef(null),u=g.exports.useRef(null);return g.exports.useEffect(()=>(u.current=new go(l.current,a),()=>{u.current&&u.current.destroy()}),[]),g.exports.useEffect(()=>{u.current&&u.current.update(t)},[t]),e(I,{ref:i,border:"1px solid",borderColor:"gray.300",_dark:{borderColor:"gray.500"},borderRadius:5,h:"full",children:e(I,{height:"full",ref:l})})}),sr=500,Vn=x(Sr,{baseStyle:{w:5,h:5}}),Gn=x(mt,{baseStyle:{w:4,h:4}}),Zn=x(fo,{baseStyle:{w:4,h:4}}),Yn=x(bo,{baseStyle:{w:3,h:3}}),Qn=t=>({[He.ReadyState.CONNECTING]:"connecting",[He.ReadyState.OPEN]:"connected",[He.ReadyState.CLOSING]:"closed",[He.ReadyState.CLOSED]:"closed",[He.ReadyState.UNINSTANTIATED]:"closed"})[t],qn=()=>{try{let t=new URL("/api/".startsWith("/")?window.location.origin+"/api/":"/api/");return(t.protocol==="https:"?"wss://":"ws://")+yr([t.host+t.pathname,"/core/logs"])+"?interval=1&token="+dt()}catch(t){return console.error("Unable to generate websocket url"),console.error(t),null}};let xe=[];const Xn=()=>{const{isEditingCore:t}=v(),{fetchCoreSettings:o,updateConfig:n,isLoading:i,config:s,isPostLoading:a,version:l,restartCore:u}=Mn(),p=g.exports.useRef(null),[y,c]=g.exports.useState([]),{t:d}=O(),C=he(),_=Oe({defaultValues:{config:s||{}}});g.exports.useEffect(()=>{s&&_.setValue("config",s)},[s]),g.exports.useEffect(()=>{t&&o()},[t]);const b=g.exports.useRef(!0),S=g.exports.useCallback(Cr(D=>{var Z,L,Y;const F=Math.abs((((Z=p.current)==null?void 0:Z.scrollTop)||0)-(((L=p.current)==null?void 0:L.scrollHeight)||0)+(((Y=p.current)==null?void 0:Y.offsetHeight)||0))<10;p.current&&F?b.current=!0:b.current=!1,D.length<40&&c(D)},300),[]),{readyState:R}=xo(qn(),{onMessage:D=>{xe.push(D.data),xe.length>sr&&(xe=xe.splice(0,xe.length-sr)),S([...xe])},shouldReconnect:()=>!0,reconnectAttempts:10,reconnectInterval:1e3});g.exports.useEffect(()=>{var D;p.current&&b.current&&(p.current.scrollTop=(D=p.current)==null?void 0:D.scrollHeight)},[y]),g.exports.useEffect(()=>()=>{xe=[]},[]);const m=Qn(R.toString()),{mutate:f,isLoading:P}=Ge(u),H=({config:D})=>{n(D).then(()=>{C({title:d("core.successMessage"),status:"success",isClosable:!0,position:"top",duration:3e3})}).catch(F=>{let Z=d("core.generalErrorMessage");typeof F.response._data.detail=="object"&&(Z=F.response._data.detail[Object.keys(F.response._data.detail)[0]]),typeof F.response._data.detail=="string"&&(Z=F.response._data.detail),C({title:Z,status:"error",isClosable:!0,position:"top",duration:3e3})})},U=g.exports.useRef(null),[T,B]=g.exports.useState(!1),G=()=>{var D;document.fullscreenElement?(document.exitFullscreen(),B(!1)):((D=U.current)==null||D.requestFullscreen(),B(!0))};return r("form",{onSubmit:_.handleSubmit(H),children:[r(ae,{children:[r(A,{children:[r(w,{justifyContent:"space-between",alignItems:"flex-start",children:[r(X,{children:[d("core.configuration")," ",i&&e(wr,{isIndeterminate:!0,size:"15px"})]}),e(w,{gap:0,children:e(te,{label:"Xray Version",placement:"top",children:e(E,{height:"100%",textTransform:"lowercase",children:l&&`v${l}`})})})]}),r(I,{position:"relative",ref:U,minHeight:"300px",children:[e(ye,{control:_.control,name:"config",render:({field:D})=>e($n,{json:s,onChange:D.onChange})}),e($,{size:"xs","aria-label":"full screen",variant:"ghost",position:"absolute",top:"2",right:"4",onClick:G,children:T?e(Yn,{}):e(Zn,{})})]})]}),r(A,{mt:"4",children:[r(w,{justifyContent:"space-between",children:[e(X,{children:d("core.logs")}),e(h,{as:X,children:d(`core.socket.${m}`)})]}),e(I,{border:"1px solid",borderColor:"gray.300",bg:"#F9F9F9",_dark:{borderColor:"gray.500",bg:"#2e3440"},borderRadius:5,minHeight:"200px",maxHeight:"250px",p:2,overflowY:"auto",ref:p,children:y.map((D,F)=>e(h,{fontSize:"xs",opacity:.8,whiteSpace:"pre-line",children:D},F))})]})]}),e(fe,{children:r(w,{w:"full",justifyContent:"space-between",children:[e(I,{children:e(N,{size:"sm",leftIcon:e(Gn,{className:gt({"animate-spin":P})}),onClick:()=>f(),children:d(P?"core.restarting":"core.restartCore")})}),e(w,{children:e(N,{size:"sm",variant:"solid",colorScheme:"primary",px:"5",type:"submit",isDisabled:i||a,isLoading:a,children:d("core.save")})})]})})]})},Jn=()=>{const{isEditingCore:t}=v(),o=v.setState.bind(null,{isEditingCore:!1}),{t:n}=O();return r(re,{isOpen:t,onClose:o,size:"3xl",children:[e(oe,{bg:"blackAlpha.300",backdropFilter:"blur(10px)"}),r(ne,{mx:"3",w:"full",children:[e(se,{pt:6,children:r(w,{gap:2,children:[e(le,{color:"primary",children:e(Vn,{color:"white"})}),e(h,{fontWeight:"semibold",fontSize:"lg",children:n("core.title")})]})}),e(ie,{mt:3}),e(Xn,{})]})]})},Je=x(yo,{baseStyle:{w:5,h:5}}),Kn=()=>{const[t,o]=g.exports.useState(!1),{deletingUser:n,onDeletingUser:i,deleteUser:s}=v(),{t:a}=O(),l=he(),u=()=>{i(null)},p=()=>{n&&(o(!0),s(n).then(()=>{l({title:a("deleteUser.deleteSuccess",{username:n.username}),status:"success",isClosable:!0,position:"top",duration:3e3})}).then(u).finally(o.bind(null,!1)))};return r(re,{isCentered:!0,isOpen:!!n,onClose:u,size:"sm",children:[e(oe,{bg:"blackAlpha.300",backdropFilter:"blur(10px)"}),r(ne,{mx:"3",children:[e(se,{pt:6,children:e(le,{color:"red",children:e(Je,{})})}),e(ie,{mt:3}),r(ae,{children:[e(h,{fontWeight:"semibold",fontSize:"lg",children:a("deleteUser.title")}),n&&e(h,{mt:1,fontSize:"sm",_dark:{color:"gray.400"},color:"gray.600",children:e(ge,{components:{b:e("b",{})},children:a("deleteUser.prompt",{username:n.username})})})]}),r(fe,{display:"flex",children:[e(N,{size:"sm",onClick:u,mr:3,w:"full",variant:"outline",children:a("cancel")}),e(N,{size:"sm",w:"full",colorScheme:"red",onClick:p,leftIcon:t?e(ke,{size:"xs"}):void 0,children:a("delete")})]})]})]})},Tt={baseStyle:{w:4,h:4}},es=x(So,Tt),ts=x(kr,Tt),Zr=x(mt,Tt),rs=Cr(t=>{v.getState().onFilterChange({...v.getState().filters,offset:0,username:t})},300),os=({...t})=>{const{loading:o,filters:n,onFilterChange:i,refetchUsers:s,onCreateUser:a}=v(),{t:l}=O(),[u,p]=g.exports.useState(""),y=d=>{p(d.target.value),rs(d.target.value)},c=()=>{p(""),i({...n,offset:0,username:""})};return r(_r,{id:"filters",templateColumns:{lg:"repeat(3, 1fr)",md:"repeat(4, 1fr)",base:"repeat(1, 1fr)"},position:"sticky",top:0,mx:"-6",px:"6",rowGap:4,gap:{lg:4,base:0},bg:"var(--chakra-colors-chakra-body-bg)",py:4,zIndex:"docked",...t,children:[e($e,{colSpan:{base:1,md:2,lg:1},order:{base:2,md:1},children:r(it,{children:[e(Co,{pointerEvents:"none",children:e(es,{})}),e(Ne,{placeholder:l("search"),value:u,borderColor:"light-border",onChange:y}),r(at,{children:[o&&e(ke,{size:"xs"}),n.username&&n.username.length>0&&e($,{onClick:c,"aria-label":"clear",size:"xs",variant:"ghost",children:e(ts,{})})]})]})}),e($e,{colSpan:2,order:{base:1,md:2},children:r(w,{justifyContent:"flex-end",alignItems:"center",h:"full",children:[e($,{"aria-label":"refresh users",disabled:o,onClick:s,size:"sm",variant:"outline",children:e(Zr,{className:gt({"animate-spin":o})})}),e(N,{colorScheme:"primary",size:"sm",onClick:()=>a(!0),px:5,children:l("createUser")})]})})]})},Yr="https://github.com/Gozargah/Marzban",ns="https://github.com/Gozargah",ss="https://github.com/Gozargah/Marzban#donation",Qr=t=>{const{version:o}=v();return e(w,{w:"full",py:"0",position:"relative",...t,children:r(h,{display:"inline-block",flexGrow:1,textAlign:"center",color:"gray.500",fontSize:"xs",children:[e(Zt,{color:"blue.400",href:Yr,children:"Marzban"}),o?` (v${o}), `:", ","Made with \u2764\uFE0F in"," ",e(Zt,{color:"blue.400",href:ns,children:"Gozargah"})]})})},is=x(wo,{baseStyle:{w:4,h:4}}),qr=({actions:t})=>{const{i18n:o}=O();var n=i=>{o.changeLanguage(i)};return r(vr,{placement:"bottom-end",children:[e(Ir,{as:$,size:"sm",variant:"outline",icon:e(is,{}),position:"relative"}),r(Dr,{minW:"100px",zIndex:9999,children:[e(de,{maxW:"100px",fontSize:"sm",onClick:()=>n("en"),children:"English"}),e(de,{maxW:"100px",fontSize:"sm",onClick:()=>n("fa"),children:"\u0641\u0627\u0631\u0633\u06CC"}),e(de,{maxW:"100px",fontSize:"sm",onClick:()=>n("zh-cn"),children:"\u7B80\u4F53\u4E2D\u6587"}),e(de,{maxW:"100px",fontSize:"sm",onClick:()=>n("ru"),children:"\u0420\u0443\u0441\u0441\u043A\u0438\u0439"})]})]})},pe={baseStyle:{w:4,h:4}},as=x(ko,pe),ls=x(_o,pe),cs=x(Sr,pe),ds=x(vo,pe),us=x(Io,pe),hs=x(Do,pe),ps=x(Ut,pe),ms=x(zr,pe),gs=x(pt,pe),fs=x(Ur,pe),ir=x(I,{baseStyle:{bg:"yellow.500",w:"2",h:"2",rounded:"full",position:"absolute"}}),Xr="marzban-menu-notification",bs=()=>{const t=localStorage.getItem(Xr);if(!t)return!0;try{return t&&Uo(parseInt(t))?Eo(new Date,new Date(parseInt(t)))>=7:!0}catch{return!0}},xs=({actions:t})=>{const{onEditingHosts:o,onResetAllUsage:n,onEditingNodes:i,onShowingNodesUsage:s}=v(),{t:a}=O(),{colorMode:l,toggleColorMode:u}=Qe(),[p,y]=g.exports.useState(bs()),c=l==="dark"?"dark_dimmed":l,d=()=>{localStorage.setItem(Xr,new Date().getTime().toString()),y(!1)};return r(w,{gap:2,justifyContent:"space-between",__css:{"& .menuList":{direction:"ltr"}},position:"relative",children:[e(h,{as:"h1",fontWeight:"semibold",fontSize:"2xl",children:a("users")}),p&&e(ir,{top:"0",right:"0",zIndex:9999}),e(I,{overflow:"auto",css:{direction:"rtl"},children:r(w,{alignItems:"center",children:[r(vr,{children:[e(Ir,{as:$,size:"sm",variant:"outline",icon:e(ue,{children:e(ds,{})}),position:"relative"}),r(Dr,{minW:"170px",zIndex:99999,className:"menuList",children:[e(de,{maxW:"170px",fontSize:"sm",icon:e(ps,{}),onClick:o.bind(null,!0),children:a("header.hostSettings")}),e(de,{maxW:"170px",fontSize:"sm",icon:e(ms,{}),onClick:i.bind(null,!0),children:a("header.nodeSettings")}),e(de,{maxW:"170px",fontSize:"sm",icon:e(gs,{}),onClick:s.bind(null,!0),children:a("header.nodesUsage")}),e(de,{maxW:"170px",fontSize:"sm",icon:e(fs,{}),onClick:n.bind(null,!0),children:a("resetAllUsage")}),e(Yt,{to:ss,target:"_blank",children:r(de,{maxW:"170px",fontSize:"sm",icon:e(hs,{}),position:"relative",onClick:d,children:[a("header.donation")," ",p&&e(ir,{top:"3",right:"2"})]})}),e(Yt,{to:"/login",children:e(de,{maxW:"170px",fontSize:"sm",icon:e(us,{}),children:a("header.logout")})})]})]}),e($,{size:"sm",variant:"outline","aria-label":"core settings",onClick:()=>{v.setState({isEditingCore:!0})},children:e(cs,{})}),e(qr,{}),e($,{size:"sm",variant:"outline","aria-label":"switch theme",onClick:()=>{Vr(l=="dark"?"light":"dark"),u()},children:l==="light"?e(as,{}):e(ls,{})}),e(I,{css:{direction:"ltr"},display:"flex",alignItems:"center",pr:"2",__css:{"& span":{display:"inline-flex"}},children:e(zo,{href:Yr,"data-color-scheme":`no-preference: ${c}; light: ${c}; dark: ${c};`,"data-size":"large","data-show-count":"true","aria-label":"Star Marzban on GitHub",children:"Star"})})]})})]})},ys=[{title:"Inbound's default",value:"inbound_default"},{title:"TLS",value:"tls"},{title:"None",value:"none"}],Ss=[{title:"",value:""},{title:"h2",value:"h2"},{title:"http/1.1",value:"http/1.1"},{title:"h2, http/1.1",value:"h2,http/1.1"}],Cs=[{title:"",value:""},...["chrome","firefox","safari","ios","android","edge","360","qq","random","randomized"].map(t=>({title:t,value:t}))],ws=[{title:"none",value:""},{title:"xtls-rprx-vision",value:"xtls-rprx-vision"}],ks=["aes-128-gcm","aes-256-gcm","chacha20-ietf-poly1305"],_s=ht(t=>({isLoading:!1,isPostLoading:!1,hosts:{},fetchHosts:()=>{t({isLoading:!0}),W("/hosts").then(o=>t({hosts:o})).finally(()=>t({isLoading:!1}))},setHosts:o=>(t({isPostLoading:!0}),W("/hosts",{method:"PUT",body:o}).finally(()=>{t({isPostLoading:!1})}))}));const vs=x(kr,{baseStyle:{w:4,h:4}}),Ce=wt.forwardRef(({disabled:t,step:o,label:n,className:i,startAdornment:s,endAdornment:a,type:l="text",placeholder:u,onChange:p,onBlur:y,name:c,value:d,onClick:C,error:_,clearable:b=!1,...S},R)=>{const m=()=>{p&&p({target:{value:"",name:c}})},{size:f="md"}=S,P=l=="number"?Fo:Ne,H=l=="number"?Lo:wt.Fragment,U=l=="number"?{keepWithinRange:!0,precision:5,format:T=>isNaN(parseFloat(String(T)))||Number(parseFloat(String(T)).toFixed(5))===0?T:Number(parseFloat(String(T)).toFixed(5)),min:0,step:o,name:c,type:l,placeholder:u,onChange:T=>{p&&p(T)},onBlur:y,value:d,onClick:C,disabled:t,flexGrow:1,size:f}:{};return r(A,{isInvalid:!!_,children:[n&&e(X,{children:n}),r(it,{size:f,w:"full",rounded:"md",_focusWithin:{outline:"2px solid",outlineColor:"primary.200"},bg:t?"gray.100":"transparent",_dark:{bg:t?"gray.600":"transparent"},children:[s&&e(Ro,{children:s}),r(H,{...U,children:[e(P,{name:c,ref:R,step:o,className:gt(i),type:l,placeholder:u,onChange:p,onBlur:y,value:d,onClick:C,disabled:t,flexGrow:1,_focusVisible:{outline:"none",borderTopColor:"transparent",borderRightColor:"transparent",borderBottomColor:"transparent"},_disabled:{cursor:"not-allowed"},...S,roundedLeft:s?"0":"md",roundedRight:a?"0":"md"}),l=="number"&&e(ue,{children:r(To,{children:[e(Ao,{}),e(Mo,{})]})})]}),a&&e(No,{borderLeftRadius:0,borderRightRadius:"6px",bg:"transparent",children:a}),b&&d&&d.length&&e(at,{borderLeftRadius:0,borderRightRadius:"6px",bg:"transparent",onClick:m,cursor:"pointer",children:e(vs,{})})]}),!!_&&e(lt,{children:_})]})}),yt=x(we,{baseStyle:{bg:"white",_dark:{bg:"gray.700"}}}),Be=x(Ce,{baseStyle:{bg:"white",_dark:{bg:"gray.700"}}}),Is=x(Ut,{baseStyle:{w:5,h:5}}),Me=x(Po,{baseStyle:{w:4,h:4,color:"gray.400",cursor:"pointer"}}),Ds=k.record(k.string().min(1),k.array(k.object({remark:k.string().min(1,"Remark is required"),address:k.string().min(1,"Address is required"),port:k.string().or(k.number()).nullable().transform(t=>typeof t=="number"?t:t!==null&&!isNaN(parseInt(t))?Number(parseInt(t)):null),sni:k.string().nullable(),host:k.string().nullable(),security:k.string(),alpn:k.string(),fingerprint:k.string()}))),rt=x(lt,{baseStyle:{color:"red.400",display:"block",textAlign:"left",w:"100%"}}),zs=({hostKey:t,isOpen:o,toggleAccordion:n})=>{const{inbounds:i}=v(),s=[...i.values()].flat().filter(_=>_.tag===t)[0],a=Et(),{fields:l,append:u,remove:p}=Wo({control:a.control,name:t}),{errors:y}=a.formState,{t:c}=O(),d=y[t],C=()=>{u({host:"",sni:"",port:null,address:"",remark:"",security:"inbound_default",alpn:"",fingerprint:""})};return g.exports.useEffect(()=>{d&&!o&&n()},[d]),r(Fe,{border:"1px solid",_dark:{borderColor:"gray.600"},_light:{borderColor:"gray.200"},borderRadius:"4px",p:1,w:"full",children:[r(Pe,{px:2,borderRadius:"3px",onClick:n,children:[e(h,{as:"span",fontWeight:"medium",fontSize:"sm",flex:"1",textAlign:"left",color:"gray.700",_dark:{color:"gray.300"},children:t}),e(kt,{})]}),e(We,{px:2,pb:2,children:r(M,{gap:3,children:[l.map((_,b)=>{var S,R,m,f,P,H,U,T,B,G,D,F,Z,L,Y,J,tt;return r(M,{border:"1px solid",_dark:{borderColor:"gray.600",bg:"#273142"},_light:{borderColor:"gray.200",bg:"#fcfbfb"},p:2,w:"full",borderRadius:"4px",children:[e(w,{w:"100%",alignItems:"flex-start",children:r(A,{position:"relative",zIndex:10,isInvalid:!!(d&&((S=d[b])==null?void 0:S.remark)),children:[r(it,{children:[e(Be,{...a.register(t+"."+b+".remark"),size:"sm",borderRadius:"4px",placeholder:"Remark"}),e(at,{children:r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(I,{mt:"-8px",children:e(Me,{})})}),e(Ee,{children:r(Le,{children:[e(Re,{}),e(Te,{}),e(Qt,{children:r(I,{fontSize:"xs",children:[e(h,{pr:"20px",children:c("hostsDialog.desc")}),r(h,{children:[r(E,{children:["{","SERVER_IP","}"]})," ",c("hostsDialog.currentServer")]}),r(h,{mt:1,children:[r(E,{children:["{","USERNAME","}"]})," ",c("hostsDialog.username")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_USAGE","}"]})," ",c("hostsDialog.dataUsage")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_LEFT","}"]})," ",c("hostsDialog.remainingData")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_LIMIT","}"]})," ",c("hostsDialog.dataLimit")]}),r(h,{mt:1,children:[r(E,{children:["{","DAYS_LEFT","}"]})," ",c("hostsDialog.remainingDays")]}),r(h,{mt:1,children:[r(E,{children:["{","EXPIRE_DATE","}"]})," ",c("hostsDialog.expireDate")]}),r(h,{mt:1,children:[r(E,{children:["{","JALALI_EXPIRE_DATE","}"]})," ",c("hostsDialog.jalaliExpireDate")]}),r(h,{mt:1,children:[r(E,{children:["{","TIME_LEFT","}"]})," ",c("hostsDialog.remainingTime")]}),r(h,{mt:1,children:[r(E,{children:["{","STATUS_EMOJI","}"]})," ",c("hostsDialog.statusEmoji")]}),r(h,{mt:1,children:[r(E,{children:["{","PROTOCOL","}"]})," ",c("hostsDialog.proxyProtocol")]}),r(h,{mt:1,children:[r(E,{children:["{","TRANSPORT","}"]})," ",c("hostsDialog.proxyMethod")]})]})})]})})]})})]}),d&&((R=d[b])==null?void 0:R.remark)&&e(rt,{children:(f=(m=d[b])==null?void 0:m.remark)==null?void 0:f.message})]})}),r(A,{isInvalid:!!(d&&((P=d[b])==null?void 0:P.address)),children:[r(it,{children:[e(Be,{size:"sm",borderRadius:"4px",placeholder:"Address (e.g. example.com)",...a.register(t+"."+b+".address")}),e(at,{children:r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(I,{mt:"-8px",children:e(Me,{})})}),e(Ee,{children:r(Le,{children:[e(Re,{}),e(Te,{}),e(Qt,{children:r(I,{fontSize:"xs",children:[e(h,{pr:"20px",children:c("hostsDialog.desc")}),r(h,{children:[r(E,{children:["{","SERVER_IP","}"]})," ",c("hostsDialog.currentServer")]}),r(h,{mt:1,children:[r(E,{children:["{","USERNAME","}"]})," ",c("hostsDialog.username")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_USAGE","}"]})," ",c("hostsDialog.dataUsage")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_LEFT","}"]})," ",c("hostsDialog.remainingData")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_LIMIT","}"]})," ",c("hostsDialog.dataLimit")]}),r(h,{mt:1,children:[r(E,{children:["{","DAYS_LEFT","}"]})," ",c("hostsDialog.remainingDays")]}),r(h,{mt:1,children:[r(E,{children:["{","EXPIRE_DATE","}"]})," ",c("hostsDialog.expireDate")]}),r(h,{mt:1,children:[r(E,{children:["{","JALALI_EXPIRE_DATE","}"]})," ",c("hostsDialog.jalaliExpireDate")]}),r(h,{mt:1,children:[r(E,{children:["{","TIME_LEFT","}"]})," ",c("hostsDialog.remainingTime")]}),r(h,{mt:1,children:[r(E,{children:["{","STATUS_EMOJI","}"]})," ",c("hostsDialog.statusEmoji")]}),r(h,{mt:1,children:[r(E,{children:["{","PROTOCOL","}"]})," ",c("hostsDialog.proxyProtocol")]}),r(h,{mt:1,children:[r(E,{children:["{","TRANSPORT","}"]})," ",c("hostsDialog.proxyMethod")]})]})})]})})]})})]}),d&&((H=d[b])==null?void 0:H.address)&&e(rt,{children:(T=(U=d[b])==null?void 0:U.address)==null?void 0:T.message})]}),e(Xe,{w:"full",allowToggle:!0,children:r(Fe,{border:"0",children:[r(Pe,{display:"flex",justifyContent:"space-between",px:0,py:1,borderRadius:3,_hover:{bg:"transparent"},children:[r(h,{fontSize:"xs",color:"gray.600",_dark:{color:"gray.500"},pl:1,children:[c("hostsDialog.advancedOptions"),e(kt,{fontSize:"sm",ml:1})]}),e(te,{label:"Delete",placement:"top",children:e($,{"aria-label":"Delete",size:"sm",colorScheme:"red",variant:"ghost",onClick:p.bind(null,b),children:e(Je,{})})})]}),e(We,{w:"full",p:1,children:r(M,{w:"full",borderRadius:"4px",children:[r(A,{isInvalid:!!(d&&((B=d[b])==null?void 0:B.port)),children:[r(X,{display:"flex",pb:1,alignItems:"center",justifyContent:"space-between",gap:1,m:"0",children:[e("span",{children:c("hostsDialog.port")}),r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(Me,{})}),e(Ee,{children:r(Le,{p:2,children:[e(Re,{}),e(Te,{}),e(h,{fontSize:"xs",pr:5,children:c("hostsDialog.port.info")})]})})]})]}),e(Be,{size:"sm",borderRadius:"4px",placeholder:String(s.port||"8080"),type:"number",...a.register(t+"."+b+".port")})]}),r(A,{isInvalid:!!(d&&((G=d[b])==null?void 0:G.sni)),children:[r(X,{display:"flex",pb:1,alignItems:"center",gap:1,justifyContent:"space-between",m:"0",children:[e("span",{children:c("hostsDialog.sni")}),r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(Me,{})}),e(Ee,{children:r(Le,{p:2,children:[e(Re,{}),e(Te,{}),e(h,{fontSize:"xs",pr:5,children:c("hostsDialog.sni.info")}),e(h,{fontSize:"xs",mt:"2",children:e(ge,{i18nKey:"hostsDialog.host.wildcard",components:{badge:e(E,{})}})}),e(h,{fontSize:"xs",children:e(ge,{i18nKey:"hostsDialog.host.multiHost",components:{badge:e(E,{})}})})]})})]})]}),e(Be,{size:"sm",borderRadius:"4px",placeholder:"SNI (e.g. example.com)",...a.register(t+"."+b+".sni")}),d&&((D=d[b])==null?void 0:D.sni)&&e(rt,{children:(Z=(F=d[b])==null?void 0:F.sni)==null?void 0:Z.message})]}),r(A,{isInvalid:!!(d&&((L=d[b])==null?void 0:L.host)),children:[r(X,{display:"flex",pb:1,alignItems:"center",gap:1,justifyContent:"space-between",m:"0",children:[e("span",{children:c("hostsDialog.host")}),r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(Me,{})}),e(Ee,{children:r(Le,{p:2,children:[e(Re,{}),e(Te,{}),e(h,{fontSize:"xs",pr:5,children:c("hostsDialog.host.info")}),e(h,{fontSize:"xs",mt:"2",children:e(ge,{i18nKey:"hostsDialog.host.wildcard",components:{badge:e(E,{})}})}),e(h,{fontSize:"xs",children:e(ge,{i18nKey:"hostsDialog.host.multiHost",components:{badge:e(E,{})}})})]})})]})]}),e(Be,{size:"sm",borderRadius:"4px",placeholder:"Host (e.g. example.com)",...a.register(t+"."+b+".host")}),d&&((Y=d[b])==null?void 0:Y.host)&&e(rt,{children:(tt=(J=d[b])==null?void 0:J.host)==null?void 0:tt.message})]}),r(A,{height:"66px",children:[r(X,{display:"flex",pb:1,alignItems:"center",gap:1,justifyContent:"space-between",m:"0",children:[e("span",{children:c("hostsDialog.security")}),r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(Me,{})}),e(Ee,{children:r(Le,{p:2,children:[e(Re,{}),e(Te,{}),e(h,{fontSize:"xs",pr:5,children:c("hostsDialog.security.info")})]})})]})]}),e(yt,{size:"sm",...a.register(t+"."+b+".security"),children:ys.map(K=>e("option",{value:K.value,children:K.title},K.value))})]}),r(A,{height:"66px",children:[e(X,{display:"flex",pb:1,alignItems:"center",gap:1,justifyContent:"space-between",m:"0",children:e("span",{children:c("hostsDialog.alpn")})}),e(yt,{size:"sm",...a.register(t+"."+b+".alpn"),children:Ss.map(K=>e("option",{value:K.value,children:K.title},K.value))})]}),r(A,{height:"66px",children:[e(X,{display:"flex",pb:1,alignItems:"center",gap:1,justifyContent:"space-between",m:"0",children:e("span",{children:c("hostsDialog.fingerprint")})}),e(yt,{size:"sm",...a.register(t+"."+b+".fingerprint"),children:Cs.map(K=>e("option",{value:K.value,children:K.title},K.value))})]})]},b)})]})})]},b)}),e(N,{variant:"outline",w:"full",size:"sm",color:"",fontWeight:"normal",onClick:C,children:c("hostsDialog.addHost")})]})})]})},Us=()=>{const{isEditingHosts:t,onEditingHosts:o,refetchUsers:n,inbounds:i}=v(),{isLoading:s,hosts:a,fetchHosts:l,isPostLoading:u,setHosts:p}=_s(),y=he(),{t:c}=O(),[d,C]=g.exports.useState({});g.exports.useEffect(()=>{t&&l()},[t]);const _=Oe({resolver:qe(Ds)});g.exports.useEffect(()=>{a&&t&&_.reset(a)},[a]);const b=()=>{C({}),o(!1)},S=m=>{p(m).then(()=>{y({title:c("hostsDialog.savedSuccess"),status:"success",isClosable:!0,position:"top",duration:3e3}),n()}).catch(f=>{var P,H,U,T,B;(((P=f==null?void 0:f.response)==null?void 0:P.status)===409||((H=f==null?void 0:f.response)==null?void 0:H.status)===400)&&y({title:(T=(U=f.response)==null?void 0:U._data)==null?void 0:T.detail,status:"error",isClosable:!0,position:"top",duration:3e3}),((B=f==null?void 0:f.response)==null?void 0:B.status)===422&&Object.keys(f.response._data.detail).forEach(G=>{y({title:f.response._data.detail[G]+" ("+G+")",status:"error",isClosable:!0,position:"top",duration:3e3})})})},R=m=>{d[String(m)]?delete d[String(m)]:d[String(m)]={},C({...d})};return r(re,{isOpen:t,onClose:b,children:[e(oe,{bg:"blackAlpha.300",backdropFilter:"blur(10px)"}),r(ne,{mx:"3",w:"fit-content",maxW:"3xl",children:[e(se,{pt:6,children:e(le,{color:"primary",children:e(Is,{color:"white"})})}),e(ie,{mt:3}),e(ae,{w:"440px",pb:3,pt:3,children:e(Er,{..._,children:r("form",{onSubmit:_.handleSubmit(S),children:[e(h,{mb:3,opacity:.8,fontSize:"sm",children:c("hostsDialog.title")}),s&&c("hostsDialog.loading"),!s&&a&&(Object.keys(a).length>0?e(Xe,{w:"full",allowToggle:!0,allowMultiple:!0,index:Object.keys(d).map(m=>parseInt(m)),children:e(M,{w:"full",children:Object.keys(a).map((m,f)=>e(zs,{toggleAccordion:()=>R(f),isOpen:d[String(f)],hostKey:m},m))})}):"No inbound found. Please check your Xray config file."),e(w,{justifyContent:"flex-end",py:2,children:e(N,{variant:"solid",mt:"2",type:"submit",colorScheme:"primary",size:"sm",px:5,isLoading:u,disabled:u,children:c("hostsDialog.apply")})})]})})})]})]})},Jr=k.object({name:k.string().min(1),address:k.string().min(1),port:k.number().min(1).or(k.string().transform(t=>parseFloat(t))),api_port:k.number().min(1).or(k.string().transform(t=>parseFloat(t))),xray_version:k.string().nullable().optional(),id:k.number().nullable().optional(),status:k.enum(["connected","connecting","error","disabled"]).nullable().optional(),message:k.string().nullable().optional(),add_as_new_host:k.boolean().optional()}),Es=()=>({name:"",address:"",port:62050,api_port:62051,xray_version:""}),Ye="fetch-nodes-query-key",Ls=()=>{const{isEditingNodes:t}=v();return zt({queryKey:Ye,queryFn:Ke.getState().fetchNodes,refetchInterval:t?3e3:void 0,refetchOnWindowFocus:!1})},Ke=ht((t,o)=>({nodes:[],addNode(n){return W("/node",{method:"POST",body:n})},fetchNodes(){return W("/nodes")},fetchNodesUsage(n){return W("/nodes/usage",{query:n})},updateNode(n){return W(`/node/${n.id}`,{method:"PUT",body:n})},setDeletingNode(n){t({deletingNode:n})},reconnectNode(n){return W(`/node/${n.id}/reconnect`,{method:"POST"})},deleteNode:()=>{var n;return W(`/node/${(n=o().deletingNode)==null?void 0:n.id}`,{method:"DELETE"})}})),At=(t,o,n)=>{if(t.response&&t.response._data){if(typeof t.response._data.detail=="string")return o({title:t.response._data.detail,status:"error",isClosable:!0,position:"top",duration:3e3});if(typeof t.response._data.detail=="object"&&n){Object.keys(t.response._data.detail).forEach(i=>n.setError(i,{message:t.response._data.detail[i]}));return}}return o({title:"Something went wrong!",status:"error",isClosable:!0,position:"top",duration:3e3})},Mt=(t,o)=>o({title:t,status:"success",isClosable:!0,position:"top",duration:3e3}),Rs=({deleteCallback:t})=>{const{deleteNode:o,deletingNode:n,setDeletingNode:i}=Ke(),{t:s}=O(),a=he(),l=Lt(),u=()=>{i(null)},{isLoading:p,mutate:y}=Ge(o,{onSuccess:()=>{Mt(s("deleteNode.deleteSuccess",{name:n&&n.name}),a),i(null),l.invalidateQueries(Ye),t&&t()},onError:c=>{At(c,a)}});return r(re,{isCentered:!0,isOpen:!!n,onClose:u,size:"sm",children:[e(oe,{bg:"blackAlpha.300",backdropFilter:"blur(10px)"}),r(ne,{mx:"3",children:[e(se,{pt:6,children:e(le,{color:"red",children:e(Je,{})})}),e(ie,{mt:3}),r(ae,{children:[e(h,{fontWeight:"semibold",fontSize:"lg",children:s("deleteNode.title")}),n&&e(h,{mt:1,fontSize:"sm",_dark:{color:"gray.400"},color:"gray.600",children:e(ge,{components:{b:e("b",{})},children:s("deleteNode.prompt",{name:n.name})})})]}),r(fe,{display:"flex",children:[e(N,{size:"sm",onClick:u,mr:3,w:"full",variant:"outline",children:s("cancel")}),e(N,{size:"sm",w:"full",colorScheme:"red",onClick:()=>y(),leftIcon:p?e(ke,{size:"xs"}):void 0,children:s("delete")})]})]})]})},et={baseStyle:{strokeWidth:"2px",w:4,h:4}},ar=x(Oo,et),Ts=x(jo,et),lr=x(Ho,et),cr=x(Lr,et),As=x(Lr,et),It=[{title:"No",value:"no_reset"},{title:"Daily",value:"day"},{title:"Weekly",value:"week"},{title:"Monthly",value:"month"},{title:"Annually",value:"year"}],Ve={active:{statusColor:"green",bandWidthColor:"primary",icon:ar},connected:{statusColor:"green",bandWidthColor:"primary",icon:ar},disabled:{statusColor:"gray",bandWidthColor:"gray",icon:Ts},expired:{statusColor:"orange",bandWidthColor:"orange",icon:cr},on_hold:{statusColor:"purple",bandWidthColor:"purple",icon:As},connecting:{statusColor:"orange",bandWidthColor:"orange",icon:cr},limited:{statusColor:"red",bandWidthColor:"red",icon:lr},error:{statusColor:"red",bandWidthColor:"red",icon:lr}},Nt=t=>{let o={status:"",time:""};if(t){j(t*1e3).utc().isAfter(j().utc())?o.status="expires":o.status="expired";const n=[],i=j.duration(j(t*1e3).utc().diff(j()));i.years()!=0&&n.push(Math.abs(i.years())+" year"+(Math.abs(i.years())!=1?"s":"")),i.months()!=0&&n.push(Math.abs(i.months())+" month"+(Math.abs(i.months())!=1?"s":"")),i.days()!=0&&n.push(Math.abs(i.days())+" day"+(Math.abs(i.days())!=1?"s":"")),n.length===0&&(i.hours()!=0&&n.push(Math.abs(i.hours())+" hour"+(Math.abs(i.hours())!=1?"s":"")),i.minutes()!=0&&n.push(Math.abs(i.minutes())+" min"+(Math.abs(i.minutes())!=1?"s":""))),o.time=n.join(", ")}return o},st=({expiryDate:t,status:o,compact:n=!1,showDetail:i=!0,extraText:s})=>{const{t:a}=O(),l=Nt(t),u=Ve[o].icon;return r(ue,{children:[r(E,{colorScheme:Ve[o].statusColor,rounded:"full",display:"inline-flex",px:3,py:1,columnGap:n?1:2,alignItems:"center",children:[e(u,{w:n?3:4}),i&&r(h,{textTransform:"capitalize",fontSize:n?".7rem":".875rem",lineHeight:n?"1rem":"1.25rem",fontWeight:"medium",letterSpacing:"tighter",children:[o,s&&`: ${s}`]})]}),i&&t&&e(h,{display:"inline-block",fontSize:"xs",fontWeight:"medium",ml:"2",color:"gray.600",_dark:{color:"gray.400"},children:a(l.status,{time:l.time})})]})},ot=x(Ce,{baseStyle:{bg:"white",_dark:{bg:"gray.700"}}}),Ms=x(zr,{baseStyle:{w:5,h:5}}),Ns=x(Bo,{baseStyle:{w:5,h:5,strokeWidth:2}}),Fs=({toggleAccordion:t,node:o})=>{const{updateNode:n,reconnectNode:i,setDeletingNode:s}=Ke(),{t:a}=O(),l=Lt(),u=he(),p=Oe({defaultValues:o,resolver:qe(Jr)}),y=s.bind(null,o),{isLoading:c,mutate:d}=Ge(n,{onSuccess:()=>{Mt("Node updated successfully",u),l.invalidateQueries(Ye)},onError:S=>{At(S,u,p)}}),{isLoading:C,mutate:_}=Ge(i.bind(null,o),{onSuccess:()=>{l.invalidateQueries(Ye)}}),b=C?"connecting":o.status?o.status:"error";return r(Fe,{border:"1px solid",_dark:{borderColor:"gray.600"},_light:{borderColor:"gray.200"},borderRadius:"4px",p:1,w:"full",children:[r(Pe,{px:2,borderRadius:"3px",onClick:t,children:[r(w,{w:"full",justifyContent:"space-between",pr:2,children:[e(h,{as:"span",fontWeight:"medium",fontSize:"sm",flex:"1",textAlign:"left",color:"gray.700",_dark:{color:"gray.300"},children:o.name}),r(w,{children:[o.xray_version&&e(E,{colorScheme:"blue",rounded:"full",display:"inline-flex",px:3,py:1,children:r(h,{textTransform:"capitalize",fontSize:"0.7rem",fontWeight:"medium",letterSpacing:"tighter",children:["Xray ",o.xray_version]})}),o.status&&e(st,{status:b,compact:!0})]})]}),e(kt,{})]}),r(We,{px:2,pb:2,children:[e(M,{pb:3,alignItems:"flex-start",children:b==="error"&&e(Ze,{status:"error",size:"xs",children:r(I,{children:[r(w,{w:"full",children:[e(ct,{w:4}),e(h,{marginInlineEnd:0,children:o.message})]}),e(w,{justifyContent:"flex-end",w:"full",children:e(N,{size:"sm","aria-label":"reconnect node",leftIcon:e(Zr,{}),onClick:()=>_(),disabled:C,children:a(C?"nodes.reconnecting":"nodes.reconnect")})})]})})}),e(Kr,{form:p,mutate:d,isLoading:c,submitBtnText:a("nodes.editNode"),btnLeftAdornment:e(te,{label:a("delete"),placement:"top",children:e($,{colorScheme:"red",variant:"ghost",size:"sm","aria-label":"delete node",onClick:y,children:e(Je,{})})})})]})]})},Ps=({toggleAccordion:t,resetAccordions:o})=>{const n=he(),{t:i}=O(),s=Lt(),{addNode:a}=Ke(),l=Oe({resolver:qe(Jr),defaultValues:{...Es(),add_as_new_host:!0}}),{isLoading:u,mutate:p}=Ge(a,{onSuccess:()=>{Mt(i("nodes.addNodeSuccess",{name:l.getValues("name")}),n),s.invalidateQueries(Ye),l.reset(),o()},onError:y=>{At(y,n,l)}});return r(Fe,{border:"1px solid",_dark:{borderColor:"gray.600"},_light:{borderColor:"gray.200"},borderRadius:"4px",p:1,w:"full",children:[e(Pe,{px:2,borderRadius:"3px",onClick:t,children:r(h,{as:"span",fontWeight:"medium",fontSize:"sm",flex:"1",textAlign:"left",color:"gray.700",_dark:{color:"gray.300"},display:"flex",gap:1,children:[e(Ns,{display:"inline-block"})," ",e("span",{children:i("nodes.addNewMarzbanNode")})]})}),e(We,{px:2,py:4,children:e(Kr,{form:l,mutate:p,isLoading:u,submitBtnText:i("nodes.addNode"),btnProps:{variant:"solid"},addAsHost:!0})})]})},Kr=({form:t,mutate:o,isLoading:n,submitBtnText:i,btnProps:s={},btnLeftAdornment:a,addAsHost:l=!1})=>{var _,b,S,R,m,f,P,H,U,T,B,G;const{t:u}=O(),[p,y]=g.exports.useState(!1),{data:c,isLoading:d}=zt({queryKey:"node-settings",queryFn:()=>W("/node/settings")});function C(D){if(document.body.createTextRange){const F=document.body.createTextRange();F.moveToElementText(D),F.select()}else if(window.getSelection){const F=window.getSelection(),Z=document.createRange();Z.selectNodeContents(D),F.removeAllRanges(),F.addRange(Z)}else console.warn("Could not select text in node: Unsupported browser.")}return e("form",{onSubmit:t.handleSubmit(D=>o(D)),children:r(M,{children:[c&&c.certificate&&e(Ze,{status:"info",alignItems:"start",children:r(Rr,{display:"flex",flexDirection:"column",overflow:"hidden",children:[e("span",{children:u("nodes.connection-hint")}),r(w,{justify:"end",py:2,children:[e(N,{as:"a",colorScheme:"primary",size:"xs",download:"ssl_client_cert.pem",href:URL.createObjectURL(new Blob([c.certificate],{type:"text/plain"})),children:u("nodes.download-certificate")}),e(te,{placement:"top",label:u("nodes.show-certificate"),children:e($,{"aria-label":u("nodes.show-certificate"),onClick:y.bind(null,!p),colorScheme:"whiteAlpha",color:"primary",size:"xs",children:p?e(Vo,{width:"15px"}):e($o,{width:"15px"})})})]}),e(Tr,{in:p,animateOpacity:!0,children:e(h,{bg:"rgba(255,255,255,.5)",_dark:{bg:"rgba(255,255,255,.2)"},rounded:"md",p:"2",lineHeight:"1.2",fontSize:"10px",fontFamily:"Courier",whiteSpace:"pre",overflow:"auto",onClick:D=>{C(D.target)},children:c.certificate})})]})}),r(w,{w:"full",children:[e(A,{children:e(ot,{label:u("nodes.nodeName"),size:"sm",placeholder:"Marzban-S2",...t.register("name"),error:(S=(b=(_=t.formState)==null?void 0:_.errors)==null?void 0:b.name)==null?void 0:S.message})}),e(w,{px:1,children:e(ye,{name:"status",control:t.control,render:({field:D})=>e(te,{placement:"top",label:`${u("usersTable.status")}: `+(D.value!=="disabled"?u("active"):u("disabled")),textTransform:"capitalize",children:e(I,{mt:"6",children:e(Ar,{colorScheme:"primary",isChecked:D.value!=="disabled",onChange:F=>{F.target.checked?D.onChange("connecting"):D.onChange("disabled")}})})},D.value)})})]}),r(w,{alignItems:"flex-start",children:[e(I,{w:"50%",children:e(ot,{label:u("nodes.nodeAddress"),size:"sm",placeholder:"51.20.12.13",...t.register("address"),error:(f=(m=(R=t.formState)==null?void 0:R.errors)==null?void 0:m.address)==null?void 0:f.message})}),e(I,{w:"25%",children:e(ot,{label:u("nodes.nodePort"),size:"sm",placeholder:"62050",...t.register("port"),error:(U=(H=(P=t.formState)==null?void 0:P.errors)==null?void 0:H.port)==null?void 0:U.message})}),e(I,{w:"25%",children:e(ot,{label:u("nodes.nodeAPIPort"),size:"sm",placeholder:"62051",...t.register("api_port"),error:(G=(B=(T=t.formState)==null?void 0:T.errors)==null?void 0:B.api_port)==null?void 0:G.message})})]}),l&&e(A,{py:1,children:e(Mr,{...t.register("add_as_new_host"),children:e(X,{m:0,children:u("nodes.addHostForEveryInbound")})})}),r(w,{w:"full",children:[a,e(N,{flexGrow:1,type:"submit",colorScheme:"primary",size:"sm",px:5,w:"full",isLoading:n,...s,children:i})]})]})})},Ws=()=>{const{isEditingNodes:t,onEditingNodes:o}=v(),{t:n}=O(),[i,s]=g.exports.useState({}),{data:a,isLoading:l}=Ls(),u=()=>{s({}),o(!1)},p=y=>{i[String(y)]?delete i[String(y)]:i[String(y)]={},s({...i})};return r(ue,{children:[r(re,{isOpen:t,onClose:u,children:[e(oe,{bg:"blackAlpha.300",backdropFilter:"blur(10px)"}),r(ne,{mx:"3",w:"fit-content",maxW:"3xl",children:[e(se,{pt:6,children:e(le,{color:"primary",children:e(Ms,{color:"white"})})}),e(ie,{mt:3}),r(ae,{w:"440px",pb:6,pt:3,children:[e(h,{mb:3,opacity:.8,fontSize:"sm",children:n("nodes.title")}),l&&"loading...",e(Xe,{w:"full",allowToggle:!0,index:Object.keys(i).map(y=>parseInt(y)),children:r(M,{w:"full",children:[!l&&a&&a.map((y,c)=>e(Fs,{toggleAccordion:()=>p(c),node:y},y.name)),e(Ps,{toggleAccordion:()=>p((a||[]).length),resetAccordions:()=>s({})})]})})]})]})]}),e(Rs,{deleteCallback:()=>s({})})]})};function Os(t){const o=360/t,n=90,i=47,s=[];for(let a=0;a(C<0&&(C+=1),C>1&&(C-=1),C<.16666666666666666?c+(d-c)*6*C:C<.5?d:C<.6666666666666666?c+(d-c)*(.6666666666666666-C)*6:c),p=n<.5?n*(1+o):n+o-n*o,y=2*n-p;i=Math.round(u(y,p,t+1/3)*255),s=Math.round(u(y,p,t)*255),a=Math.round(u(y,p,t-1/3)*255)}const l=u=>{const p=u.toString(16);return p.length===1?"0"+p:p};return`#${l(i)}${l(s)}${l(a)}`}const dr=({border:t,...o})=>{const{getInputProps:n,getRadioProps:i}=Jo(o),s=Se({base:"xs",md:"sm"});return r(I,{as:"label",children:[e("input",{...n()}),e(I,{...i(),minW:"48px",w:"full",h:"full",textAlign:"center",cursor:"pointer",fontSize:s,borderWidth:t?"1px":"0px",borderRadius:"md",_checked:{bg:"primary.500",color:"white",borderColor:"primary.500"},_focus:{boxShadow:"outline"},px:3,py:1,children:o.children})]})},eo=({onChange:t,defaultValue:o,...n})=>{const{t:i,i18n:s}=O();Qe();const a=Se({base:["7h","1d","3d","1w"],md:["7h","1d","3d","1w","1m","3m"]}),l={h:"hour",d:"day",w:"week",m:"month",y:"year"},u=Se({base:[{title:"hours",options:["1h","3h","6h","12h"]},{title:"days",options:["1d","2d","3d","4d"]},{title:"weeks",options:["1w","2w","3w","4w"]},{title:"months",options:["1m","2m","3m","6m"]}],md:[{title:"hours",options:["1h","2h","3h","6h","8h","12h"]},{title:"days",options:["1d","2d","3d","4d","5d","6d"]},{title:"weeks",options:["1w","2w","3w","4w"]},{title:"months",options:["1m","2m","3m","6m","8m"]}]}),{getRootProps:p,getRadioProps:y,setValue:c}=Go({name:"filter",defaultValue:o,onChange:L=>{if(L==="custom")return;_(),a.indexOf(L)>=0?(R(i("userDialog.custom")),f(!1)):(R(i("userDialog.custom")+` (${L})`),f(!0));const Y=Number(L.substring(0,L.length-1)),J=l[L[L.length-1]];t(L,{start:j().utc().subtract(Y,J).format("YYYY-MM-DDTHH:00:00")})}}),{isOpen:d,onOpen:C,onClose:_}=Zo(),b=g.exports.useRef(null);Yo({ref:b,handler:_});const[S,R]=g.exports.useState(i("userDialog.custom")),[m,f]=g.exports.useState(!1),[P,H]=g.exports.useState(0),U=Se({base:1,md:2}),T=Se({base:"xs",md:"sm"}),[B,G]=g.exports.useState(null),[D,F]=g.exports.useState(null),Z=L=>{const[Y,J]=L;D&&!J?(G(null),F(null)):(G(Y),F(J),Y&&J&&(_(),t("custom",{start:j(Y).format("YYYY-MM-DDT00:00:00"),end:j(J).format("YYYY-MM-DDT23:59:59")})))};return r(M,{...n,children:[P==0&&r(Rt,{...p(),gap:0,display:"flex",borderWidth:"1px",borderRadius:"md",minW:{base:"320px",md:"400px"},children:[a.map(L=>e(dr,{...y({value:L}),children:L},L)),e(I,{onClick:()=>{G(null),F(null),C()},cursor:"pointer",borderRadius:"md",w:"full",fontSize:T,px:3,py:1,bg:m?"primary.500":"unset",color:m?"white":"unset",borderColor:m?"primary.500":"unset",children:r(w,{children:[e(h,{children:S}),e(bt,{as:qt,boxSize:"18px"})]})})]}),P==1&&r(w,{onClick:C,cursor:"pointer",fontSize:T,borderRadius:"md",px:3,py:1,minW:{base:"320px",md:"400px"},borderWidth:"1px",children:[e(h,{w:"full",color:B?"unset":"gray.500",children:B?j(B).format("YYYY-MM-DD (00:00)"):i("userDialog.startDate")}),e(bt,{as:Nr,boxSize:"18px"}),e(h,{w:"full",color:D?"unset":"gray.500",children:D?j(D).format("YYYY-MM-DD (23:59)"):i("userDialog.endDate")}),e(bt,{as:qt,boxSize:"18px"})]}),e(M,{ref:b,marginTop:"40px !important",borderRadius:"md",borderWidth:"1px",position:"absolute",zIndex:"1",backgroundColor:"white",_dark:{backgroundColor:"gray.700"},display:d?"unset":"none",children:r(Qo,{onChange:L=>H(L),children:[r(qo,{children:[e(Xt,{fontSize:T,children:i("userDialog.relative")}),e(Xt,{fontSize:T,children:i("userDialog.absolute")})]}),r(Xo,{children:[e(Jt,{children:u.map(L=>e(M,{alignItems:"start",pl:2,pr:2,children:r(w,{justifyItems:"flex-start",mb:4,children:[e(h,{fontSize:T,minW:"60px",children:i("userDialog."+L.title)}),L.options.map(Y=>e(dr,{border:!0,...y({value:Y}),children:Y},Y+".custom"))]})},L.title))}),e(Jt,{className:"datepicker-panel",children:e(M,{children:e(Fr,{locale:s.language.toLocaleLowerCase(),selected:B,onChange:Z,startDate:B,endDate:D,selectsRange:!0,maxDate:new Date,monthsShown:U,peekNextMonth:!1,inline:!0})})})]})]})})]})};function ut(t,o,n=[],i=[]){const s=ee(n.reduce((a,l)=>a+=l,0));return{series:n,options:{labels:i,chart:{width:"100%",height:"100%",type:"donut",animations:{enabled:!1}},title:{text:`${o}${s}`,align:"center",style:{fontWeight:"var(--chakra-fontWeights-medium)",color:t==="dark"?"var(--chakra-colors-gray-300)":void 0}},legend:{position:"bottom",labels:{colors:t==="dark"?"#CBD5E0":void 0,useSeriesColors:!1}},stroke:{width:1,colors:void 0},dataLabels:{formatter:(a,{seriesIndex:l,w:u})=>ee(u.config.series[l],1)},tooltip:{custom:({series:a,seriesIndex:l,dataPointIndex:u,w:p})=>{const y=ee(a[l],1),c=Math.max(a.reduce((C,_)=>C+=_),1),d=Math.round(a[l]/c*1e3)/10+"%";return`
+import{i as Ct,B as to,a as ro,b as oo,j as yr,d as j,U as Dt,z as no,r as so,f as io,Q as ao,e as lo,$ as co,c as ht,g as x,h as uo,C as ho,k as pt,u as zt,l as O,m as r,H as w,n as e,T as h,o as po,p as I,s as mo,q as g,t as Qe,J as go,v as Sr,A as mt,w as fo,x as bo,M as re,y as oe,D as ne,E as se,F as ie,G as he,I as Oe,K as Cr,L as xo,N as Ge,O as ae,P as A,R as X,S as wr,V as te,W as E,X as ye,Y as $,Z as fe,_ as N,a0 as gt,a1 as He,a2 as yo,a3 as ge,a4 as ke,a5 as So,a6 as kr,a7 as _r,a8 as $e,a9 as it,aa as Co,ab as Ne,ac as at,ad as Zt,ae as wo,af as vr,ag as Ir,ah as Dr,ai as de,aj as ko,ak as _o,al as vo,am as Io,an as Do,ao as Ut,ap as zr,aq as Ur,ar as ue,as as Yt,at as zo,au as Uo,av as Eo,aw as wt,ax as Lo,ay as Ro,az as To,aA as Ao,aB as Mo,aC as No,aD as lt,aE as Fo,aF as we,aG as Po,aH as k,aI as qe,aJ as Er,aK as Xe,aL as M,aM as Et,aN as Wo,aO as Fe,aP as Pe,aQ as kt,aR as We,aS as ze,aT as Ue,aU as Ee,aV as Le,aW as Re,aX as Te,aY as Qt,aZ as Lt,a_ as Oo,a$ as jo,b0 as Ho,b1 as Lr,b2 as Bo,b3 as Ze,b4 as ct,b5 as Rr,b6 as $o,b7 as Vo,b8 as Tr,b9 as Ar,ba as Mr,bb as Se,bc as Go,bd as Zo,be as Yo,bf as Rt,bg as bt,bh as qt,bi as Nr,bj as Qo,bk as qo,bl as Xt,bm as Xo,bn as Jt,bo as Fr,bp as Jo,bq as Pr,br as Ko,bs as en,bt as Wr,bu as tn,bv as rn,bw as Or,bx as jr,by as Hr,bz as q,bA as on,bB as Br,bC as nn,bD as sn,bE as an,bF as ln,bG as cn,bH as dn,bI as un,bJ as $r,bK as hn,bL as Kt,bM as er,bN as Ae,bO as me,bP as tr,bQ as ce,bR as rr,bS as pn,bT as mn,bU as gn,bV as fn,bW as bn,bX as xn,bY as yn,bZ as Sn,b_ as Cn,b$ as wn,c0 as kn,c1 as _n,c2 as vn,c3 as In,c4 as Dn,c5 as zn,c6 as Un}from"./vendor.11357817.js";(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))i(s);new MutationObserver(s=>{for(const a of s)if(a.type==="childList")for(const l of a.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&i(l)}).observe(document,{childList:!0,subtree:!0});function n(s){const a={};return s.integrity&&(a.integrity=s.integrity),s.referrerpolicy&&(a.referrerPolicy=s.referrerpolicy),s.crossorigin==="use-credentials"?a.credentials="include":s.crossorigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function i(s){if(s.ep)return;s.ep=!0;const a=n(s);fetch(s.href,a)}})();Ct.use(to).use(ro).use(oo).init({debug:{}.NODE_ENV==="development",returnNull:!1,fallbackLng:"en",interpolation:{escapeValue:!1},react:{useSuspense:!1},load:"languageOnly",detection:{caches:["localStorage","sessionStorage","cookie"]},backend:{loadPath:yr(["/dashboard/","locales/{{lng}}.json"])}},function(t,o){j.locale(Ct.language)});Ct.on("languageChanged",t=>{j.locale(t)});Dt("zh-cn",no);Dt("ru",so);Dt("fa",io);const _t=new ao,Vr=t=>{const o=document.querySelector('meta[name="theme-color"]');o==null||o.setAttribute("content",t=="dark"?"#1A202C":"#3B81F6")},En=lo({shadows:{outline:"0 0 0 2px var(--chakra-colors-primary-200)"},fonts:{body:"Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif"},colors:{"light-border":"#d2d2d4",primary:{50:"#9cb7f2",100:"#88a9ef",200:"#749aec",300:"#618ce9",400:"#4d7de7",500:"#396fe4",600:"#3364cd",700:"#2e59b6",800:"#284ea0",900:"#224389"},gray:{750:"#222C3B"}},components:{Alert:{baseStyle:{container:{borderRadius:"6px",fontSize:"sm"}}},Select:{baseStyle:{field:{_dark:{borderColor:"gray.600",borderRadius:"6px"},_light:{borderRadius:"6px"}}}},FormHelperText:{baseStyle:{fontSize:"xs"}},FormLabel:{baseStyle:{fontSize:"sm",fontWeight:"medium",mb:"1",_dark:{color:"gray.300"}}},Input:{baseStyle:{addon:{_dark:{borderColor:"gray.600",_placeholder:{color:"gray.500"}}},field:{_focusVisible:{boxShadow:"none",borderColor:"primary.200",outlineColor:"primary.200"},_dark:{borderColor:"gray.600",_disabled:{color:"gray.400",borderColor:"gray.500"},_placeholder:{color:"gray.500"}}}}},Table:{baseStyle:{table:{borderCollapse:"separate",borderSpacing:0},thead:{borderBottomColor:"light-border"},th:{background:"#F9FAFB",borderColor:"light-border !important",borderBottomColor:"light-border !important",borderTop:"1px solid ",borderTopColor:"light-border !important",_first:{borderLeft:"1px solid",borderColor:"light-border !important"},_last:{borderRight:"1px solid",borderColor:"light-border !important"},_dark:{borderColor:"gray.600 !important",background:"gray.750"}},td:{transition:"all .1s ease-out",borderColor:"light-border",borderBottomColor:"light-border !important",_first:{borderLeft:"1px solid",borderColor:"light-border",_dark:{borderColor:"gray.600"}},_last:{borderRight:"1px solid",borderColor:"light-border",_dark:{borderColor:"gray.600"}},_dark:{borderColor:"gray.600",borderBottomColor:"gray.600 !important"}},tr:{"&.interactive":{cursor:"pointer",_hover:{"& > td":{bg:"gray.200"},_dark:{"& > td":{bg:"gray.750"}}}},_last:{"& > td":{_first:{borderBottomLeftRadius:"8px"},_last:{borderBottomRightRadius:"8px"}}}}}}}});const dt=()=>localStorage.getItem("token"),Ln=t=>{localStorage.setItem("token",t)},Rn=()=>{localStorage.removeItem("token")},Tn=co.create({baseURL:"/api/"}),An=(t,o={})=>(dt()&&(o.headers={...(o==null?void 0:o.headers)||{},Authorization:`Bearer ${dt()}`}),Tn(t,o)),W=An,Mn=ht(t=>({isLoading:!0,isPostLoading:!1,version:null,started:!1,logs_websocket:null,config:"",fetchCoreSettings:()=>{t({isLoading:!0}),Promise.all([W("/core").then(({version:o,started:n,logs_websocket:i})=>t({version:o,started:n,logs_websocket:i})),W("/core/config").then(o=>t({config:o}))]).finally(()=>t({isLoading:!1}))},updateConfig:o=>(t({isPostLoading:!0}),W("/core/config",{method:"PUT",body:o}).finally(()=>{t({isPostLoading:!1})})),restartCore:()=>W("/core/restart",{method:"POST"})}));function ee(t,o=2,n=!1){if(!+t)return"0 B";const i=1024,s=o<0?0:o,a=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],l=Math.floor(Math.log(t)/Math.log(i));return n?[parseFloat((t/Math.pow(i,l)).toFixed(s)),a[l]]:`${parseFloat((t/Math.pow(i,l)).toFixed(s))} ${a[l]}`}const or=t=>{if(t!==null)return t.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")},Nn=x(uo,{baseStyle:{w:5,h:5,position:"relative",zIndex:"2"}}),Fn=x(ho,{baseStyle:{w:5,h:5,position:"relative",zIndex:"2"}}),Pn=x(pt,{baseStyle:{w:5,h:5,position:"relative",zIndex:"2"}}),xt=({title:t,content:o,icon:n})=>r(po,{p:6,borderWidth:"1px",borderColor:"light-border",bg:"#F9FAFB",_dark:{borderColor:"gray.600",bg:"gray.750"},borderStyle:"solid",boxShadow:"none",borderRadius:"12px",width:"full",display:"flex",justifyContent:"space-between",flexDirection:"row",children:[r(w,{alignItems:"center",columnGap:"4",children:[e(I,{p:"2",position:"relative",color:"white",_before:{content:'""',position:"absolute",top:0,left:0,bg:"primary.400",display:"block",w:"full",h:"full",borderRadius:"5px",opacity:".5",z:"1"},_after:{content:'""',position:"absolute",top:"-5px",left:"-5px",bg:"primary.400",display:"block",w:"calc(100% + 10px)",h:"calc(100% + 10px)",borderRadius:"8px",opacity:".4",z:"1"},children:n}),e(h,{color:"gray.600",_dark:{color:"gray.300"},fontWeight:"medium",textTransform:"capitalize",fontSize:"sm",children:t})]}),e(I,{fontSize:"3xl",fontWeight:"semibold",mt:"2",children:o})]}),vt="statistics-query-key",Wn=t=>{const{version:o}=v(),{data:n}=zt({queryKey:vt,queryFn:()=>W("/system"),refetchInterval:5e3,onSuccess:({version:s})=>{o!==s&&v.setState({version:s})}}),{t:i}=O();return r(w,{justifyContent:"space-between",gap:0,columnGap:{lg:4,md:0},rowGap:{lg:0,base:4},display:"flex",flexDirection:{lg:"row",base:"column"},...t,children:[e(xt,{title:i("activeUsers"),content:n&&r(w,{alignItems:"flex-end",children:[e(h,{children:or(n.users_active)}),r(h,{fontWeight:"normal",fontSize:"lg",as:"span",display:"inline-block",pb:"5px",children:["/ ",or(n.total_user)]})]}),icon:e(Nn,{})}),e(xt,{title:i("dataUsage"),content:n&&ee(n.incoming_bandwidth+n.outgoing_bandwidth),icon:e(Fn,{})}),e(xt,{title:i("memoryUsage"),content:n&&r(w,{alignItems:"flex-end",children:[e(h,{children:ee(n.mem_used,1,!0)[0]}),r(h,{fontWeight:"normal",fontSize:"lg",as:"span",display:"inline-block",pb:"5px",children:[ee(n.mem_used,1,!0)[1]," /"," ",ee(n.mem_total,1)]})]}),icon:e(Pn,{})})]})},Gr="infinity-num-users-per-page",nr=10,On=()=>{const t=localStorage.getItem(Gr)||nr.toString();return parseInt(t)||nr},jn=t=>localStorage.setItem(Gr,t),Hn=t=>{for(const o in t)t[o]||delete t[o];return v.setState({loading:!0}),W("/users",{query:t}).then(o=>(v.setState({users:o}),o)).finally(()=>{v.setState({loading:!1})})},Bn=()=>W("/inbounds").then(t=>{v.setState({inbounds:new Map(Object.entries(t))})}).finally(()=>{v.setState({loading:!1})}),v=ht(mo((t,o)=>({version:null,editingUser:null,deletingUser:null,isCreatingNewUser:!1,QRcodeLinks:null,subscribeUrl:null,users:{users:[],total:0},loading:!0,isResetingAllUsage:!1,isEditingHosts:!1,isEditingNodes:!1,isShowingNodesUsage:!1,resetUsageUser:null,revokeSubscriptionUser:null,filters:{username:"",limit:On(),sort:"-created_at"},inbounds:new Map,isEditingCore:!1,refetchUsers:()=>{Hn(o().filters)},resetAllUsage:()=>W("/users/reset",{method:"POST"}).then(()=>{o().onResetAllUsage(!1),o().refetchUsers()}),onResetAllUsage:n=>t({isResetingAllUsage:n}),onCreateUser:n=>t({isCreatingNewUser:n}),onEditingUser:n=>{t({editingUser:n})},onDeletingUser:n=>{t({deletingUser:n})},onFilterChange:n=>{t({filters:{...o().filters,...n}}),o().refetchUsers()},setQRCode:n=>{t({QRcodeLinks:n})},deleteUser:n=>(t({editingUser:null}),W(`/user/${n.username}`,{method:"DELETE"}).then(()=>{t({deletingUser:null}),o().refetchUsers(),_t.invalidateQueries(vt)})),createUser:n=>W("/user",{method:"POST",body:n}).then(()=>{t({editingUser:null}),o().refetchUsers(),_t.invalidateQueries(vt)}),editUser:n=>W(`/user/${n.username}`,{method:"PUT",body:n}).then(()=>{o().onEditingUser(null),o().refetchUsers()}),fetchUserUsage:(n,i)=>{for(const s in i)i[s]||delete i[s];return W(`/user/${n.username}/usage`,{method:"GET",query:i})},onEditingHosts:n=>{t({isEditingHosts:n})},onEditingNodes:n=>{t({isEditingNodes:n})},onShowingNodesUsage:n=>{t({isShowingNodesUsage:n})},setSubLink:n=>{t({subscribeUrl:n})},resetDataUsage:n=>W(`/user/${n.username}/reset`,{method:"POST"}).then(()=>{t({resetUsageUser:null}),o().refetchUsers()}),revokeSubscription:n=>W(`/user/${n.username}/revoke_sub`,{method:"POST"}).then(i=>{t({revokeSubscriptionUser:null,editingUser:i}),o().refetchUsers()})}))),le=({children:t,color:o})=>e(I,{position:"relative",width:"36px",height:"36px",display:"flex",justifyContent:"center",alignItems:"center",_before:{content:'""',display:"block",position:"absolute",top:"0",left:"0",width:"calc(100%)",height:"calc(100%)",bg:`${o}.400`,opacity:".5",borderRadius:"5px",zIndex:"1",_dark:{bg:`${o}.400`}},_after:{content:'""',display:"block",position:"absolute",top:"0",left:"0",width:"calc(100% + 10px)",height:"calc(100% + 10px)",transform:"translate(-5px, -5px)",bg:`${o}.400`,opacity:".4",borderRadius:"8px",zIndex:"1",_dark:{bg:`${o}.400`}},children:e(h,{color:`${o}.500`,_dark:{color:`${o}.900`},position:"relative",zIndex:"2",children:t})});window.ace.define("ace/theme/nord_dark",["require","exports","module","ace/lib/dom"],(t,o,n)=>{o.isDark=!0,o.cssClass="ace-nord-dark",t("../lib/dom").importCssString(o.cssText,o.cssClass)});window.ace.define("ace/theme/dawn",["require","exports","module","ace/lib/dom"],(t,o,n)=>{o.isDark=!1,o.cssClass="ace-dawn",t("../lib/dom").importCssString(o.cssText,o.cssClass)});const $n=g.exports.forwardRef(({json:t,onChange:o,mode:n="code"},i)=>{const{colorMode:s}=Qe(),a={mode:n,onChangeText:o,statusBar:!1,mainMenuBar:!1,theme:s==="dark"?"ace/theme/nord_dark":"ace/theme/dawn"},l=g.exports.useRef(null),u=g.exports.useRef(null);return g.exports.useEffect(()=>(u.current=new go(l.current,a),()=>{u.current&&u.current.destroy()}),[]),g.exports.useEffect(()=>{u.current&&u.current.update(t)},[t]),e(I,{ref:i,border:"1px solid",borderColor:"gray.300",_dark:{borderColor:"gray.500"},borderRadius:5,h:"full",children:e(I,{height:"full",ref:l})})}),sr=500,Vn=x(Sr,{baseStyle:{w:5,h:5}}),Gn=x(mt,{baseStyle:{w:4,h:4}}),Zn=x(fo,{baseStyle:{w:4,h:4}}),Yn=x(bo,{baseStyle:{w:3,h:3}}),Qn=t=>({[He.ReadyState.CONNECTING]:"connecting",[He.ReadyState.OPEN]:"connected",[He.ReadyState.CLOSING]:"closed",[He.ReadyState.CLOSED]:"closed",[He.ReadyState.UNINSTANTIATED]:"closed"})[t],qn=()=>{try{let t=new URL("/api/".startsWith("/")?window.location.origin+"/api/":"/api/");return(t.protocol==="https:"?"wss://":"ws://")+yr([t.host+t.pathname,"/core/logs"])+"?interval=1&token="+dt()}catch(t){return console.error("Unable to generate websocket url"),console.error(t),null}};let xe=[];const Xn=()=>{const{isEditingCore:t}=v(),{fetchCoreSettings:o,updateConfig:n,isLoading:i,config:s,isPostLoading:a,version:l,restartCore:u}=Mn(),p=g.exports.useRef(null),[y,c]=g.exports.useState([]),{t:d}=O(),C=he(),_=Oe({defaultValues:{config:s||{}}});g.exports.useEffect(()=>{s&&_.setValue("config",s)},[s]),g.exports.useEffect(()=>{t&&o()},[t]);const b=g.exports.useRef(!0),S=g.exports.useCallback(Cr(D=>{var Z,L,Y;const F=Math.abs((((Z=p.current)==null?void 0:Z.scrollTop)||0)-(((L=p.current)==null?void 0:L.scrollHeight)||0)+(((Y=p.current)==null?void 0:Y.offsetHeight)||0))<10;p.current&&F?b.current=!0:b.current=!1,D.length<40&&c(D)},300),[]),{readyState:R}=xo(qn(),{onMessage:D=>{xe.push(D.data),xe.length>sr&&(xe=xe.splice(0,xe.length-sr)),S([...xe])},shouldReconnect:()=>!0,reconnectAttempts:10,reconnectInterval:1e3});g.exports.useEffect(()=>{var D;p.current&&b.current&&(p.current.scrollTop=(D=p.current)==null?void 0:D.scrollHeight)},[y]),g.exports.useEffect(()=>()=>{xe=[]},[]);const m=Qn(R.toString()),{mutate:f,isLoading:P}=Ge(u),H=({config:D})=>{n(D).then(()=>{C({title:d("core.successMessage"),status:"success",isClosable:!0,position:"top",duration:3e3})}).catch(F=>{let Z=d("core.generalErrorMessage");typeof F.response._data.detail=="object"&&(Z=F.response._data.detail[Object.keys(F.response._data.detail)[0]]),typeof F.response._data.detail=="string"&&(Z=F.response._data.detail),C({title:Z,status:"error",isClosable:!0,position:"top",duration:3e3})})},U=g.exports.useRef(null),[T,B]=g.exports.useState(!1),G=()=>{var D;document.fullscreenElement?(document.exitFullscreen(),B(!1)):((D=U.current)==null||D.requestFullscreen(),B(!0))};return r("form",{onSubmit:_.handleSubmit(H),children:[r(ae,{children:[r(A,{children:[r(w,{justifyContent:"space-between",alignItems:"flex-start",children:[r(X,{children:[d("core.configuration")," ",i&&e(wr,{isIndeterminate:!0,size:"15px"})]}),e(w,{gap:0,children:e(te,{label:"Xray Version",placement:"top",children:e(E,{height:"100%",textTransform:"lowercase",children:l&&`v${l}`})})})]}),r(I,{position:"relative",ref:U,minHeight:"300px",children:[e(ye,{control:_.control,name:"config",render:({field:D})=>e($n,{json:s,onChange:D.onChange})}),e($,{size:"xs","aria-label":"full screen",variant:"ghost",position:"absolute",top:"2",right:"4",onClick:G,children:T?e(Yn,{}):e(Zn,{})})]})]}),r(A,{mt:"4",children:[r(w,{justifyContent:"space-between",children:[e(X,{children:d("core.logs")}),e(h,{as:X,children:d(`core.socket.${m}`)})]}),e(I,{border:"1px solid",borderColor:"gray.300",bg:"#F9F9F9",_dark:{borderColor:"gray.500",bg:"#2e3440"},borderRadius:5,minHeight:"200px",maxHeight:"250px",p:2,overflowY:"auto",ref:p,children:y.map((D,F)=>e(h,{fontSize:"xs",opacity:.8,whiteSpace:"pre-line",children:D},F))})]})]}),e(fe,{children:r(w,{w:"full",justifyContent:"space-between",children:[e(I,{children:e(N,{size:"sm",leftIcon:e(Gn,{className:gt({"animate-spin":P})}),onClick:()=>f(),children:d(P?"core.restarting":"core.restartCore")})}),e(w,{children:e(N,{size:"sm",variant:"solid",colorScheme:"primary",px:"5",type:"submit",isDisabled:i||a,isLoading:a,children:d("core.save")})})]})})]})},Jn=()=>{const{isEditingCore:t}=v(),o=v.setState.bind(null,{isEditingCore:!1}),{t:n}=O();return r(re,{isOpen:t,onClose:o,size:"3xl",children:[e(oe,{bg:"blackAlpha.300",backdropFilter:"blur(10px)"}),r(ne,{mx:"3",w:"full",children:[e(se,{pt:6,children:r(w,{gap:2,children:[e(le,{color:"primary",children:e(Vn,{color:"white"})}),e(h,{fontWeight:"semibold",fontSize:"lg",children:n("core.title")})]})}),e(ie,{mt:3}),e(Xn,{})]})]})},Je=x(yo,{baseStyle:{w:5,h:5}}),Kn=()=>{const[t,o]=g.exports.useState(!1),{deletingUser:n,onDeletingUser:i,deleteUser:s}=v(),{t:a}=O(),l=he(),u=()=>{i(null)},p=()=>{n&&(o(!0),s(n).then(()=>{l({title:a("deleteUser.deleteSuccess",{username:n.username}),status:"success",isClosable:!0,position:"top",duration:3e3})}).then(u).finally(o.bind(null,!1)))};return r(re,{isCentered:!0,isOpen:!!n,onClose:u,size:"sm",children:[e(oe,{bg:"blackAlpha.300",backdropFilter:"blur(10px)"}),r(ne,{mx:"3",children:[e(se,{pt:6,children:e(le,{color:"red",children:e(Je,{})})}),e(ie,{mt:3}),r(ae,{children:[e(h,{fontWeight:"semibold",fontSize:"lg",children:a("deleteUser.title")}),n&&e(h,{mt:1,fontSize:"sm",_dark:{color:"gray.400"},color:"gray.600",children:e(ge,{components:{b:e("b",{})},children:a("deleteUser.prompt",{username:n.username})})})]}),r(fe,{display:"flex",children:[e(N,{size:"sm",onClick:u,mr:3,w:"full",variant:"outline",children:a("cancel")}),e(N,{size:"sm",w:"full",colorScheme:"red",onClick:p,leftIcon:t?e(ke,{size:"xs"}):void 0,children:a("delete")})]})]})]})},Tt={baseStyle:{w:4,h:4}},es=x(So,Tt),ts=x(kr,Tt),Zr=x(mt,Tt),rs=Cr(t=>{v.getState().onFilterChange({...v.getState().filters,offset:0,username:t})},300),os=({...t})=>{const{loading:o,filters:n,onFilterChange:i,refetchUsers:s,onCreateUser:a}=v(),{t:l}=O(),[u,p]=g.exports.useState(""),y=d=>{p(d.target.value),rs(d.target.value)},c=()=>{p(""),i({...n,offset:0,username:""})};return r(_r,{id:"filters",templateColumns:{lg:"repeat(3, 1fr)",md:"repeat(4, 1fr)",base:"repeat(1, 1fr)"},position:"sticky",top:0,mx:"-6",px:"6",rowGap:4,gap:{lg:4,base:0},bg:"var(--chakra-colors-chakra-body-bg)",py:4,zIndex:"docked",...t,children:[e($e,{colSpan:{base:1,md:2,lg:1},order:{base:2,md:1},children:r(it,{children:[e(Co,{pointerEvents:"none",children:e(es,{})}),e(Ne,{placeholder:l("search"),value:u,borderColor:"light-border",onChange:y}),r(at,{children:[o&&e(ke,{size:"xs"}),n.username&&n.username.length>0&&e($,{onClick:c,"aria-label":"clear",size:"xs",variant:"ghost",children:e(ts,{})})]})]})}),e($e,{colSpan:2,order:{base:1,md:2},children:r(w,{justifyContent:"flex-end",alignItems:"center",h:"full",children:[e($,{"aria-label":"refresh users",disabled:o,onClick:s,size:"sm",variant:"outline",children:e(Zr,{className:gt({"animate-spin":o})})}),e(N,{colorScheme:"primary",size:"sm",onClick:()=>a(!0),px:5,children:l("createUser")})]})})]})},Yr="https://github.com/Niraj-Dilshan/infinity",ns="https://github.com/Niraj-Dilshan",ss="https://github.com/Niraj-Dilshan/infinity#donation",Qr=t=>{const{version:o}=v();return e(w,{w:"full",py:"0",position:"relative",...t,children:r(h,{display:"inline-block",flexGrow:1,textAlign:"center",color:"gray.500",fontSize:"xs",children:[e(Zt,{color:"blue.400",href:Yr,children:"infinity"}),o?` (v${o}), `:", ","Made with \u2764\uFE0F in"," ",e(Zt,{color:"blue.400",href:ns,children:"Niraj-Dilshan"})]})})},is=x(wo,{baseStyle:{w:4,h:4}}),qr=({actions:t})=>{const{i18n:o}=O();var n=i=>{o.changeLanguage(i)};return r(vr,{placement:"bottom-end",children:[e(Ir,{as:$,size:"sm",variant:"outline",icon:e(is,{}),position:"relative"}),r(Dr,{minW:"100px",zIndex:9999,children:[e(de,{maxW:"100px",fontSize:"sm",onClick:()=>n("en"),children:"English"}),e(de,{maxW:"100px",fontSize:"sm",onClick:()=>n("fa"),children:"\u0641\u0627\u0631\u0633\u06CC"}),e(de,{maxW:"100px",fontSize:"sm",onClick:()=>n("zh-cn"),children:"\u7B80\u4F53\u4E2D\u6587"}),e(de,{maxW:"100px",fontSize:"sm",onClick:()=>n("ru"),children:"\u0420\u0443\u0441\u0441\u043A\u0438\u0439"})]})]})},pe={baseStyle:{w:4,h:4}},as=x(ko,pe),ls=x(_o,pe),cs=x(Sr,pe),ds=x(vo,pe),us=x(Io,pe),hs=x(Do,pe),ps=x(Ut,pe),ms=x(zr,pe),gs=x(pt,pe),fs=x(Ur,pe),ir=x(I,{baseStyle:{bg:"yellow.500",w:"2",h:"2",rounded:"full",position:"absolute"}}),Xr="infinity-menu-notification",bs=()=>{const t=localStorage.getItem(Xr);if(!t)return!0;try{return t&&Uo(parseInt(t))?Eo(new Date,new Date(parseInt(t)))>=7:!0}catch{return!0}},xs=({actions:t})=>{const{onEditingHosts:o,onResetAllUsage:n,onEditingNodes:i,onShowingNodesUsage:s}=v(),{t:a}=O(),{colorMode:l,toggleColorMode:u}=Qe(),[p,y]=g.exports.useState(bs()),c=l==="dark"?"dark_dimmed":l,d=()=>{localStorage.setItem(Xr,new Date().getTime().toString()),y(!1)};return r(w,{gap:2,justifyContent:"space-between",__css:{"& .menuList":{direction:"ltr"}},position:"relative",children:[e(h,{as:"h1",fontWeight:"semibold",fontSize:"2xl",children:a("users")}),p&&e(ir,{top:"0",right:"0",zIndex:9999}),e(I,{overflow:"auto",css:{direction:"rtl"},children:r(w,{alignItems:"center",children:[r(vr,{children:[e(Ir,{as:$,size:"sm",variant:"outline",icon:e(ue,{children:e(ds,{})}),position:"relative"}),r(Dr,{minW:"170px",zIndex:99999,className:"menuList",children:[e(de,{maxW:"170px",fontSize:"sm",icon:e(ps,{}),onClick:o.bind(null,!0),children:a("header.hostSettings")}),e(de,{maxW:"170px",fontSize:"sm",icon:e(ms,{}),onClick:i.bind(null,!0),children:a("header.nodeSettings")}),e(de,{maxW:"170px",fontSize:"sm",icon:e(gs,{}),onClick:s.bind(null,!0),children:a("header.nodesUsage")}),e(de,{maxW:"170px",fontSize:"sm",icon:e(fs,{}),onClick:n.bind(null,!0),children:a("resetAllUsage")}),e(Yt,{to:ss,target:"_blank",children:r(de,{maxW:"170px",fontSize:"sm",icon:e(hs,{}),position:"relative",onClick:d,children:[a("header.donation")," ",p&&e(ir,{top:"3",right:"2"})]})}),e(Yt,{to:"/login",children:e(de,{maxW:"170px",fontSize:"sm",icon:e(us,{}),children:a("header.logout")})})]})]}),e($,{size:"sm",variant:"outline","aria-label":"core settings",onClick:()=>{v.setState({isEditingCore:!0})},children:e(cs,{})}),e(qr,{}),e($,{size:"sm",variant:"outline","aria-label":"switch theme",onClick:()=>{Vr(l=="dark"?"light":"dark"),u()},children:l==="light"?e(as,{}):e(ls,{})}),e(I,{css:{direction:"ltr"},display:"flex",alignItems:"center",pr:"2",__css:{"& span":{display:"inline-flex"}},children:e(zo,{href:Yr,"data-color-scheme":`no-preference: ${c}; light: ${c}; dark: ${c};`,"data-size":"large","data-show-count":"true","aria-label":"Star infinity on GitHub",children:"Star"})})]})})]})},ys=[{title:"Inbound's default",value:"inbound_default"},{title:"TLS",value:"tls"},{title:"None",value:"none"}],Ss=[{title:"",value:""},{title:"h2",value:"h2"},{title:"http/1.1",value:"http/1.1"},{title:"h2, http/1.1",value:"h2,http/1.1"}],Cs=[{title:"",value:""},...["chrome","firefox","safari","ios","android","edge","360","qq","random","randomized"].map(t=>({title:t,value:t}))],ws=[{title:"none",value:""},{title:"xtls-rprx-vision",value:"xtls-rprx-vision"}],ks=["aes-128-gcm","aes-256-gcm","chacha20-ietf-poly1305"],_s=ht(t=>({isLoading:!1,isPostLoading:!1,hosts:{},fetchHosts:()=>{t({isLoading:!0}),W("/hosts").then(o=>t({hosts:o})).finally(()=>t({isLoading:!1}))},setHosts:o=>(t({isPostLoading:!0}),W("/hosts",{method:"PUT",body:o}).finally(()=>{t({isPostLoading:!1})}))}));const vs=x(kr,{baseStyle:{w:4,h:4}}),Ce=wt.forwardRef(({disabled:t,step:o,label:n,className:i,startAdornment:s,endAdornment:a,type:l="text",placeholder:u,onChange:p,onBlur:y,name:c,value:d,onClick:C,error:_,clearable:b=!1,...S},R)=>{const m=()=>{p&&p({target:{value:"",name:c}})},{size:f="md"}=S,P=l=="number"?Fo:Ne,H=l=="number"?Lo:wt.Fragment,U=l=="number"?{keepWithinRange:!0,precision:5,format:T=>isNaN(parseFloat(String(T)))||Number(parseFloat(String(T)).toFixed(5))===0?T:Number(parseFloat(String(T)).toFixed(5)),min:0,step:o,name:c,type:l,placeholder:u,onChange:T=>{p&&p(T)},onBlur:y,value:d,onClick:C,disabled:t,flexGrow:1,size:f}:{};return r(A,{isInvalid:!!_,children:[n&&e(X,{children:n}),r(it,{size:f,w:"full",rounded:"md",_focusWithin:{outline:"2px solid",outlineColor:"primary.200"},bg:t?"gray.100":"transparent",_dark:{bg:t?"gray.600":"transparent"},children:[s&&e(Ro,{children:s}),r(H,{...U,children:[e(P,{name:c,ref:R,step:o,className:gt(i),type:l,placeholder:u,onChange:p,onBlur:y,value:d,onClick:C,disabled:t,flexGrow:1,_focusVisible:{outline:"none",borderTopColor:"transparent",borderRightColor:"transparent",borderBottomColor:"transparent"},_disabled:{cursor:"not-allowed"},...S,roundedLeft:s?"0":"md",roundedRight:a?"0":"md"}),l=="number"&&e(ue,{children:r(To,{children:[e(Ao,{}),e(Mo,{})]})})]}),a&&e(No,{borderLeftRadius:0,borderRightRadius:"6px",bg:"transparent",children:a}),b&&d&&d.length&&e(at,{borderLeftRadius:0,borderRightRadius:"6px",bg:"transparent",onClick:m,cursor:"pointer",children:e(vs,{})})]}),!!_&&e(lt,{children:_})]})}),yt=x(we,{baseStyle:{bg:"white",_dark:{bg:"gray.700"}}}),Be=x(Ce,{baseStyle:{bg:"white",_dark:{bg:"gray.700"}}}),Is=x(Ut,{baseStyle:{w:5,h:5}}),Me=x(Po,{baseStyle:{w:4,h:4,color:"gray.400",cursor:"pointer"}}),Ds=k.record(k.string().min(1),k.array(k.object({remark:k.string().min(1,"Remark is required"),address:k.string().min(1,"Address is required"),port:k.string().or(k.number()).nullable().transform(t=>typeof t=="number"?t:t!==null&&!isNaN(parseInt(t))?Number(parseInt(t)):null),sni:k.string().nullable(),host:k.string().nullable(),security:k.string(),alpn:k.string(),fingerprint:k.string()}))),rt=x(lt,{baseStyle:{color:"red.400",display:"block",textAlign:"left",w:"100%"}}),zs=({hostKey:t,isOpen:o,toggleAccordion:n})=>{const{inbounds:i}=v(),s=[...i.values()].flat().filter(_=>_.tag===t)[0],a=Et(),{fields:l,append:u,remove:p}=Wo({control:a.control,name:t}),{errors:y}=a.formState,{t:c}=O(),d=y[t],C=()=>{u({host:"",sni:"",port:null,address:"",remark:"",security:"inbound_default",alpn:"",fingerprint:""})};return g.exports.useEffect(()=>{d&&!o&&n()},[d]),r(Fe,{border:"1px solid",_dark:{borderColor:"gray.600"},_light:{borderColor:"gray.200"},borderRadius:"4px",p:1,w:"full",children:[r(Pe,{px:2,borderRadius:"3px",onClick:n,children:[e(h,{as:"span",fontWeight:"medium",fontSize:"sm",flex:"1",textAlign:"left",color:"gray.700",_dark:{color:"gray.300"},children:t}),e(kt,{})]}),e(We,{px:2,pb:2,children:r(M,{gap:3,children:[l.map((_,b)=>{var S,R,m,f,P,H,U,T,B,G,D,F,Z,L,Y,J,tt;return r(M,{border:"1px solid",_dark:{borderColor:"gray.600",bg:"#273142"},_light:{borderColor:"gray.200",bg:"#fcfbfb"},p:2,w:"full",borderRadius:"4px",children:[e(w,{w:"100%",alignItems:"flex-start",children:r(A,{position:"relative",zIndex:10,isInvalid:!!(d&&((S=d[b])==null?void 0:S.remark)),children:[r(it,{children:[e(Be,{...a.register(t+"."+b+".remark"),size:"sm",borderRadius:"4px",placeholder:"Remark"}),e(at,{children:r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(I,{mt:"-8px",children:e(Me,{})})}),e(Ee,{children:r(Le,{children:[e(Re,{}),e(Te,{}),e(Qt,{children:r(I,{fontSize:"xs",children:[e(h,{pr:"20px",children:c("hostsDialog.desc")}),r(h,{children:[r(E,{children:["{","SERVER_IP","}"]})," ",c("hostsDialog.currentServer")]}),r(h,{mt:1,children:[r(E,{children:["{","USERNAME","}"]})," ",c("hostsDialog.username")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_USAGE","}"]})," ",c("hostsDialog.dataUsage")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_LEFT","}"]})," ",c("hostsDialog.remainingData")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_LIMIT","}"]})," ",c("hostsDialog.dataLimit")]}),r(h,{mt:1,children:[r(E,{children:["{","DAYS_LEFT","}"]})," ",c("hostsDialog.remainingDays")]}),r(h,{mt:1,children:[r(E,{children:["{","EXPIRE_DATE","}"]})," ",c("hostsDialog.expireDate")]}),r(h,{mt:1,children:[r(E,{children:["{","JALALI_EXPIRE_DATE","}"]})," ",c("hostsDialog.jalaliExpireDate")]}),r(h,{mt:1,children:[r(E,{children:["{","TIME_LEFT","}"]})," ",c("hostsDialog.remainingTime")]}),r(h,{mt:1,children:[r(E,{children:["{","STATUS_EMOJI","}"]})," ",c("hostsDialog.statusEmoji")]}),r(h,{mt:1,children:[r(E,{children:["{","PROTOCOL","}"]})," ",c("hostsDialog.proxyProtocol")]}),r(h,{mt:1,children:[r(E,{children:["{","TRANSPORT","}"]})," ",c("hostsDialog.proxyMethod")]})]})})]})})]})})]}),d&&((R=d[b])==null?void 0:R.remark)&&e(rt,{children:(f=(m=d[b])==null?void 0:m.remark)==null?void 0:f.message})]})}),r(A,{isInvalid:!!(d&&((P=d[b])==null?void 0:P.address)),children:[r(it,{children:[e(Be,{size:"sm",borderRadius:"4px",placeholder:"Address (e.g. example.com)",...a.register(t+"."+b+".address")}),e(at,{children:r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(I,{mt:"-8px",children:e(Me,{})})}),e(Ee,{children:r(Le,{children:[e(Re,{}),e(Te,{}),e(Qt,{children:r(I,{fontSize:"xs",children:[e(h,{pr:"20px",children:c("hostsDialog.desc")}),r(h,{children:[r(E,{children:["{","SERVER_IP","}"]})," ",c("hostsDialog.currentServer")]}),r(h,{mt:1,children:[r(E,{children:["{","USERNAME","}"]})," ",c("hostsDialog.username")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_USAGE","}"]})," ",c("hostsDialog.dataUsage")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_LEFT","}"]})," ",c("hostsDialog.remainingData")]}),r(h,{mt:1,children:[r(E,{children:["{","DATA_LIMIT","}"]})," ",c("hostsDialog.dataLimit")]}),r(h,{mt:1,children:[r(E,{children:["{","DAYS_LEFT","}"]})," ",c("hostsDialog.remainingDays")]}),r(h,{mt:1,children:[r(E,{children:["{","EXPIRE_DATE","}"]})," ",c("hostsDialog.expireDate")]}),r(h,{mt:1,children:[r(E,{children:["{","JALALI_EXPIRE_DATE","}"]})," ",c("hostsDialog.jalaliExpireDate")]}),r(h,{mt:1,children:[r(E,{children:["{","TIME_LEFT","}"]})," ",c("hostsDialog.remainingTime")]}),r(h,{mt:1,children:[r(E,{children:["{","STATUS_EMOJI","}"]})," ",c("hostsDialog.statusEmoji")]}),r(h,{mt:1,children:[r(E,{children:["{","PROTOCOL","}"]})," ",c("hostsDialog.proxyProtocol")]}),r(h,{mt:1,children:[r(E,{children:["{","TRANSPORT","}"]})," ",c("hostsDialog.proxyMethod")]})]})})]})})]})})]}),d&&((H=d[b])==null?void 0:H.address)&&e(rt,{children:(T=(U=d[b])==null?void 0:U.address)==null?void 0:T.message})]}),e(Xe,{w:"full",allowToggle:!0,children:r(Fe,{border:"0",children:[r(Pe,{display:"flex",justifyContent:"space-between",px:0,py:1,borderRadius:3,_hover:{bg:"transparent"},children:[r(h,{fontSize:"xs",color:"gray.600",_dark:{color:"gray.500"},pl:1,children:[c("hostsDialog.advancedOptions"),e(kt,{fontSize:"sm",ml:1})]}),e(te,{label:"Delete",placement:"top",children:e($,{"aria-label":"Delete",size:"sm",colorScheme:"red",variant:"ghost",onClick:p.bind(null,b),children:e(Je,{})})})]}),e(We,{w:"full",p:1,children:r(M,{w:"full",borderRadius:"4px",children:[r(A,{isInvalid:!!(d&&((B=d[b])==null?void 0:B.port)),children:[r(X,{display:"flex",pb:1,alignItems:"center",justifyContent:"space-between",gap:1,m:"0",children:[e("span",{children:c("hostsDialog.port")}),r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(Me,{})}),e(Ee,{children:r(Le,{p:2,children:[e(Re,{}),e(Te,{}),e(h,{fontSize:"xs",pr:5,children:c("hostsDialog.port.info")})]})})]})]}),e(Be,{size:"sm",borderRadius:"4px",placeholder:String(s.port||"8080"),type:"number",...a.register(t+"."+b+".port")})]}),r(A,{isInvalid:!!(d&&((G=d[b])==null?void 0:G.sni)),children:[r(X,{display:"flex",pb:1,alignItems:"center",gap:1,justifyContent:"space-between",m:"0",children:[e("span",{children:c("hostsDialog.sni")}),r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(Me,{})}),e(Ee,{children:r(Le,{p:2,children:[e(Re,{}),e(Te,{}),e(h,{fontSize:"xs",pr:5,children:c("hostsDialog.sni.info")}),e(h,{fontSize:"xs",mt:"2",children:e(ge,{i18nKey:"hostsDialog.host.wildcard",components:{badge:e(E,{})}})}),e(h,{fontSize:"xs",children:e(ge,{i18nKey:"hostsDialog.host.multiHost",components:{badge:e(E,{})}})})]})})]})]}),e(Be,{size:"sm",borderRadius:"4px",placeholder:"SNI (e.g. example.com)",...a.register(t+"."+b+".sni")}),d&&((D=d[b])==null?void 0:D.sni)&&e(rt,{children:(Z=(F=d[b])==null?void 0:F.sni)==null?void 0:Z.message})]}),r(A,{isInvalid:!!(d&&((L=d[b])==null?void 0:L.host)),children:[r(X,{display:"flex",pb:1,alignItems:"center",gap:1,justifyContent:"space-between",m:"0",children:[e("span",{children:c("hostsDialog.host")}),r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(Me,{})}),e(Ee,{children:r(Le,{p:2,children:[e(Re,{}),e(Te,{}),e(h,{fontSize:"xs",pr:5,children:c("hostsDialog.host.info")}),e(h,{fontSize:"xs",mt:"2",children:e(ge,{i18nKey:"hostsDialog.host.wildcard",components:{badge:e(E,{})}})}),e(h,{fontSize:"xs",children:e(ge,{i18nKey:"hostsDialog.host.multiHost",components:{badge:e(E,{})}})})]})})]})]}),e(Be,{size:"sm",borderRadius:"4px",placeholder:"Host (e.g. example.com)",...a.register(t+"."+b+".host")}),d&&((Y=d[b])==null?void 0:Y.host)&&e(rt,{children:(tt=(J=d[b])==null?void 0:J.host)==null?void 0:tt.message})]}),r(A,{height:"66px",children:[r(X,{display:"flex",pb:1,alignItems:"center",gap:1,justifyContent:"space-between",m:"0",children:[e("span",{children:c("hostsDialog.security")}),r(ze,{isLazy:!0,placement:"right",children:[e(Ue,{children:e(Me,{})}),e(Ee,{children:r(Le,{p:2,children:[e(Re,{}),e(Te,{}),e(h,{fontSize:"xs",pr:5,children:c("hostsDialog.security.info")})]})})]})]}),e(yt,{size:"sm",...a.register(t+"."+b+".security"),children:ys.map(K=>e("option",{value:K.value,children:K.title},K.value))})]}),r(A,{height:"66px",children:[e(X,{display:"flex",pb:1,alignItems:"center",gap:1,justifyContent:"space-between",m:"0",children:e("span",{children:c("hostsDialog.alpn")})}),e(yt,{size:"sm",...a.register(t+"."+b+".alpn"),children:Ss.map(K=>e("option",{value:K.value,children:K.title},K.value))})]}),r(A,{height:"66px",children:[e(X,{display:"flex",pb:1,alignItems:"center",gap:1,justifyContent:"space-between",m:"0",children:e("span",{children:c("hostsDialog.fingerprint")})}),e(yt,{size:"sm",...a.register(t+"."+b+".fingerprint"),children:Cs.map(K=>e("option",{value:K.value,children:K.title},K.value))})]})]},b)})]})})]},b)}),e(N,{variant:"outline",w:"full",size:"sm",color:"",fontWeight:"normal",onClick:C,children:c("hostsDialog.addHost")})]})})]})},Us=()=>{const{isEditingHosts:t,onEditingHosts:o,refetchUsers:n,inbounds:i}=v(),{isLoading:s,hosts:a,fetchHosts:l,isPostLoading:u,setHosts:p}=_s(),y=he(),{t:c}=O(),[d,C]=g.exports.useState({});g.exports.useEffect(()=>{t&&l()},[t]);const _=Oe({resolver:qe(Ds)});g.exports.useEffect(()=>{a&&t&&_.reset(a)},[a]);const b=()=>{C({}),o(!1)},S=m=>{p(m).then(()=>{y({title:c("hostsDialog.savedSuccess"),status:"success",isClosable:!0,position:"top",duration:3e3}),n()}).catch(f=>{var P,H,U,T,B;(((P=f==null?void 0:f.response)==null?void 0:P.status)===409||((H=f==null?void 0:f.response)==null?void 0:H.status)===400)&&y({title:(T=(U=f.response)==null?void 0:U._data)==null?void 0:T.detail,status:"error",isClosable:!0,position:"top",duration:3e3}),((B=f==null?void 0:f.response)==null?void 0:B.status)===422&&Object.keys(f.response._data.detail).forEach(G=>{y({title:f.response._data.detail[G]+" ("+G+")",status:"error",isClosable:!0,position:"top",duration:3e3})})})},R=m=>{d[String(m)]?delete d[String(m)]:d[String(m)]={},C({...d})};return r(re,{isOpen:t,onClose:b,children:[e(oe,{bg:"blackAlpha.300",backdropFilter:"blur(10px)"}),r(ne,{mx:"3",w:"fit-content",maxW:"3xl",children:[e(se,{pt:6,children:e(le,{color:"primary",children:e(Is,{color:"white"})})}),e(ie,{mt:3}),e(ae,{w:"440px",pb:3,pt:3,children:e(Er,{..._,children:r("form",{onSubmit:_.handleSubmit(S),children:[e(h,{mb:3,opacity:.8,fontSize:"sm",children:c("hostsDialog.title")}),s&&c("hostsDialog.loading"),!s&&a&&(Object.keys(a).length>0?e(Xe,{w:"full",allowToggle:!0,allowMultiple:!0,index:Object.keys(d).map(m=>parseInt(m)),children:e(M,{w:"full",children:Object.keys(a).map((m,f)=>e(zs,{toggleAccordion:()=>R(f),isOpen:d[String(f)],hostKey:m},m))})}):"No inbound found. Please check your Xray config file."),e(w,{justifyContent:"flex-end",py:2,children:e(N,{variant:"solid",mt:"2",type:"submit",colorScheme:"primary",size:"sm",px:5,isLoading:u,disabled:u,children:c("hostsDialog.apply")})})]})})})]})]})},Jr=k.object({name:k.string().min(1),address:k.string().min(1),port:k.number().min(1).or(k.string().transform(t=>parseFloat(t))),api_port:k.number().min(1).or(k.string().transform(t=>parseFloat(t))),xray_version:k.string().nullable().optional(),id:k.number().nullable().optional(),status:k.enum(["connected","connecting","error","disabled"]).nullable().optional(),message:k.string().nullable().optional(),add_as_new_host:k.boolean().optional()}),Es=()=>({name:"",address:"",port:62050,api_port:62051,xray_version:""}),Ye="fetch-nodes-query-key",Ls=()=>{const{isEditingNodes:t}=v();return zt({queryKey:Ye,queryFn:Ke.getState().fetchNodes,refetchInterval:t?3e3:void 0,refetchOnWindowFocus:!1})},Ke=ht((t,o)=>({nodes:[],addNode(n){return W("/node",{method:"POST",body:n})},fetchNodes(){return W("/nodes")},fetchNodesUsage(n){return W("/nodes/usage",{query:n})},updateNode(n){return W(`/node/${n.id}`,{method:"PUT",body:n})},setDeletingNode(n){t({deletingNode:n})},reconnectNode(n){return W(`/node/${n.id}/reconnect`,{method:"POST"})},deleteNode:()=>{var n;return W(`/node/${(n=o().deletingNode)==null?void 0:n.id}`,{method:"DELETE"})}})),At=(t,o,n)=>{if(t.response&&t.response._data){if(typeof t.response._data.detail=="string")return o({title:t.response._data.detail,status:"error",isClosable:!0,position:"top",duration:3e3});if(typeof t.response._data.detail=="object"&&n){Object.keys(t.response._data.detail).forEach(i=>n.setError(i,{message:t.response._data.detail[i]}));return}}return o({title:"Something went wrong!",status:"error",isClosable:!0,position:"top",duration:3e3})},Mt=(t,o)=>o({title:t,status:"success",isClosable:!0,position:"top",duration:3e3}),Rs=({deleteCallback:t})=>{const{deleteNode:o,deletingNode:n,setDeletingNode:i}=Ke(),{t:s}=O(),a=he(),l=Lt(),u=()=>{i(null)},{isLoading:p,mutate:y}=Ge(o,{onSuccess:()=>{Mt(s("deleteNode.deleteSuccess",{name:n&&n.name}),a),i(null),l.invalidateQueries(Ye),t&&t()},onError:c=>{At(c,a)}});return r(re,{isCentered:!0,isOpen:!!n,onClose:u,size:"sm",children:[e(oe,{bg:"blackAlpha.300",backdropFilter:"blur(10px)"}),r(ne,{mx:"3",children:[e(se,{pt:6,children:e(le,{color:"red",children:e(Je,{})})}),e(ie,{mt:3}),r(ae,{children:[e(h,{fontWeight:"semibold",fontSize:"lg",children:s("deleteNode.title")}),n&&e(h,{mt:1,fontSize:"sm",_dark:{color:"gray.400"},color:"gray.600",children:e(ge,{components:{b:e("b",{})},children:s("deleteNode.prompt",{name:n.name})})})]}),r(fe,{display:"flex",children:[e(N,{size:"sm",onClick:u,mr:3,w:"full",variant:"outline",children:s("cancel")}),e(N,{size:"sm",w:"full",colorScheme:"red",onClick:()=>y(),leftIcon:p?e(ke,{size:"xs"}):void 0,children:s("delete")})]})]})]})},et={baseStyle:{strokeWidth:"2px",w:4,h:4}},ar=x(Oo,et),Ts=x(jo,et),lr=x(Ho,et),cr=x(Lr,et),As=x(Lr,et),It=[{title:"No",value:"no_reset"},{title:"Daily",value:"day"},{title:"Weekly",value:"week"},{title:"Monthly",value:"month"},{title:"Annually",value:"year"}],Ve={active:{statusColor:"green",bandWidthColor:"primary",icon:ar},connected:{statusColor:"green",bandWidthColor:"primary",icon:ar},disabled:{statusColor:"gray",bandWidthColor:"gray",icon:Ts},expired:{statusColor:"orange",bandWidthColor:"orange",icon:cr},on_hold:{statusColor:"purple",bandWidthColor:"purple",icon:As},connecting:{statusColor:"orange",bandWidthColor:"orange",icon:cr},limited:{statusColor:"red",bandWidthColor:"red",icon:lr},error:{statusColor:"red",bandWidthColor:"red",icon:lr}},Nt=t=>{let o={status:"",time:""};if(t){j(t*1e3).utc().isAfter(j().utc())?o.status="expires":o.status="expired";const n=[],i=j.duration(j(t*1e3).utc().diff(j()));i.years()!=0&&n.push(Math.abs(i.years())+" year"+(Math.abs(i.years())!=1?"s":"")),i.months()!=0&&n.push(Math.abs(i.months())+" month"+(Math.abs(i.months())!=1?"s":"")),i.days()!=0&&n.push(Math.abs(i.days())+" day"+(Math.abs(i.days())!=1?"s":"")),n.length===0&&(i.hours()!=0&&n.push(Math.abs(i.hours())+" hour"+(Math.abs(i.hours())!=1?"s":"")),i.minutes()!=0&&n.push(Math.abs(i.minutes())+" min"+(Math.abs(i.minutes())!=1?"s":""))),o.time=n.join(", ")}return o},st=({expiryDate:t,status:o,compact:n=!1,showDetail:i=!0,extraText:s})=>{const{t:a}=O(),l=Nt(t),u=Ve[o].icon;return r(ue,{children:[r(E,{colorScheme:Ve[o].statusColor,rounded:"full",display:"inline-flex",px:3,py:1,columnGap:n?1:2,alignItems:"center",children:[e(u,{w:n?3:4}),i&&r(h,{textTransform:"capitalize",fontSize:n?".7rem":".875rem",lineHeight:n?"1rem":"1.25rem",fontWeight:"medium",letterSpacing:"tighter",children:[o,s&&`: ${s}`]})]}),i&&t&&e(h,{display:"inline-block",fontSize:"xs",fontWeight:"medium",ml:"2",color:"gray.600",_dark:{color:"gray.400"},children:a(l.status,{time:l.time})})]})},ot=x(Ce,{baseStyle:{bg:"white",_dark:{bg:"gray.700"}}}),Ms=x(zr,{baseStyle:{w:5,h:5}}),Ns=x(Bo,{baseStyle:{w:5,h:5,strokeWidth:2}}),Fs=({toggleAccordion:t,node:o})=>{const{updateNode:n,reconnectNode:i,setDeletingNode:s}=Ke(),{t:a}=O(),l=Lt(),u=he(),p=Oe({defaultValues:o,resolver:qe(Jr)}),y=s.bind(null,o),{isLoading:c,mutate:d}=Ge(n,{onSuccess:()=>{Mt("Node updated successfully",u),l.invalidateQueries(Ye)},onError:S=>{At(S,u,p)}}),{isLoading:C,mutate:_}=Ge(i.bind(null,o),{onSuccess:()=>{l.invalidateQueries(Ye)}}),b=C?"connecting":o.status?o.status:"error";return r(Fe,{border:"1px solid",_dark:{borderColor:"gray.600"},_light:{borderColor:"gray.200"},borderRadius:"4px",p:1,w:"full",children:[r(Pe,{px:2,borderRadius:"3px",onClick:t,children:[r(w,{w:"full",justifyContent:"space-between",pr:2,children:[e(h,{as:"span",fontWeight:"medium",fontSize:"sm",flex:"1",textAlign:"left",color:"gray.700",_dark:{color:"gray.300"},children:o.name}),r(w,{children:[o.xray_version&&e(E,{colorScheme:"blue",rounded:"full",display:"inline-flex",px:3,py:1,children:r(h,{textTransform:"capitalize",fontSize:"0.7rem",fontWeight:"medium",letterSpacing:"tighter",children:["Xray ",o.xray_version]})}),o.status&&e(st,{status:b,compact:!0})]})]}),e(kt,{})]}),r(We,{px:2,pb:2,children:[e(M,{pb:3,alignItems:"flex-start",children:b==="error"&&e(Ze,{status:"error",size:"xs",children:r(I,{children:[r(w,{w:"full",children:[e(ct,{w:4}),e(h,{marginInlineEnd:0,children:o.message})]}),e(w,{justifyContent:"flex-end",w:"full",children:e(N,{size:"sm","aria-label":"reconnect node",leftIcon:e(Zr,{}),onClick:()=>_(),disabled:C,children:a(C?"nodes.reconnecting":"nodes.reconnect")})})]})})}),e(Kr,{form:p,mutate:d,isLoading:c,submitBtnText:a("nodes.editNode"),btnLeftAdornment:e(te,{label:a("delete"),placement:"top",children:e($,{colorScheme:"red",variant:"ghost",size:"sm","aria-label":"delete node",onClick:y,children:e(Je,{})})})})]})]})},Ps=({toggleAccordion:t,resetAccordions:o})=>{const n=he(),{t:i}=O(),s=Lt(),{addNode:a}=Ke(),l=Oe({resolver:qe(Jr),defaultValues:{...Es(),add_as_new_host:!0}}),{isLoading:u,mutate:p}=Ge(a,{onSuccess:()=>{Mt(i("nodes.addNodeSuccess",{name:l.getValues("name")}),n),s.invalidateQueries(Ye),l.reset(),o()},onError:y=>{At(y,n,l)}});return r(Fe,{border:"1px solid",_dark:{borderColor:"gray.600"},_light:{borderColor:"gray.200"},borderRadius:"4px",p:1,w:"full",children:[e(Pe,{px:2,borderRadius:"3px",onClick:t,children:r(h,{as:"span",fontWeight:"medium",fontSize:"sm",flex:"1",textAlign:"left",color:"gray.700",_dark:{color:"gray.300"},display:"flex",gap:1,children:[e(Ns,{display:"inline-block"})," ",e("span",{children:i("nodes.addNewinfinityNode")})]})}),e(We,{px:2,py:4,children:e(Kr,{form:l,mutate:p,isLoading:u,submitBtnText:i("nodes.addNode"),btnProps:{variant:"solid"},addAsHost:!0})})]})},Kr=({form:t,mutate:o,isLoading:n,submitBtnText:i,btnProps:s={},btnLeftAdornment:a,addAsHost:l=!1})=>{var _,b,S,R,m,f,P,H,U,T,B,G;const{t:u}=O(),[p,y]=g.exports.useState(!1),{data:c,isLoading:d}=zt({queryKey:"node-settings",queryFn:()=>W("/node/settings")});function C(D){if(document.body.createTextRange){const F=document.body.createTextRange();F.moveToElementText(D),F.select()}else if(window.getSelection){const F=window.getSelection(),Z=document.createRange();Z.selectNodeContents(D),F.removeAllRanges(),F.addRange(Z)}else console.warn("Could not select text in node: Unsupported browser.")}return e("form",{onSubmit:t.handleSubmit(D=>o(D)),children:r(M,{children:[c&&c.certificate&&e(Ze,{status:"info",alignItems:"start",children:r(Rr,{display:"flex",flexDirection:"column",overflow:"hidden",children:[e("span",{children:u("nodes.connection-hint")}),r(w,{justify:"end",py:2,children:[e(N,{as:"a",colorScheme:"primary",size:"xs",download:"ssl_client_cert.pem",href:URL.createObjectURL(new Blob([c.certificate],{type:"text/plain"})),children:u("nodes.download-certificate")}),e(te,{placement:"top",label:u("nodes.show-certificate"),children:e($,{"aria-label":u("nodes.show-certificate"),onClick:y.bind(null,!p),colorScheme:"whiteAlpha",color:"primary",size:"xs",children:p?e(Vo,{width:"15px"}):e($o,{width:"15px"})})})]}),e(Tr,{in:p,animateOpacity:!0,children:e(h,{bg:"rgba(255,255,255,.5)",_dark:{bg:"rgba(255,255,255,.2)"},rounded:"md",p:"2",lineHeight:"1.2",fontSize:"10px",fontFamily:"Courier",whiteSpace:"pre",overflow:"auto",onClick:D=>{C(D.target)},children:c.certificate})})]})}),r(w,{w:"full",children:[e(A,{children:e(ot,{label:u("nodes.nodeName"),size:"sm",placeholder:"infinity-S2",...t.register("name"),error:(S=(b=(_=t.formState)==null?void 0:_.errors)==null?void 0:b.name)==null?void 0:S.message})}),e(w,{px:1,children:e(ye,{name:"status",control:t.control,render:({field:D})=>e(te,{placement:"top",label:`${u("usersTable.status")}: `+(D.value!=="disabled"?u("active"):u("disabled")),textTransform:"capitalize",children:e(I,{mt:"6",children:e(Ar,{colorScheme:"primary",isChecked:D.value!=="disabled",onChange:F=>{F.target.checked?D.onChange("connecting"):D.onChange("disabled")}})})},D.value)})})]}),r(w,{alignItems:"flex-start",children:[e(I,{w:"50%",children:e(ot,{label:u("nodes.nodeAddress"),size:"sm",placeholder:"51.20.12.13",...t.register("address"),error:(f=(m=(R=t.formState)==null?void 0:R.errors)==null?void 0:m.address)==null?void 0:f.message})}),e(I,{w:"25%",children:e(ot,{label:u("nodes.nodePort"),size:"sm",placeholder:"62050",...t.register("port"),error:(U=(H=(P=t.formState)==null?void 0:P.errors)==null?void 0:H.port)==null?void 0:U.message})}),e(I,{w:"25%",children:e(ot,{label:u("nodes.nodeAPIPort"),size:"sm",placeholder:"62051",...t.register("api_port"),error:(G=(B=(T=t.formState)==null?void 0:T.errors)==null?void 0:B.api_port)==null?void 0:G.message})})]}),l&&e(A,{py:1,children:e(Mr,{...t.register("add_as_new_host"),children:e(X,{m:0,children:u("nodes.addHostForEveryInbound")})})}),r(w,{w:"full",children:[a,e(N,{flexGrow:1,type:"submit",colorScheme:"primary",size:"sm",px:5,w:"full",isLoading:n,...s,children:i})]})]})})},Ws=()=>{const{isEditingNodes:t,onEditingNodes:o}=v(),{t:n}=O(),[i,s]=g.exports.useState({}),{data:a,isLoading:l}=Ls(),u=()=>{s({}),o(!1)},p=y=>{i[String(y)]?delete i[String(y)]:i[String(y)]={},s({...i})};return r(ue,{children:[r(re,{isOpen:t,onClose:u,children:[e(oe,{bg:"blackAlpha.300",backdropFilter:"blur(10px)"}),r(ne,{mx:"3",w:"fit-content",maxW:"3xl",children:[e(se,{pt:6,children:e(le,{color:"primary",children:e(Ms,{color:"white"})})}),e(ie,{mt:3}),r(ae,{w:"440px",pb:6,pt:3,children:[e(h,{mb:3,opacity:.8,fontSize:"sm",children:n("nodes.title")}),l&&"loading...",e(Xe,{w:"full",allowToggle:!0,index:Object.keys(i).map(y=>parseInt(y)),children:r(M,{w:"full",children:[!l&&a&&a.map((y,c)=>e(Fs,{toggleAccordion:()=>p(c),node:y},y.name)),e(Ps,{toggleAccordion:()=>p((a||[]).length),resetAccordions:()=>s({})})]})})]})]})]}),e(Rs,{deleteCallback:()=>s({})})]})};function Os(t){const o=360/t,n=90,i=47,s=[];for(let a=0;a(C<0&&(C+=1),C>1&&(C-=1),C<.16666666666666666?c+(d-c)*6*C:C<.5?d:C<.6666666666666666?c+(d-c)*(.6666666666666666-C)*6:c),p=n<.5?n*(1+o):n+o-n*o,y=2*n-p;i=Math.round(u(y,p,t+1/3)*255),s=Math.round(u(y,p,t)*255),a=Math.round(u(y,p,t-1/3)*255)}const l=u=>{const p=u.toString(16);return p.length===1?"0"+p:p};return`#${l(i)}${l(s)}${l(a)}`}const dr=({border:t,...o})=>{const{getInputProps:n,getRadioProps:i}=Jo(o),s=Se({base:"xs",md:"sm"});return r(I,{as:"label",children:[e("input",{...n()}),e(I,{...i(),minW:"48px",w:"full",h:"full",textAlign:"center",cursor:"pointer",fontSize:s,borderWidth:t?"1px":"0px",borderRadius:"md",_checked:{bg:"primary.500",color:"white",borderColor:"primary.500"},_focus:{boxShadow:"outline"},px:3,py:1,children:o.children})]})},eo=({onChange:t,defaultValue:o,...n})=>{const{t:i,i18n:s}=O();Qe();const a=Se({base:["7h","1d","3d","1w"],md:["7h","1d","3d","1w","1m","3m"]}),l={h:"hour",d:"day",w:"week",m:"month",y:"year"},u=Se({base:[{title:"hours",options:["1h","3h","6h","12h"]},{title:"days",options:["1d","2d","3d","4d"]},{title:"weeks",options:["1w","2w","3w","4w"]},{title:"months",options:["1m","2m","3m","6m"]}],md:[{title:"hours",options:["1h","2h","3h","6h","8h","12h"]},{title:"days",options:["1d","2d","3d","4d","5d","6d"]},{title:"weeks",options:["1w","2w","3w","4w"]},{title:"months",options:["1m","2m","3m","6m","8m"]}]}),{getRootProps:p,getRadioProps:y,setValue:c}=Go({name:"filter",defaultValue:o,onChange:L=>{if(L==="custom")return;_(),a.indexOf(L)>=0?(R(i("userDialog.custom")),f(!1)):(R(i("userDialog.custom")+` (${L})`),f(!0));const Y=Number(L.substring(0,L.length-1)),J=l[L[L.length-1]];t(L,{start:j().utc().subtract(Y,J).format("YYYY-MM-DDTHH:00:00")})}}),{isOpen:d,onOpen:C,onClose:_}=Zo(),b=g.exports.useRef(null);Yo({ref:b,handler:_});const[S,R]=g.exports.useState(i("userDialog.custom")),[m,f]=g.exports.useState(!1),[P,H]=g.exports.useState(0),U=Se({base:1,md:2}),T=Se({base:"xs",md:"sm"}),[B,G]=g.exports.useState(null),[D,F]=g.exports.useState(null),Z=L=>{const[Y,J]=L;D&&!J?(G(null),F(null)):(G(Y),F(J),Y&&J&&(_(),t("custom",{start:j(Y).format("YYYY-MM-DDT00:00:00"),end:j(J).format("YYYY-MM-DDT23:59:59")})))};return r(M,{...n,children:[P==0&&r(Rt,{...p(),gap:0,display:"flex",borderWidth:"1px",borderRadius:"md",minW:{base:"320px",md:"400px"},children:[a.map(L=>e(dr,{...y({value:L}),children:L},L)),e(I,{onClick:()=>{G(null),F(null),C()},cursor:"pointer",borderRadius:"md",w:"full",fontSize:T,px:3,py:1,bg:m?"primary.500":"unset",color:m?"white":"unset",borderColor:m?"primary.500":"unset",children:r(w,{children:[e(h,{children:S}),e(bt,{as:qt,boxSize:"18px"})]})})]}),P==1&&r(w,{onClick:C,cursor:"pointer",fontSize:T,borderRadius:"md",px:3,py:1,minW:{base:"320px",md:"400px"},borderWidth:"1px",children:[e(h,{w:"full",color:B?"unset":"gray.500",children:B?j(B).format("YYYY-MM-DD (00:00)"):i("userDialog.startDate")}),e(bt,{as:Nr,boxSize:"18px"}),e(h,{w:"full",color:D?"unset":"gray.500",children:D?j(D).format("YYYY-MM-DD (23:59)"):i("userDialog.endDate")}),e(bt,{as:qt,boxSize:"18px"})]}),e(M,{ref:b,marginTop:"40px !important",borderRadius:"md",borderWidth:"1px",position:"absolute",zIndex:"1",backgroundColor:"white",_dark:{backgroundColor:"gray.700"},display:d?"unset":"none",children:r(Qo,{onChange:L=>H(L),children:[r(qo,{children:[e(Xt,{fontSize:T,children:i("userDialog.relative")}),e(Xt,{fontSize:T,children:i("userDialog.absolute")})]}),r(Xo,{children:[e(Jt,{children:u.map(L=>e(M,{alignItems:"start",pl:2,pr:2,children:r(w,{justifyItems:"flex-start",mb:4,children:[e(h,{fontSize:T,minW:"60px",children:i("userDialog."+L.title)}),L.options.map(Y=>e(dr,{border:!0,...y({value:Y}),children:Y},Y+".custom"))]})},L.title))}),e(Jt,{className:"datepicker-panel",children:e(M,{children:e(Fr,{locale:s.language.toLocaleLowerCase(),selected:B,onChange:Z,startDate:B,endDate:D,selectsRange:!0,maxDate:new Date,monthsShown:U,peekNextMonth:!1,inline:!0})})})]})]})})]})};function ut(t,o,n=[],i=[]){const s=ee(n.reduce((a,l)=>a+=l,0));return{series:n,options:{labels:i,chart:{width:"100%",height:"100%",type:"donut",animations:{enabled:!1}},title:{text:`${o}${s}`,align:"center",style:{fontWeight:"var(--chakra-fontWeights-medium)",color:t==="dark"?"var(--chakra-colors-gray-300)":void 0}},legend:{position:"bottom",labels:{colors:t==="dark"?"#CBD5E0":void 0,useSeriesColors:!1}},stroke:{width:1,colors:void 0},dataLabels:{formatter:(a,{seriesIndex:l,w:u})=>ee(u.config.series[l],1)},tooltip:{custom:({series:a,seriesIndex:l,dataPointIndex:u,w:p})=>{const y=ee(a[l],1),c=Math.max(a.reduce((C,_)=>C+=_),1),d=Math.round(a[l]/c*1e3)/10+"%";return`
- Marzban
+ infinity
-
-
+
+
diff --git a/app/dashboard/build/locales/en.json b/app/dashboard/build/locales/en.json
index 6d068e152..a131e9c01 100644
--- a/app/dashboard/build/locales/en.json
+++ b/app/dashboard/build/locales/en.json
@@ -99,10 +99,10 @@
"hostsDialog.fingerprint": "Fingerprint",
"hostsDialog.host.multiHost": "To set multiple addresses, separate them with , Each time an address is chosen randomly.",
"hostsDialog.host.wildcard": "Use * to generate a random string (works for wildcard domain names)",
- "nodes.title": "Using Marzban-Node, you are able to scale up your connection quality by adding different nodes on different servers.",
- "nodes.addNewMarzbanNode": "Add New Marzban Node",
+ "nodes.title": "Using infinity-Node, you are able to scale up your connection quality by adding different nodes on different servers.",
+ "nodes.addNewinfinityNode": "Add New infinity Node",
"nodes.certificate": "Certificate",
- "nodes.connection-hint": "To setup a Marzban Node, you need to set this certificate on the node to initialize a secure connection between main server and the node",
+ "nodes.connection-hint": "To setup a infinity Node, you need to set this certificate on the node to initialize a secure connection between main server and the node",
"nodes.download-certificate": "Download certificate",
"nodes.show-certificate": "Show certificate",
"nodes.hide-certificate": "Hide certificate",
diff --git a/app/dashboard/build/locales/fa.json b/app/dashboard/build/locales/fa.json
index 7390f55b3..f93d4005c 100644
--- a/app/dashboard/build/locales/fa.json
+++ b/app/dashboard/build/locales/fa.json
@@ -102,8 +102,8 @@
"hostsDialog.fingerprint": "اثرانگشت",
"hostsDialog.host.multiHost": "برای تنظیم چند آدرس، با , از هم جدا کنید. هر دفعه آدرسی به صورت تصادفی قرار داده میشود.",
"hostsDialog.host.wildcard": "از * برای ساخت عبارت تصادفی استفاده کنید (برای نامهای wildcard کار میکند)",
- "nodes.title": "با استفاده از Marzban-Node, شما میتوانید با افزودن گرههای متفاوت در سرورهای متفاوت، کیفیت اتصال خود را بالاتر ببرید.",
- "nodes.addNewMarzbanNode": "افزودن گره مرزبان",
+ "nodes.title": "با استفاده از infinity-Node, شما میتوانید با افزودن گرههای متفاوت در سرورهای متفاوت، کیفیت اتصال خود را بالاتر ببرید.",
+ "nodes.addNewinfinityNode": "افزودن گره مرزبان",
"nodes.certificate": "گواهی",
"nodes.addHostForEveryInbound": "استفاده از این گره به عنوان میزبان تمام ورودیها",
"nodes.addNode": "افزودن گره",
diff --git a/app/dashboard/build/locales/ru.json b/app/dashboard/build/locales/ru.json
index e636e42d8..400c9d507 100644
--- a/app/dashboard/build/locales/ru.json
+++ b/app/dashboard/build/locales/ru.json
@@ -99,8 +99,8 @@
"hostsDialog.fingerprint": "Fingerprint",
"hostsDialog.host.multiHost": "Чтобы установить несколько адресов, разделяйте их с помощью ,. Каждый раз выбирается случайный адрес.",
"hostsDialog.host.wildcard": "Используйте *, чтобы сгенерировать случайную строку (работает для доменных имен с подстановочными знаками)",
- "nodes.title": "Используя Marzban-Node, вы можете повысить качество соединения, добавляя узлы на разных серверах.",
- "nodes.addNewMarzbanNode": "Добавить новый узел Marzban",
+ "nodes.title": "Используя infinity-Node, вы можете повысить качество соединения, добавляя узлы на разных серверах.",
+ "nodes.addNewinfinityNode": "Добавить новый узел infinity",
"nodes.certificate": "Сертификат",
"nodes.addHostForEveryInbound": "Добавить этот узел как новый хост для каждого inbound",
"nodes.addNode": "Добавить узел",
@@ -112,7 +112,7 @@
"nodes.nodeAPIPort": "API порт",
"nodes.editNode": "Редактировать узел",
"nodes.reconnect": "Переподключиться",
- "nodes.connection-hint": "Для настройки узла Marzban, необходимо установить на нем данный сертификат, для инициализации безопасного соединения между главным сервером и узлом",
+ "nodes.connection-hint": "Для настройки узла infinity, необходимо установить на нем данный сертификат, для инициализации безопасного соединения между главным сервером и узлом",
"nodes.download-certificate": "Скачать сертификат",
"nodes.show-certificate": "Показать сертификат",
"nodes.hide-certificate": "Скрыть сертификат",
diff --git a/app/dashboard/build/locales/zh.json b/app/dashboard/build/locales/zh.json
index cf8b41429..476cce3bb 100644
--- a/app/dashboard/build/locales/zh.json
+++ b/app/dashboard/build/locales/zh.json
@@ -93,8 +93,8 @@
"hostsDialog.security.info": "如果此主机的中间件服务器使用的安全层与入站默认值不同,则可以在此处设置自定义安全层。",
"hostsDialog.alpn": "ALPN",
"hostsDialog.fingerprint": "指纹",
- "nodes.title": "使用 Marzban-Node,您可以通过在不同的服务器上添加不同的节点来提供多节点负载。",
- "nodes.addNewMarzbanNode": "添加新的 Marzban 节点",
+ "nodes.title": "使用 infinity-Node,您可以通过在不同的服务器上添加不同的节点来提供多节点负载。",
+ "nodes.addNewinfinityNode": "添加新的 infinity 节点",
"nodes.certificate": "证书",
"nodes.addHostForEveryInbound": "为每个入站请求添加此节点作为新主机",
"nodes.addNode": "添加节点",
@@ -105,7 +105,7 @@
"nodes.nodePort": "端口",
"nodes.nodeAPIPort": "API 端口",
"nodes.reconnect": "重新连接",
- "nodes.connection-hint": "要设置Marzban节点,您需要在节点上设置此证书以初始化主服务器和节点之间的安全连接",
+ "nodes.connection-hint": "要设置infinity节点,您需要在节点上设置此证书以初始化主服务器和节点之间的安全连接",
"nodes.download-certificate": "下载证书",
"nodes.show-certificate": "如何证书",
"nodes.hide-certificate": "隐藏证书",
diff --git a/app/dashboard/index.html b/app/dashboard/index.html
index 4fc52083e..50b884a39 100644
--- a/app/dashboard/index.html
+++ b/app/dashboard/index.html
@@ -3,7 +3,7 @@
- Marzban
+ infinity
-
-
+
+
diff --git a/app/dashboard/package-lock.json b/app/dashboard/package-lock.json
index 112c32723..3a3c15fbf 100644
--- a/app/dashboard/package-lock.json
+++ b/app/dashboard/package-lock.json
@@ -1,11 +1,11 @@
{
- "name": "marzban-dashboard",
+ "name": "infinity-dashboard",
"version": "0.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
- "name": "marzban-dashboard",
+ "name": "infinity-dashboard",
"version": "0.0.0",
"hasInstallScript": true,
"dependencies": {
diff --git a/app/dashboard/package.json b/app/dashboard/package.json
index f7ddb6807..83aadfdfa 100644
--- a/app/dashboard/package.json
+++ b/app/dashboard/package.json
@@ -1,5 +1,5 @@
{
- "name": "marzban-dashboard",
+ "name": "infinity-dashboard",
"private": true,
"version": "0.0.0",
"scripts": {
diff --git a/app/dashboard/public/locales/en.json b/app/dashboard/public/locales/en.json
index 6d068e152..a131e9c01 100644
--- a/app/dashboard/public/locales/en.json
+++ b/app/dashboard/public/locales/en.json
@@ -99,10 +99,10 @@
"hostsDialog.fingerprint": "Fingerprint",
"hostsDialog.host.multiHost": "To set multiple addresses, separate them with , Each time an address is chosen randomly.",
"hostsDialog.host.wildcard": "Use * to generate a random string (works for wildcard domain names)",
- "nodes.title": "Using Marzban-Node, you are able to scale up your connection quality by adding different nodes on different servers.",
- "nodes.addNewMarzbanNode": "Add New Marzban Node",
+ "nodes.title": "Using infinity-Node, you are able to scale up your connection quality by adding different nodes on different servers.",
+ "nodes.addNewinfinityNode": "Add New infinity Node",
"nodes.certificate": "Certificate",
- "nodes.connection-hint": "To setup a Marzban Node, you need to set this certificate on the node to initialize a secure connection between main server and the node",
+ "nodes.connection-hint": "To setup a infinity Node, you need to set this certificate on the node to initialize a secure connection between main server and the node",
"nodes.download-certificate": "Download certificate",
"nodes.show-certificate": "Show certificate",
"nodes.hide-certificate": "Hide certificate",
diff --git a/app/dashboard/public/locales/fa.json b/app/dashboard/public/locales/fa.json
index 7390f55b3..f93d4005c 100644
--- a/app/dashboard/public/locales/fa.json
+++ b/app/dashboard/public/locales/fa.json
@@ -102,8 +102,8 @@
"hostsDialog.fingerprint": "اثرانگشت",
"hostsDialog.host.multiHost": "برای تنظیم چند آدرس، با , از هم جدا کنید. هر دفعه آدرسی به صورت تصادفی قرار داده میشود.",
"hostsDialog.host.wildcard": "از * برای ساخت عبارت تصادفی استفاده کنید (برای نامهای wildcard کار میکند)",
- "nodes.title": "با استفاده از Marzban-Node, شما میتوانید با افزودن گرههای متفاوت در سرورهای متفاوت، کیفیت اتصال خود را بالاتر ببرید.",
- "nodes.addNewMarzbanNode": "افزودن گره مرزبان",
+ "nodes.title": "با استفاده از infinity-Node, شما میتوانید با افزودن گرههای متفاوت در سرورهای متفاوت، کیفیت اتصال خود را بالاتر ببرید.",
+ "nodes.addNewinfinityNode": "افزودن گره مرزبان",
"nodes.certificate": "گواهی",
"nodes.addHostForEveryInbound": "استفاده از این گره به عنوان میزبان تمام ورودیها",
"nodes.addNode": "افزودن گره",
diff --git a/app/dashboard/public/locales/ru.json b/app/dashboard/public/locales/ru.json
index e636e42d8..400c9d507 100644
--- a/app/dashboard/public/locales/ru.json
+++ b/app/dashboard/public/locales/ru.json
@@ -99,8 +99,8 @@
"hostsDialog.fingerprint": "Fingerprint",
"hostsDialog.host.multiHost": "Чтобы установить несколько адресов, разделяйте их с помощью ,. Каждый раз выбирается случайный адрес.",
"hostsDialog.host.wildcard": "Используйте *, чтобы сгенерировать случайную строку (работает для доменных имен с подстановочными знаками)",
- "nodes.title": "Используя Marzban-Node, вы можете повысить качество соединения, добавляя узлы на разных серверах.",
- "nodes.addNewMarzbanNode": "Добавить новый узел Marzban",
+ "nodes.title": "Используя infinity-Node, вы можете повысить качество соединения, добавляя узлы на разных серверах.",
+ "nodes.addNewinfinityNode": "Добавить новый узел infinity",
"nodes.certificate": "Сертификат",
"nodes.addHostForEveryInbound": "Добавить этот узел как новый хост для каждого inbound",
"nodes.addNode": "Добавить узел",
@@ -112,7 +112,7 @@
"nodes.nodeAPIPort": "API порт",
"nodes.editNode": "Редактировать узел",
"nodes.reconnect": "Переподключиться",
- "nodes.connection-hint": "Для настройки узла Marzban, необходимо установить на нем данный сертификат, для инициализации безопасного соединения между главным сервером и узлом",
+ "nodes.connection-hint": "Для настройки узла infinity, необходимо установить на нем данный сертификат, для инициализации безопасного соединения между главным сервером и узлом",
"nodes.download-certificate": "Скачать сертификат",
"nodes.show-certificate": "Показать сертификат",
"nodes.hide-certificate": "Скрыть сертификат",
diff --git a/app/dashboard/public/locales/zh.json b/app/dashboard/public/locales/zh.json
index cf8b41429..476cce3bb 100644
--- a/app/dashboard/public/locales/zh.json
+++ b/app/dashboard/public/locales/zh.json
@@ -93,8 +93,8 @@
"hostsDialog.security.info": "如果此主机的中间件服务器使用的安全层与入站默认值不同,则可以在此处设置自定义安全层。",
"hostsDialog.alpn": "ALPN",
"hostsDialog.fingerprint": "指纹",
- "nodes.title": "使用 Marzban-Node,您可以通过在不同的服务器上添加不同的节点来提供多节点负载。",
- "nodes.addNewMarzbanNode": "添加新的 Marzban 节点",
+ "nodes.title": "使用 infinity-Node,您可以通过在不同的服务器上添加不同的节点来提供多节点负载。",
+ "nodes.addNewinfinityNode": "添加新的 infinity 节点",
"nodes.certificate": "证书",
"nodes.addHostForEveryInbound": "为每个入站请求添加此节点作为新主机",
"nodes.addNode": "添加节点",
@@ -105,7 +105,7 @@
"nodes.nodePort": "端口",
"nodes.nodeAPIPort": "API 端口",
"nodes.reconnect": "重新连接",
- "nodes.connection-hint": "要设置Marzban节点,您需要在节点上设置此证书以初始化主服务器和节点之间的安全连接",
+ "nodes.connection-hint": "要设置infinity节点,您需要在节点上设置此证书以初始化主服务器和节点之间的安全连接",
"nodes.download-certificate": "下载证书",
"nodes.show-certificate": "如何证书",
"nodes.hide-certificate": "隐藏证书",
diff --git a/app/dashboard/src/components/Footer.tsx b/app/dashboard/src/components/Footer.tsx
index f96b531b7..df0aa4052 100644
--- a/app/dashboard/src/components/Footer.tsx
+++ b/app/dashboard/src/components/Footer.tsx
@@ -15,12 +15,12 @@ export const Footer: FC = (props) => {
fontSize="xs"
>
- Marzban
+ infinity
{version ? ` (v${version}), ` : ", "}
Made with ❤️ in{" "}
- Gozargah
+ Niraj-Dilshan
diff --git a/app/dashboard/src/components/Header.tsx b/app/dashboard/src/components/Header.tsx
index c42608f9d..a3a86a660 100644
--- a/app/dashboard/src/components/Header.tsx
+++ b/app/dashboard/src/components/Header.tsx
@@ -63,7 +63,7 @@ const NotificationCircle = chakra(Box, {
},
});
-const NOTIFICATION_KEY = "marzban-menu-notification";
+const NOTIFICATION_KEY = "infinity-menu-notification";
export const shouldShowDonation = (): boolean => {
const date = localStorage.getItem(NOTIFICATION_KEY);
@@ -226,7 +226,7 @@ export const Header: FC = ({ actions }) => {
data-color-scheme={`no-preference: ${gBtnColor}; light: ${gBtnColor}; dark: ${gBtnColor};`}
data-size="large"
data-show-count="true"
- aria-label="Star Marzban on GitHub"
+ aria-label="Star infinity on GitHub"
>
Star
diff --git a/app/dashboard/src/components/NodesModal.tsx b/app/dashboard/src/components/NodesModal.tsx
index 78446f388..3aa2b3209 100644
--- a/app/dashboard/src/components/NodesModal.tsx
+++ b/app/dashboard/src/components/NodesModal.tsx
@@ -288,7 +288,7 @@ const AddNodeForm: FC = ({
gap={1}
>
{" "}
- {t("nodes.addNewMarzbanNode")}
+ {t("nodes.addNewinfinityNode")}
@@ -431,7 +431,7 @@ const NodeForm: NodeFormType = ({
diff --git a/app/dashboard/src/constants/Project.ts b/app/dashboard/src/constants/Project.ts
index ddd90b070..5c70f75dc 100644
--- a/app/dashboard/src/constants/Project.ts
+++ b/app/dashboard/src/constants/Project.ts
@@ -1,3 +1,3 @@
-export const REPO_URL = "https://github.com/Gozargah/Marzban";
-export const ORGANIZATION_URL = "https://github.com/Gozargah";
-export const DONATION_URL = "https://github.com/Gozargah/Marzban#donation";
+export const REPO_URL = "https://github.com/Niraj-Dilshan/infinity";
+export const ORGANIZATION_URL = "https://github.com/Niraj-Dilshan";
+export const DONATION_URL = "https://github.com/Niraj-Dilshan/infinity#donation";
diff --git a/app/dashboard/src/utils/userPreferenceStorage.ts b/app/dashboard/src/utils/userPreferenceStorage.ts
index 11334261a..e1913717e 100644
--- a/app/dashboard/src/utils/userPreferenceStorage.ts
+++ b/app/dashboard/src/utils/userPreferenceStorage.ts
@@ -1,4 +1,4 @@
-const NUM_USERS_PER_PAGE_LOCAL_STORAGE_KEY = "marzban-num-users-per-page";
+const NUM_USERS_PER_PAGE_LOCAL_STORAGE_KEY = "infinity-num-users-per-page";
const NUM_USERS_PER_PAGE_DEFAULT = 10;
export const getUsersPerPageLimitSize = () => {
const numUsersPerPage =
diff --git a/app/telegram/handlers/admin.py b/app/telegram/handlers/admin.py
index 19a040430..667a23f22 100644
--- a/app/telegram/handlers/admin.py
+++ b/app/telegram/handlers/admin.py
@@ -97,7 +97,7 @@ def help_command(message: types.Message):
cleanup_messages(message.chat.id)
bot.clear_step_handler_by_chat_id(message.chat.id)
return bot.reply_to(message, """
-{user_link} Welcome to Marzban Telegram-Bot Admin Panel.
+{user_link} Welcome to infinity Telegram-Bot Admin Panel.
Here you can manage your users and proxies.
To get started, use the buttons below.
""".format(
diff --git a/app/utils/crypto.py b/app/utils/crypto.py
index 82d239c53..ba2a5d8a7 100644
--- a/app/utils/crypto.py
+++ b/app/utils/crypto.py
@@ -18,7 +18,7 @@ def generate_certificate():
k = crypto.PKey()
k.generate_key(crypto.TYPE_RSA, 4096)
cert = crypto.X509()
- cert.get_subject().CN = "Gozargah"
+ cert.get_subject().CN = "Niraj-Dilshan"
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(100*365*24*60*60)
cert.set_issuer(cert.get_subject())
diff --git a/app/views/admin.py b/app/views/admin.py
index cb272128a..86a01a741 100644
--- a/app/views/admin.py
+++ b/app/views/admin.py
@@ -78,7 +78,7 @@ def modify_admin(username: str,
if (username != admin.username) and dbadmin.is_sudo:
raise HTTPException(
status_code=403,
- detail=("You're not allowed to edit another sudoers account. Use marzban-cli instead.",),
+ detail=("You're not allowed to edit another sudoers account. Use infinity-cli instead.",),
)
dbadmin = crud.update_admin(db, dbadmin, modified_admin)
@@ -99,7 +99,7 @@ def remove_admin(username: str,
if dbadmin.is_sudo:
raise HTTPException(
status_code=403,
- detail=("You're not allowed to delete sudoers accounts. Use marzban-cli instead."),
+ detail=("You're not allowed to delete sudoers accounts. Use infinity-cli instead."),
)
dbadmin = crud.remove_admin(db, dbadmin)
diff --git a/app/xray/node.py b/app/xray/node.py
index 667608380..2ff883ca5 100644
--- a/app/xray/node.py
+++ b/app/xray/node.py
@@ -162,7 +162,7 @@ def start(self, config: XRayConfig):
address=self.address,
port=self.api_port,
ssl_cert=self._node_cert.encode(),
- ssl_target_name="Gozargah"
+ ssl_target_name="Niraj-Dilshan"
)
try:
grpc.channel_ready_future(self._api._channel).result(timeout=5)
diff --git a/cli/README.md b/cli/README.md
index 429eda824..d4cff1f40 100644
--- a/cli/README.md
+++ b/cli/README.md
@@ -41,7 +41,7 @@ $ admin [OPTIONS] COMMAND [ARGS]...
Creates an admin
-Password can also be set using the `MARZBAN_ADMIN_PASSWORD` environment variable for non-interactive usages.
+Password can also be set using the `infinity_ADMIN_PASSWORD` environment variable for non-interactive usages.
**Usage**:
diff --git a/cli/admin.py b/cli/admin.py
index 1a3034f2a..a7f1af4e4 100644
--- a/cli/admin.py
+++ b/cli/admin.py
@@ -68,7 +68,7 @@ def create_admin(
"""
Creates an admin
- Password can also be set using the `MARZBAN_ADMIN_PASSWORD` environment variable for non-interactive usages.
+ Password can also be set using the `infinity_ADMIN_PASSWORD` environment variable for non-interactive usages.
"""
with GetDB() as db:
try:
diff --git a/cli/utils.py b/cli/utils.py
index 0ff37d10a..aa953c575 100644
--- a/cli/utils.py
+++ b/cli/utils.py
@@ -12,7 +12,7 @@
T = TypeVar("T")
rich_console = Console()
-PASSWORD_ENVIRON_NAME = "MARZBAN_ADMIN_PASSWORD"
+PASSWORD_ENVIRON_NAME = "infinity_ADMIN_PASSWORD"
FLAGS: Dict[str, tuple] = {
"username": ("--username", "-u"),
diff --git a/docker-compose.yml b/docker-compose.yml
index f647593b0..da3466b58 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,8 +1,8 @@
services:
- marzban:
- image: gozargah/marzban:latest
+ infinity:
+ image: Niraj-Dilshan/infinity:latest
restart: always
env_file: .env
network_mode: host
volumes:
- - /var/lib/marzban:/var/lib/marzban
+ - /var/lib/infinity:/var/lib/infinity
diff --git a/marzban-cli.py b/infinity-cli.py
old mode 100755
new mode 100644
similarity index 100%
rename from marzban-cli.py
rename to infinity-cli.py
diff --git a/install_service.sh b/install_service.sh
index 3a380ebc7..29b178b4a 100755
--- a/install_service.sh
+++ b/install_service.sh
@@ -1,8 +1,8 @@
#!/bin/bash
-SERVICE_NAME="marzban"
-SERVICE_DESCRIPTION="Marzban Service"
-SERVICE_DOCUMENTATION="https://github.com/gozargah/marzban"
+SERVICE_NAME="infinity"
+SERVICE_DESCRIPTION="infinity Service"
+SERVICE_DOCUMENTATION="https://github.com/Niraj-Dilshan/infinity"
MAIN_PY_PATH="$PWD/main.py"
SERVICE_FILE="/etc/systemd/system/$SERVICE_NAME.service"
diff --git a/marzban.code-workspace b/marzban.code-workspace
deleted file mode 100644
index 876a1499c..000000000
--- a/marzban.code-workspace
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "folders": [
- {
- "path": "."
- }
- ],
- "settings": {}
-}
\ No newline at end of file