Лёгкий Python-бот, который периодически читает виджет с breaking.proxy.sqstat.ru,
извлекает данные по двум карточкам (RAAS/AAS и SPEC OPS) и обновляет одно
сообщение в Discord-канале.
- открывает страницу источника и дожидается появления нужных карточек;
- извлекает онлайн и название карты для
RAAS/AASиSPEC OPS; - отправляет служебное сообщение один раз и дальше редактирует его;
- показывает время последнего успешного обращения к сайту в footer embeds;
- обновляет содержимое сразу при изменении состояния серверов;
- поддерживает heartbeat-обновление виджета, даже если состояние не изменилось;
- хранит
message_idи последнее успешное состояние в JSON-файле; - пишет короткие и стабильные логи с таймингами этапов.
Текущая логика оптимизирована под меньшую нагрузку на CPU, RAM и Discord API:
- базовая частота опроса:
30секунд; - если состояние серверов изменилось — сообщение в Discord обновляется сразу;
- если состояние не изменилось — сообщение не редактируется на каждом цикле;
- при этом heartbeat сохраняется: footer с временем последнего успешного запроса
обновляется периодически, по умолчанию раз в
900секунд; - при повторяющихся ошибках включается простой backoff до заданного предела;
- Playwright переиспользует браузерный контекст и страницу;
- отключаются лишние ресурсы браузера (например, изображения, шрифты, трекеры), чтобы снизить нагрузку.
- Python 3.11+
discord.pyplaywrightpython-dotenv
.
├── bot/
│ ├── config.py # конфигурация из env/config.json
│ ├── embeds.py # формирование Discord embeds
│ ├── models.py # модели данных
│ ├── parser.py # парсер HTML-карточек
│ ├── state.py # JSON-хранилище состояния
│ └── widget_updater.py # цикл обновления и редактирование сообщения
├── main.py # точка входа
├── requirements.txt
├── .env.example # пример env-конфига
├── config.json # альтернативный конфиг (не обязателен)
└── state.json # файл состояния (можно переопределить через STATE_FILE)
-
Создайте виртуальное окружение и активируйте его:
python -m venv .venv source .venv/bin/activate -
Установите зависимости:
pip install -r requirements.txt
-
Установите браузер для Playwright:
python -m playwright install chromium
-
Настройте конфиг одним из двух способов:
Вариант A — через
.env:cp .env.example .env
После этого заполните минимум:
DISCORD_TOKENCHANNEL_ID
Вариант B — через
config.json:- создайте файл
config.jsonв корне проекта; - используйте пример из раздела ниже.
-
Запустите бота:
python main.py
Бот поддерживает два источника конфигурации:
- переменные окружения (
.env); config.jsonв корне проекта.
Если значение задано и в .env, и в config.json, используется значение из переменной окружения.
| Переменная | Обязательна | По умолчанию | Описание |
|---|---|---|---|
DISCORD_TOKEN |
✅ | — | токен Discord-бота |
CHANNEL_ID |
✅ | — | ID канала для виджета |
UPDATE_INTERVAL_SECONDS |
❌ | 30 |
базовый интервал опроса сайта, сек |
HEARTBEAT_EDIT_INTERVAL_SECONDS |
❌ | 900 |
как часто обновлять heartbeat в Discord, если данные не изменились |
MAX_BACKOFF_SECONDS |
❌ | 300 |
верхний предел backoff при повторных ошибках |
PARSER_TIMEOUT_SECONDS |
❌ | 20 |
timeout парсера/страницы |
BASE_URL |
❌ | https://breaking.proxy.sqstat.ru |
URL источника данных |
STATE_FILE |
❌ | state.json |
путь к JSON-файлу состояния |
LOG_LEVEL |
❌ | INFO |
уровень логирования (DEBUG, INFO, WARNING, ERROR) |
{
"DISCORD_TOKEN": "your_discord_bot_token",
"CHANNEL_ID": "123456789012345678",
"UPDATE_INTERVAL_SECONDS": 30,
"HEARTBEAT_EDIT_INTERVAL_SECONDS": 900,
"MAX_BACKOFF_SECONDS": 300,
"PARSER_TIMEOUT_SECONDS": 20,
"BASE_URL": "https://breaking.proxy.sqstat.ru",
"STATE_FILE": "state.json",
"LOG_LEVEL": "INFO"
}Сообщение в Discord обновляется немедленно, если изменились:
- онлайн;
- карта;
- изображение карты;
- или если нужно пересоздать сообщение.
Если состояние серверов не изменилось, бот всё равно периодически обновляет embeds, чтобы в footer было видно актуальное время последнего успешного обращения к сайту.
Это позволяет быстро понять:
- бот жив;
- сайт доступен;
- парсинг проходит успешно.
Логи сделаны в коротком и стабильном формате:
12:30:18 | I | __main__ | Logged in as MyBot#1234 | update_interval_seconds=30 | heartbeat_edit_interval_seconds=900 | max_backoff_seconds=300
12:30:19 | I | bot.parser | Fetched 2 eligible server cards | goto_ms=842 | wait_ms=126 | eval_ms=19 | total_ms=1002
12:30:19 | I | bot.widget_updater | Widget published | reason=state-changed | fetch_ms=1015 | publish_ms=488 | persist_ms=1 | state_saved=True
12:30:49 | I | bot.widget_updater | Widget heartbeat skipped: data unchanged and heartbeat not due | fetch_ms=934
Что важно:
- время в формате
HH:MM:SS; - уровень логирования — одной буквой (
D/I/W/E); - логируются тайминги чтения страницы, публикации и сохранения состояния;
- heartbeat и реальное изменение данных различаются отдельными сообщениями.
По умолчанию бот использует state.json.
В нём хранятся:
channel_idmessage_id- последнее успешное состояние серверов
- время последнего успешного обращения к сайту
Файл записывается только при изменении состояния, чтобы уменьшить лишний I/O.
- недоступность сайта или ошибка Playwright: ошибка логируется, цикл продолжается;
- при серии ошибок включается backoff до
MAX_BACKOFF_SECONDS; - пустой snapshot не публикуется поверх последнего нормального состояния;
- если
message_idбольше не существует, создаётся новое сообщение; - если канал недоступен или не является текстовым — бот завершится с ошибкой.
Если у тебя есть локальные debug-файлы HTML, их можно использовать для анализа DOM и подстройки селекторов/парсинга без запуска полного цикла обновлений.
При необходимости можно удалить state.json, чтобы сбросить сохранённый message_id
и заставить бота создать новое сообщение.
Примерный порядок для VPS/хостинга:
-
Установить Python 3.11+.
-
Загрузить проект.
-
Установить зависимости:
pip install -r requirements.txt
-
Установить Chromium для Playwright:
python -m playwright install chromium
-
Создать
.envилиconfig.json. -
Убедиться, что
STATE_FILEдоступен для записи. -
Запустить:
python main.py
Укажи нужную лицензию перед публикацией, если репозиторий будет использоваться публично.