Для провайдеров: метаданные подписки
Приложение получает серверы и метаданные напрямую от URL подписки. Возвращайте заголовки вместе с успешным ответом со списком серверов. Не заменяйте тело HTML-страницей кабинета или ошибкой авторизации с кодом 200.
Основные поля
| Заголовок | Назначение |
|---|---|
Profile-Title | Название подписки: текст или base64: + Base64 UTF-8 |
Profile-Web-Page-URL | Ссылка на сайт/кабинет провайдера |
Profile-Web-Page-Title | Подпись вместо «Сайт провайдера»; не требует premium |
Support-URL | Ссылка поддержки |
Profile-Update-Interval | Интервал обновления подписки в часах |
Profile-Buttons | JSON-массив кнопок с text и url |
Profile-Theme / Qmesh-Theme | Одна тема или массив тем на выбор пользователя |
Routing | Поддерживаемый профиль маршрутизации Happ |
Profile-Geosite-URL / Qmesh-Geosite-URL | Прямой HTTPS URL базы GeoSite |
Profile-Geoip-URL / Qmesh-Geoip-URL | Прямой HTTPS URL базы GeoIP |
Имена HTTP-заголовков нечувствительны к регистру. Для не-ASCII значений используйте предусмотренное конкретным полем кодирование: кириллица в произвольном HTTP-заголовке может исказиться на прокси.
Кнопки
Profile-Buttons: [{"text":"Account","url":"https://provider.example/account"},{"text":"Support","url":"https://provider.example/support"}]Для кириллицы можно передать base64: от JSON в UTF-8. Поддерживаются до шести разных кнопок, подпись 1–64 символа, абсолютный HTTP/HTTPS URL без логина/пароля. Необязательные поля: variant (outline, filled, text), width (auto, full или число), icon (external, support, account, payment, none). Кнопка открывает ссылку только по нажатию пользователя.
Несколько тем
Значение Profile-Theme — JSON-объект или массив объектов. Для массива кодируйте весь JSON один раз, не отдельные темы. Пример можно скачать как provider-themes.json.
import base64
import json
from pathlib import Path
themes = json.loads(Path("provider-themes.json").read_text(encoding="utf-8"))
header = "base64:" + base64.b64encode(
json.dumps(themes, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
).decode("ascii")
# Возвратить header в Profile-Theme.Пользователь видит превью и подтверждает применение. Некорректные элементы пропускаются; идентификаторы тем должны быть уникальными. Поддерживается до 20 элементов. Заголовок ограничен 64 KiB, декодированный JSON — 48 KiB, отдельная тема — 8 KiB. Не передавайте в теме секреты.
Маршрутизация и геобазы
В заголовке Routing передавайте qmesh://routing/onadd/<Base64 JSON>, qmesh://routing/add/<Base64 JSON> или qmesh://routing/off.
onaddдобавляет профиль и включает его для этой подписки.addдобавляет профиль без автоматического включения; пользователь может включить его в настройках подписки.offотключает профиль, сохраняя его параметры.
<Base64 JSON> — закодированный в Base64 UTF-8 JSON-объект профиля. Внутри профиля источники баз задаются Geositeurl и Geoipurl, а группы правил — BlockSites, BlockIp, DirectSites, DirectIp, ProxySites и ProxyIp.
Отдельные geo-заголовки имеют приоритет над профилем Happ и локальными источниками. Файлы автоматически скачиваются после добавления или обновления подписки, даже без ссылок на категории в текущих правилах. Повторное получение заголовка обновляет файл; подготовка подключения повторяет загрузку, если актуального файла нет. Возвращайте совместимые полные .dat по HTTPS; не HTML-страницы и не ссылки, требующие браузерной сессии.
Группы и описания
Элемент подписки с хостом group отображается заголовком группы и не выбирается для подключения. Порядок серверов берётся из подписки. Описание сервера отображается рядом с его названием, поэтому используйте его для кратких пояснений, а не для секретных данных.
User-Agent и устройство
Основной User-Agent содержит версию Qmesh и ОС. При совместимом повторном запросе используется Happ/Qmesh <version>. Не привязывайте ответ только к точному номеру версии.
В запросе подписки передаётся X-Hwid: SHA-256 от префикса Qmesh, ОС и системного идентификатора. Это непрозрачная строка из 64 строчных hex-символов, а не исходный ID. Предусмотрите сброс привязки при переустановке/смене устройства. Если native ID недоступен, заголовка может не быть.
Проверка перед публикацией
Проверьте импорт новой подписки, обновление существующей, отсутствие/удаление метаданных, недоступность внешних файлов и отображение на узком экране. Оформление и дополнительные объявления premium не должны мешать базовому подключению.