Отправка Discord-вебхуков из Roblox (HttpService + прокси)
Как отправлять сообщения в Discord через вебхук из игры Roblox с помощью HttpService. Блокировка IP Roblox, прокси для вебхуков, embed-сообщения и лимиты — с примерами на Lua.
🇬🇧 Доступно также на English
Зачем отправлять Discord-вебхуки из Roblox?
Разработчики Roblox используют вебхуки Discord, чтобы логировать игровые события в канал Discord: входы игроков, покупки, команды админов, срабатывания анти-чита, отчёты об ошибках и аналитику. Вебхук превращает ваш сервер Discord в дашборд игры в реальном времени — без написания собственного бэкенда.
В этом руководстве показано, как отправлять сообщения из серверного Script через HttpService, почему прямые запросы падают на боевых серверах и как это починить с помощью прокси. Все примеры — обычный Lua, который можно вставить в серверный скрипт.
Шаг 1: Включите HTTP-запросы
Roblox по умолчанию блокирует исходящий HTTP. Включите его один раз для игры:
- Откройте игру в Roblox Studio
- Перейдите в Home → Game Settings → Security
- Включите Allow HTTP Requests
- Сохраните и опубликуйте
Без этого каждый запрос выбросит ошибку Http requests are not enabled.
Шаг 2: Получите URL вебхука Discord
В Discord: Настройки сервера → Интеграции → Вебхуки → Новый вебхук, выберите канал и нажмите Копировать URL вебхука. Он выглядит так:
https://discord.com/api/webhooks/123456789012345678/AbCdEf-gHiJkLmNoPqRsTuVwXyZ
Если вы новичок в вебхуках, сначала прочитайте руководство по настройке вебхука Discord.
Предупреждение о безопасности: URL вебхука — это секрет. Любой, у кого он есть, может писать в ваш канал. Используйте его только в серверных
Script(внутриServerScriptService), никогда вLocalScript— иначе читеры его украдут. См. безопасность вебхуков.
Шаг 3: Блокировка IP Roblox (важно)
Если отправить запрос напрямую на discord.com из опубликованной игры, вы получите ошибку вроде Http 403 (Forbidden). Discord блокирует диапазоны IP дата-центров, на которых работают серверы Roblox, чтобы бороться со злоупотреблениями.
- В Studio запросы идут с вашего домашнего IP, поэтому прямые вызовы работают — это сбивает с толку многих разработчиков, которые думают, что код в порядке.
- На боевых серверах тот же код падает.
Решение — прокси для вебхуков: небольшой сервис, который принимает ваш запрос и пересылает его в Discord с разрешённого IP.
Шаг 4a: Прямой запрос (только для тестов в Studio)
Это работает в Studio, чтобы проверить payload, но в продакшене падёт:
local HttpService = game:GetService("HttpService")
local WEBHOOK_URL = "https://discord.com/api/webhooks/ID/TOKEN"
local data = {
content = "Привет из Roblox!",
username = "Game Logger",
}
local success, err = pcall(function()
HttpService:PostAsync(WEBHOOK_URL, HttpService:JSONEncode(data))
end)
if not success then
warn("Вебхук упал: " .. tostring(err))
end
JSONEncode превращает таблицу Lua в JSON-тело, которое ожидает Discord, а pcall не даёт упавшему запросу обрушить скрипт.
Шаг 4b: Через прокси (продакшен)
Прокси принимает ваше сообщение и ретранслирует его в Discord с незаблокированного IP. Можно поднять свой, использовать публичный или relay-эндпоинт discord-webhook.com, который пересылает payload на стороне сервера:
local HttpService = game:GetService("HttpService")
-- Настоящий URL вебхука остаётся только на сервере
local WEBHOOK_URL = "https://discord.com/api/webhooks/ID/TOKEN"
local PROXY_URL = "https://discord-webhook.com/api/webhook/send"
local function sendToDiscord(payload)
local body = HttpService:JSONEncode({
webhookUrl = WEBHOOK_URL,
payload = payload,
})
local success, result = pcall(function()
return HttpService:PostAsync(
PROXY_URL,
body,
Enum.HttpContentType.ApplicationJson
)
end)
if not success then
warn("Прокси Discord упал: " .. tostring(result))
end
return success
end
sendToDiscord({
content = "Игрок только что зашёл в игру.",
username = "Game Logger",
})
Relay ожидает JSON-объект с двумя ключами: webhookUrl (ваш вебхук Discord) и payload (обычный объект сообщения Discord — content, embeds, username, avatar_url и т. д.). Он проверяет URL, пересылает сообщение и возвращает { "success": true, "messageId": "..." }.
Почему прокси, а не любой публичный? Некоторые публичные прокси для Roblox отключаются без предупреждения или логируют ваши payload. Какой бы прокси вы ни выбрали, относитесь к его URL как к ретранслятору и держите настоящий URL вебхука на сервере.
Шаг 5: Отправьте embed-сообщение
Простой текст подходит для быстрых логов, но embed даёт заголовки, цвета, поля и миниатюры. Соберите embed как вложенную таблицу Lua:
local function logPlayerJoin(player)
sendToDiscord({
embeds = {
{
title = "Игрок зашёл",
color = 5763719, -- зелёный, десятичная форма #57F287
fields = {
{ name = "Никнейм", value = player.Name, inline = true },
{ name = "User ID", value = tostring(player.UserId), inline = true },
{ name = "Возраст аккаунта", value = player.AccountAge .. " дн.", inline = true },
},
thumbnail = {
url = "https://www.roblox.com/headshot-thumbnail/image?userId="
.. player.UserId .. "&width=420&height=420&format=png",
},
footer = { text = "Лог игры" },
},
},
})
end
game.Players.PlayerAdded:Connect(logPlayerJoin)
Цвета embed в Discord — это десятичные числа, а не hex-строки: #57F287 превращается в 5763719. В справочнике цветов embed перечислены частые десятичные значения, либо соберите весь embed визуально в конструкторе вебхуков и скопируйте значения полей в таблицу Lua.
Шаг 6: Соблюдайте лимиты
Действуют два отдельных лимита:
- Discord: около 30 запросов в минуту на один вебхук. При превышении Discord возвращает
429с заголовкомRetry-After. См. объяснение лимитов. - Roblox:
HttpServiceразрешает примерно 500 запросов в минуту на сервер игры по всем эндпоинтам.
Для нагруженной игры группируйте события вместо одного вебхука на действие. Складывайте сообщения в очередь и отправляйте по таймеру:
local queue = {}
local function enqueue(line)
table.insert(queue, line)
end
task.spawn(function()
while true do
task.wait(10) -- отправка каждые 10 секунд
if #queue > 0 then
local batch = table.concat(queue, "\n")
queue = {}
sendToDiscord({ content = string.sub(batch, 1, 2000) })
end
end
end)
Discord ограничивает content 2000 символами, поэтому string.sub не даёт большому батчу вызвать ошибку 400.
Частые сценарии
- Логи покупок — вызывайте вебхук внутри
ProcessReceipt, чтобы фиксировать траты Robux. - Действия админов — логируйте баны, кики и команды с именем модератора.
- Алерты анти-чита — отправляйте красный embed при срабатывании детекта.
- Отчёты об ошибках — оборачивайте рискованный код в
pcallи пересылайте текст ошибки. - Онлайн в реальном времени — отправляйте статус-embed по таймеру, чтобы команда видела онлайн.
Решение проблем
| Симптом | Причина и решение |
|---|---|
Http requests are not enabled | Включите Allow HTTP Requests в Game Settings → Security. |
| Работает в Studio, падает после публикации | Блокировка IP Roblox — переходите на прокси (Шаг 4b). |
HTTP 400 | Некорректный JSON или контент длиннее 2000 символов / превышены лимиты embed. См. гайд по ошибкам. |
HTTP 401 / 404 | Вебхук удалён или токен пересоздан — скопируйте свежий URL. |
HTTP 429 | Рейт-лимит — группируйте сообщения и снижайте частоту. |
Что дальше
Теперь вы можете логировать любое игровое событие в Discord прямо из Roblox. Соберите embed визуально в бесплатном конструкторе вебхуков и перенесите структуру в таблицы Lua. Больше паттернов — в гайде по автоматизации и уведомлениям и руководстве по форматированию embed.
Похожие статьи
- Настройка вебхука Discord — полное руководство за 2 минуты — Создайте свой первый URL вебхука
- Безопасность вебхуков Discord — утечки токенов, ротация, защита — Защитите URL от читеров
- Лимиты вебхуков Discord — Обработка 429 и группировка
- Полное руководство по форматированию embed в Discord — Создавайте красивые embed
Попробуйте в нашем инструменте
Открыть конструктор Discord Webhook