feat(discord): add Discord notification bot service (#6486)

* feat(discord): add Discord notification bot service, settings UI, and event subscriber
- internal/web/service/discord: implement lightweight Discord REST API v10 client and EventBus subscriber
- internal/web/service/setting: add discordBotEnable, discordBotToken, discordChannelId, discordEnabledEvents, discordCpu, discordMemory settings and secret protection
- internal/web/controller: register POST /panel/api/setting/testDiscord endpoint
- frontend: add Discord settings tab, notifications configuration, sidebar navigation, and command palette integration
- translation: add localization keys across all 13 locales
- tests: add comprehensive unit tests with httptest server and verify route/i18n contracts

* fix(discord): address PR review findings on concurrency, linting, i18n, and stories

- subscriber: eliminate unbounded goroutines, sending inline per EventBus contract
- discord: accept context.Context in SendMessage, SendEmbed, SendTest with http.NewRequestWithContext
- format: apply gofumpt to controller and entity struct alignments
- i18n: localize testDiscord controller responses across all 13 locales
- storybook: add DiscordNotifications.stories.tsx component story

* docs: add Discord bot setup and operations guide

- add docs/content/docs/en/operations/discord-bot.mdx with setup steps, event indicators, settings, and troubleshooting
- add docs/content/docs/ru/operations/discord-bot.mdx with localized instructions
- update operations/meta.json across en, ru, zh, fa
- link Discord bot from panel configuration overview

* feat(discord): add discordLang, discordRunTime, discordBotBackup settings and update settings UI

- internal/web/entity: add DiscordRunTime, DiscordBotBackup, DiscordLang fields to AllSetting
- internal/web/service/setting: add defaultValueMap entries, getters, and setters
- frontend: update AllSetting schema, model defaults, and generate OpenAPI / Zod contracts
- frontend: extract shared NotifyTimeField component and update DiscordTab with General and Notifications tabs
- translation: add localization keys across all 13 locales

* feat(discord): implement scheduled status reports and database backup attachments

- internal/web/service/discord: add SendMessageWithFiles supporting multipart uploads
- internal/web/service/discord: implement BuildReport and SendReport generating rich status embeds
- internal/web/service/discord: attach database backup (and config.json) when discordBotBackup is enabled
- internal/web/job: implement DiscordNotifyJob scheduled via robfig/cron
- internal/web/locale: add LocalizerFor and I18nForLang helpers
- internal/web/controller: trigger reloadDiscordFunc to dynamically reschedule cron upon setting changes
- internal/web/web: register and reschedule DiscordNotifyJob
- tests: comprehensive unit tests for multipart uploads, status reporting, and job execution

* feat(discord): add interactive bot commands via Gateway WebSocket and update documentation

- internal/web/service/discord/gateway: connect to Discord Gateway v10 via WebSocket (gorilla/websocket)
- internal/web/service/discord/gateway: handle heartbeat loop, reconnection, and command dispatch
- commands: implement !status, !report, !backup, !usage <email>, !inbounds, !restart, !help (with ! and / prefixes)
- internal/web/web: start/stop Gateway client with server and reload dynamically on setting updates
- docs: update operations guide (en, ru) with scheduled reports, backups, commands, and privileged intents
- tests: add end-to-end WebSocket Gateway test verifying command handling

* style(discord): fix goimports formatting and add 3x-ui to gitignore

* fix(discord): stop gateway panics, reconnect storms and proxy bypass

The Gateway client wrote to its websocket from both the heartbeat ticker
and the read loop answering server-requested op 1 heartbeats. gorilla
panics on concurrent writes and neither goroutine recovers, so a colliding
heartbeat took the whole panel process down; writes now share writeMu.

It also reconnected every 5s forever after close codes Discord marks
non-reconnectable (4004 bad token, 4010-4014, including 4014 when Message
Content Intent is off), re-identifying and logging a warning each time.
The loop now stops on those codes; the docs say to restart the panel.

The gateway dialed with websocket.DefaultDialer, bypassing the panel
egress proxy the REST client already uses, so where Discord is filtered
notifications arrived but commands never connected.

* fix(discord): deliver the scheduled report when the backup upload fails

SendReport posted the report embed and the x-ui.db/config.json attachments
in one multipart request. Once the database outgrows Discord's upload cap
(20 MiB by default) the request is rejected and the report embed is lost
with it on every run, leaving only a log warning. Send the embed first and
the attachments as a second message.

* chore(discord): delete tests that pass whether or not the code works

TestDiscordNotifyJob_NilServiceNoPanic and TestHandleEvent_NilDiscordService
feed a nil DiscordService that web.go never passes, and
TestDiscordNotifyJob_DisabledNoPanic passes with or without the enable
guard because Xray is not running under test.

* fix(discord): require admin user IDs for bot commands and honor discordLang

Any member who could post in the configured channel could run !backup
(the whole x-ui.db and config.json, even with discordBotBackup off),
!restart and !usage. Commands now run only for the Discord user IDs in
the new discordAdminIds setting; an empty list turns commands off.

discordLang was saved and offered in the UI, but nothing read it, so
every embed stayed English. The test message, alerts, the scheduled
report and command replies now render through I18nForLang in the chosen
language, with a discord section in all 13 locales. InitLocalizer takes
an fs.FS so tests load the real translation files.

---------

Co-authored-by: Sanaei <ho3ein.sanaei@gmail.com>
This commit is contained in:
Egor
2026-09-13 17:04:53 +05:00
committed by GitHub
parent cba8f0672f
commit bf7ce2daaa
59 changed files with 6271 additions and 206 deletions
+1
View File
@@ -67,6 +67,7 @@ These have their own settings groups and pages:
<Cards>
<Card title="Telegram bot" href="/docs/operations/telegram-bot" description="Token, chat IDs, alerts, and reports." />
<Card title="Discord bot" href="/docs/operations/discord-bot" description="Token, channel ID, and event alerts." />
<Card title="Subscription" href="/docs/config/subscription" description="Subscription server, formats, and paths." />
<Card title="Security" href="/docs/operations/security" description="2FA, IP limits, and hardening." />
</Cards>
@@ -0,0 +1,121 @@
---
title: Discord Bot
description: Connect a Discord bot to 3x-ui to receive real-time Embed notifications in a channel for panel events (service crashes, node status, CPU/RAM load, and login attempts).
icon: Bot
---
3x-ui provides comprehensive Discord integration: real-time event notifications via the event bus (`EventBus`), periodic scheduled health reports with database backups, and interactive commands via the Discord Gateway.
<Callout type="info">
Discord notifications and scheduled reports use outbound HTTPS REST API v10 calls. Interactive bot commands connect via a secure background WebSocket connection to the Discord Gateway.
</Callout>
## Set it up
<Steps>
<Step>
### Create a Discord Application & Bot
1. Open the [Discord Developer Portal](https://discord.com/developers/applications) and sign in.
2. Click **New Application** at the top right, enter a name (e.g., `3x-ui Notifier`), and confirm.
3. In the left sidebar, navigate to the **Bot** tab.
4. Click **Reset Token** (or **Add Bot** if not already created) and copy the **Bot Token**. Keep this token secure.
5. Under **Privileged Gateway Intents**, toggle on **Message Content Intent** (required for the bot to read prefix commands like `!status`).
</Step>
<Step>
### Invite the Bot to your Discord Server
1. In the Discord Developer Portal, navigate to **OAuth2** $\rightarrow$ **URL Generator**.
2. Under **Scopes**, check `bot`.
3. Under **Bot Permissions**, select:
- **Send Messages**
- **Embed Links**
- **Attach Files** (required for database backups)
- **Read Message History**
4. Copy the generated URL at the bottom and open it in your browser to invite the bot to your server.
</Step>
<Step>
### Copy the Channel ID
1. In your Discord client, enable Developer Mode: **User Settings** $\rightarrow$ **Advanced** $\rightarrow$ **Developer Mode** (toggle on).
2. Right-click the channel where you want alerts and bot interaction to occur and select **Copy Channel ID**.
3. Ensure the bot has access to view and send messages in this specific channel.
</Step>
<Step>
### Configure the Panel
1. In the 3x-ui panel, open **Panel Settings** $\rightarrow$ **Discord Bot** (or navigate to `/settings#discord`).
2. Under **General**:
- Toggle **Enable Discord Notifications** on.
- Enter your **Discord Bot Token** and **Channel ID**.
- Enter your own Discord user ID in **Admin User IDs** (right-click your name → **Copy User ID**; separate several IDs with commas).
- Select your preferred **Discord Bot Language**.
3. Under **Notifications**:
- Set the **Notification Time** schedule (e.g., `@daily`, `@weekly`, or custom crontab).
- Optionally toggle **Database Backups** to automatically attach `x-ui.db` with periodic reports.
- Select which events trigger notifications and adjust CPU/RAM thresholds.
4. Click **Send Test Notification** to verify delivery. A test embed will immediately appear in your Discord channel.
5. Click **Save** to apply changes.
</Step>
</Steps>
## Bot Commands
When enabled, the bot listens to commands in the configured Discord channel (supporting both `!` and `/` prefixes). Only users listed in **Admin User IDs** can run them; messages from anyone else are ignored, and an empty list turns commands off. `!backup` and scheduled backups post the database into the channel, so pick a channel only admins can read:
| Command | Description |
| ------- | ----------- |
| `!status` | Display system load, RAM, CPU usage, TCP/UDP connections, and active clients. |
| `!report` | Generate and send a complete status report embed immediately. |
| `!backup` | Download current database backup file (`x-ui.db`) and `config.json`. |
| `!usage <email>` | Query bandwidth usage (upload/download), quota limit, and expiration date for a client. |
| `!inbounds` | List all active inbounds with port, protocol, traffic, and client counts. |
| `!restart` | Safely restart the Xray core without restarting the web panel. |
| `!help` | Display list of available bot commands. |
## Event Alerts
Alerts are sent as Discord Embeds with color coding and relevant diagnostics:
| Event | Indicator | Description |
| ----- | --------- | ----------- |
| `xray.crash` | 🔴 Red | Xray-core crashed; includes reason and timestamp |
| `outbound.down` | 🔴 Red | Outbound connectivity test failed |
| `outbound.up` | 🟢 Green | Outbound connectivity restored |
| `node.down` | 🔴 Red | Remote sub-node offline or unreachable |
| `node.up` | 🟢 Green | Remote sub-node reconnected and healthy |
| `cpu.high` | 🟠 Orange | Host CPU usage exceeded configured threshold (`discordCpu`) |
| `memory.high` | 🟠 Orange | Host memory usage exceeded configured threshold (`discordMemory`) |
| `login.attempt` | 🟢 / 🔴 | Web panel login attempt with username, IP, and status |
<Callout type="warn">
Login alerts report the attempted username and client IP address. Passwords are never logged or transmitted.
</Callout>
## Settings Reference
| Setting | Default | Description |
| ------- | ------- | ----------- |
| `discordBotEnable` | `false` | Master toggle for Discord bot and notifications. |
| `discordBotToken` | _(secret)_ | Discord Bot token from Developer Portal. |
| `discordChannelId` | _(none)_ | Target Discord channel snowflake ID (1720 digits). |
| `discordAdminIds` | _(none)_ | Comma-separated Discord user IDs allowed to run bot commands. Empty turns commands off. |
| `discordLang` | `en-US` | Language for Discord bot messages and reports. |
| `discordRunTime` | `@daily` | Cron expression or interval for periodic status reports. |
| `discordBotBackup` | `false` | Whether to attach database backup (`x-ui.db`) to reports. |
| `discordEnabledEvents` | `login.attempt,cpu.high` | Comma-separated list of enabled event types. |
| `discordCpu` | `80` | CPU utilization percentage threshold for alerts (0100). |
| `discordMemory` | `80` | RAM utilization percentage threshold for alerts (0100). |
## Troubleshooting
- **Test fails with "invalid bot token (401)"**: Verify that you copied the full Bot Token from the **Bot** tab in Developer Portal, not the Client Secret or Application ID.
- **Test fails with "missing permissions (403)"**: Ensure the bot role has **Send Messages**, **Embed Links**, and **Attach Files** permissions in the target channel or category.
- **Commands do not respond**: Check that your Discord user ID is listed in **Admin User IDs**. Then ensure **Message Content Intent** is enabled under the **Bot** tab in Discord Developer Portal and restart the panel: Discord closes the connection for good when the intent is missing, so the bot does not retry on its own.
- **Test fails with "channel not found (404)"**: Verify the numeric Channel ID. Ensure the bot is present in the server that owns the channel.
- **Proxying outbound requests**: If your host requires a proxy to connect to Discord, configure **Panel Outbound** in Panel Settings. Discord requests automatically route through the configured panel outbound proxy.
@@ -7,6 +7,7 @@
"outbounds-routing",
"backup-restore",
"telegram-bot",
"discord-bot",
"security"
]
}
@@ -227,7 +227,8 @@ _openapi:
title: Reset the recorded IP list for a client.
url: '#reset-the-recorded-ip-list-for-a-client'
- depth: 2
title: List registered HWID devices for a client with a short fingerprint. Full hashes are not exposed.
title: List registered HWID devices for a client with a short fingerprint. Full
hashes are not exposed.
url: '#list-registered-hwid-devices-for-a-client-with-a-short-fingerprint-full-hashes-are-not-exposed'
- depth: 2
title: Clear all registered HWID devices for a client so new devices can
@@ -481,7 +482,8 @@ _openapi:
id: list-source-ips-that-have-connected-with-the-given-clients-credentials-returns-an-array-of-ip-timestamp-strings
- content: Reset the recorded IP list for a client.
id: reset-the-recorded-ip-list-for-a-client
- content: List registered HWID devices for a client with a short fingerprint. Full hashes are not exposed.
- content: List registered HWID devices for a client with a short fingerprint.
Full hashes are not exposed.
id: list-registered-hwid-devices-for-a-client-with-a-short-fingerprint-full-hashes-are-not-exposed
- content: Clear all registered HWID devices for a client so new devices can
register again.
@@ -48,6 +48,10 @@ _openapi:
title: Test Telegram bot connection by sending a test message to the configured
chat.
url: '#test-telegram-bot-connection-by-sending-a-test-message-to-the-configured-chat'
- depth: 2
title: Test Discord bot connection by sending a test embed to the configured
channel.
url: '#test-discord-bot-connection-by-sending-a-test-embed-to-the-configured-channel'
- depth: 2
title: Return the built-in default Xray JSON config template that ships with
this panel version.
@@ -86,6 +90,9 @@ _openapi:
- content: Test Telegram bot connection by sending a test message to the
configured chat.
id: test-telegram-bot-connection-by-sending-a-test-message-to-the-configured-chat
- content: Test Discord bot connection by sending a test embed to the configured
channel.
id: test-discord-bot-connection-by-sending-a-test-embed-to-the-configured-channel
- content: Return the built-in default Xray JSON config template that ships with
this panel version.
id: return-the-built-in-default-xray-json-config-template-that-ships-with-this-panel-version
@@ -101,7 +108,7 @@ export default function Layout(props) {
return (
<>
{props.children}
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/setting/all","method":"post"},{"path":"/panel/api/setting/defaultSettings","method":"post"},{"path":"/panel/api/setting/factoryDefaults","method":"post"},{"path":"/panel/api/setting/update","method":"post"},{"path":"/panel/api/setting/validateRegex","method":"post"},{"path":"/panel/api/setting/updateUser","method":"post"},{"path":"/panel/api/setting/restartPanel","method":"post"},{"path":"/panel/api/setting/testSmtp","method":"post"},{"path":"/panel/api/setting/testTgBot","method":"post"},{"path":"/panel/api/setting/getDefaultJsonConfig","method":"get"}]} showTitle />
<Comp document="./public/openapi.json" webhooks={[]} operations={[{"path":"/panel/api/setting/all","method":"post"},{"path":"/panel/api/setting/defaultSettings","method":"post"},{"path":"/panel/api/setting/factoryDefaults","method":"post"},{"path":"/panel/api/setting/update","method":"post"},{"path":"/panel/api/setting/validateRegex","method":"post"},{"path":"/panel/api/setting/updateUser","method":"post"},{"path":"/panel/api/setting/restartPanel","method":"post"},{"path":"/panel/api/setting/testSmtp","method":"post"},{"path":"/panel/api/setting/testTgBot","method":"post"},{"path":"/panel/api/setting/testDiscord","method":"post"},{"path":"/panel/api/setting/getDefaultJsonConfig","method":"get"}]} showTitle />
</>
);
}
@@ -7,6 +7,7 @@
"outbounds-routing",
"backup-restore",
"telegram-bot",
"discord-bot",
"security"
]
}
+1
View File
@@ -67,6 +67,7 @@ icon: SlidersHorizontal
<Cards>
<Card title="Бот Telegram" href="/docs/operations/telegram-bot" description="Токен, идентификаторы чатов, оповещения и отчёты." />
<Card title="Discord-бот" href="/docs/operations/discord-bot" description="Токен, ID канала и оповещения о событиях." />
<Card title="Подписка" href="/docs/config/subscription" description="Сервер подписок, форматы и пути." />
<Card title="Безопасность" href="/docs/operations/security" description="2FA, ограничения по IP и усиление защиты." />
</Cards>
@@ -0,0 +1,121 @@
---
title: Discord-бот
description: Подключите Discord-бота к 3x-ui для получения оповещений о событиях панели (сбои сервисов, доступность узлов, нагрузка CPU/RAM и попытки входа) прямо в канал Discord.
icon: Bot
---
3x-ui предоставляет полную интеграцию с Discord: мгновенные уведомления о событиях через шину событий панели (`EventBus`), периодические отчёты о состоянии сервера с резервным копированием базы данных, а также интерактивные команды через Discord Gateway.
<Callout type="info">
Уведомления и периодические отчёты отправляются через исходящие HTTPS-запросы к REST API Discord v10. Интерактивные команды бота работают через постоянное защищённое WebSocket-соединение с Discord Gateway.
</Callout>
## Настройка
<Steps>
<Step>
### Создайте приложение и бота в Discord
1. Откройте [Discord Developer Portal](https://discord.com/developers/applications) и авторизуйтесь.
2. Нажмите **New Application** в правом верхнем углу, укажите имя (например, `3x-ui Notifier`) и подтвердите создание.
3. В боковом меню перейдите во вкладку **Bot**.
4. Нажмите **Reset Token** (или **Add Bot**, если бот ещё не создан) и скопируйте **Bot Token**. Сохраните токен в надёжном месте.
5. В блоке **Privileged Gateway Intents** включите переключатель **Message Content Intent** (необходимо, чтобы бот мог читать команды вида `!status`).
</Step>
<Step>
### Пригласите бота на свой сервер Discord
1. В Developer Portal перейдите в раздел **OAuth2** $\rightarrow$ **URL Generator**.
2. В блоке **Scopes** отметьте галочкой `bot`.
3. В блоке **Bot Permissions** выберите:
- **Send Messages** (Отправка сообщений)
- **Embed Links** (Встраивание ссылок / Embeds)
- **Attach Files** (Прикрепление файлов — необходимо для резервных копий БД)
- **Read Message History** (Чтение истории сообщений)
4. Скопируйте полученную ссылку внизу страницы, откройте её в браузере и добавьте бота на нужный сервер.
</Step>
<Step>
### Скопируйте ID канала (Channel ID)
1. В клиенте Discord включите режим разработчика: **Настройки пользователя** $\rightarrow$ **Расширенные** $\rightarrow$ **Режим разработчика** (Developer Mode).
2. Нажмите правой кнопкой мыши по каналу, куда должны приходить уведомления и команды, и выберите **Копировать ID канала**.
3. Убедитесь, что у бота есть права на просмотр и отправку сообщений в этот канал.
</Step>
<Step>
### Настройте панель 3x-ui
1. В веб-интерфейсе 3x-ui перейдите в **Настройки панели** $\rightarrow$ **Discord Bot** (или перейдите по адресу `/settings#discord`).
2. Во вкладке **Основные настройки**:
- Включите **Включить уведомления Discord**.
- Укажите **Токен Discord-бота** и **ID канала**.
- Укажите свой ID пользователя Discord в поле **ID администраторов** (правый клик по своему имени → **Копировать ID пользователя**; несколько ID разделяйте запятыми).
- Выберите **Язык Discord-бота**.
3. Во вкладке **Уведомления**:
- Настройте **Частоту уведомлений** (например, `@daily`, `@weekly` или произвольное выражение crontab).
- При необходимости включите **Резервное копирование базы данных**, чтобы отчёт сопровождался файлом `x-ui.db`.
- Выберите отслеживаемые события и настройте пороги нагрузки CPU/RAM.
4. Нажмите **Отправить тестовое сообщение**, чтобы проверить доставку. В канале Discord появится тестовое Embed-сообщение.
5. Нажмите **Сохранить** для применения настроек.
</Step>
</Steps>
## Команды бота
Когда бот включён, он принимает текстовые команды в настроенном канале (поддерживаются префиксы `!` и `/`). Выполнять их могут только пользователи из списка **ID администраторов**; сообщения остальных игнорируются, а при пустом списке команды отключены. `!backup` и плановые резервные копии публикуют базу данных в канал, поэтому выбирайте канал, доступный только администраторам:
| Команда | Описание |
| ------- | -------- |
| `!status` | Вывести нагрузку системы, память, процессор, число соединений и активных клиентов. |
| `!report` | Немедленно сгенерировать и отправить подробный отчёт о состоянии сервера. |
| `!backup` | Отправить файл резервной копии базы данных (`x-ui.db`) и `config.json`. |
| `!usage <email>` | Запросить статистику трафика (Upload/Download), лимит и срок действия клиента. |
| `!inbounds` | Показать список всех активных подключений (порты, протоколы, клиенты, трафик). |
| `!restart` | Перезапустить ядро Xray без перезапуска веб-панели. |
| `!help` | Показать справку по доступным командам. |
## Оповещения о событиях
Уведомления приходят в виде Embed-карточек с цветовым обозначением важности:
| Событие | Индикатор | Описание |
| ------- | --------- | -------- |
| `xray.crash` | 🔴 Красный | Сбой процесса Xray-core с указанием причины и времени |
| `outbound.down` | 🔴 Красный | Неудачная проверка доступности исходящего соединения (outbound) |
| `outbound.up` | 🟢 Зеленый | Восстановление доступности исходящего соединения |
| `node.down` | 🔴 Красный | Удалённый под-узел (node) отключился или недоступен |
| `node.up` | 🟢 Зеленый | Удалённый под-узел снова в сети и готов к работе |
| `cpu.high` | 🟠 Оранжевый | Нагрузка процессора превысила заданный порог (`discordCpu`) |
| `memory.high` | 🟠 Оранжевый | Использование оперативной памяти превысило порог (`discordMemory`) |
| `login.attempt` | 🟢 / 🔴 | Попытка авторизации в панели (с указанием IP и логина) |
<Callout type="warn">
Оповещения о входе содержат только введённое имя пользователя и IP-адрес. Пароли никогда не логируются и не передаются.
</Callout>
## Параметры конфигурации
| Параметр | По умолчанию | Описание |
| -------- | ------------ | -------- |
| `discordBotEnable` | `false` | Главный переключатель бота и уведомлений Discord. |
| `discordBotToken` | _(секрет)_ | Токен бота из Discord Developer Portal. |
| `discordChannelId` | _(пусто)_ | Идентификатор канала Discord (1720 цифр). |
| `discordAdminIds` | _(пусто)_ | ID пользователей Discord через запятую, которым разрешено выполнять команды бота. Пустой список отключает команды. |
| `discordLang` | `en-US` | Язык сообщений и отчётов бота. |
| `discordRunTime` | `@daily` | Расписание генерации периодических отчётов (crontab). |
| `discordBotBackup` | `false` | Отправлять ли файл резервной копии базы данных (`x-ui.db`) вместе с отчётом. |
| `discordEnabledEvents` | `login.attempt,cpu.high` | Список отслеживаемых событий через запятую. |
| `discordCpu` | `80` | Порог нагрузки процессора для алерта (в процентах, 0–100). |
| `discordMemory` | `80` | Порог использования RAM для алерта (в процентах, 0–100). |
## Устранение неполадок
- **Ошибка "invalid bot token (401)"**: Проверьте, что вы скопировали именно Bot Token из раздела **Bot**, а не Client Secret или Application ID.
- **Ошибка "missing permissions (403)"**: Проверьте, выданы ли роли бота права **Send Messages**, **Embed Links** и **Attach Files** в целевом канале или категории каналов.
- **Бот не реагирует на команды**: Проверьте, что ваш ID пользователя Discord указан в **ID администраторов**. Затем убедитесь, что в Discord Developer Portal в разделе **Bot** включен **Message Content Intent**, и перезапустите панель: без этого разрешения Discord окончательно закрывает соединение, и бот не переподключается сам.
- **Ошибка "channel not found (404)"**: Проверьте правильность числового Channel ID и убедитесь, что бот состоит на сервере, которому принадлежит канал.
- **Проксирование запросов**: Если сервер не имеет прямого доступа к серверам Discord, настройте исходящий прокси в **Настройках панели** (**Исходящий трафик панели** / `panelOutbound`). Запросы бота будут автоматически направляться через этот прокси.
@@ -7,6 +7,7 @@
"outbounds-routing",
"backup-restore",
"telegram-bot",
"discord-bot",
"security"
]
}
@@ -7,6 +7,7 @@
"outbounds-routing",
"backup-restore",
"telegram-bot",
"discord-bot",
"security"
]
}