feat(sub): add Happ client integration, routing presets, and app management (#6434)

* feat(sub): add Happ client integration, routing presets, and app management

Implement comprehensive Happ proxy client integration according to official developer specifications.

- Fix header emission on disabled routing and hidden settings to send explicit '0' headers rather than omitting, allowing Happ clients to reset cached settings.
- Add support for 'happ://routing/off' deeplink in routing validation.
- Preserve '?serverDescription=' query parameters in link fragments without escaping to support Happ server subtitles across VMess, VLESS, Trojan and SS.
- Add Happ application management headers: ProviderID, New-Url, Fallback-Url, Sub-Info banners, Sub-Expire notifications, No-Limit mode, hardware ID enforcement, TUN modes/types, route exclusions, APNS exclusions, and per-app proxy settings.
- Add curated routing presets (Iran Bypass, China Direct, AdBlock, Global) and interactive visual rule generator in frontend settings.
- Synchronize all 13 translation locales with native Persian, Russian, and Chinese translations.

* fix(sub): keep Happ header overrides behind the auto-detect opt-in

The Routing-Enable/Hide-Settings off values were emitted on the
User-Agent alone, so every panel that upgraded would push
"Routing-Enable: 0" — documented by happ.su as disabling routing
globally — to every Happ client without the operator enabling anything.
They now ride subHappAutoDetect like every other Happ header.

Two further mismatches against the vendor spec:

- serverDescription was written as a key of the VMess base64 JSON
  object. happ.su documents it as a "#Title?serverDescription=<base64>"
  link parameter or a JSON "meta" entry, so the caption never reached
  Happ while every other VMess consumer received an unknown key.
  Dropped rather than moved: emitting the documented form is unsafe
  here because our own parser base64-decodes the whole VMess body
  (internal/util/link/outbound.go).

- The TUN Mode dropdown stored the literal "default", forwarded as
  "Tun-Mode: default", where happ.su documents system|gvisor only. It
  now stores the unset value so no header is sent. TUN Type "default"
  is a documented value and is unchanged.

Each fix carries a test that fails without it.
This commit is contained in:
Pejman Yousefi
2026-09-10 17:16:12 +03:30
committed by GitHub
parent d5ab84e8d5
commit 1456658028
35 changed files with 3460 additions and 51 deletions
+93 -1
View File
@@ -1466,7 +1466,99 @@
"subExpiredTemplate": "Шаблон истекшей подписки",
"subExpiredTemplateDesc": "Шаблон для фиктивного узла, когда срок действия подписки истек.",
"subTrafficDepletedTemplate": "Шаблон исчерпания трафика",
"subTrafficDepletedTemplateDesc": "Шаблон для фиктивного узла, когда лимит трафика исчерпан."
"subTrafficDepletedTemplateDesc": "Шаблон для фиктивного узла, когда лимит трафика исчерпан.",
"subHappAutoDetect": "Автоопределение заголовков Happ",
"subHappAutoDetectDesc": "Автоматически добавлять заголовки и маршрутизацию для клиентов с User-Agent Happ.",
"subHappProviderId": "Идентификатор провайдера (Provider ID)",
"subHappProviderIdDesc": "Уникальный идентификатор для управления приложением, удаленной конфигурации и миграции.",
"subHappNewUrl": "Новый URL подписки (Миграция)",
"subHappNewUrlDesc": "Новый адрес подписки. При получении клиент Happ автоматически переключится на данный URL.",
"subHappFallbackUrl": "Резервный URL подписки (Fallback)",
"subHappFallbackUrlDesc": "Резервный адрес подписки на случай недоступности основного сервера.",
"subHappSubInfoText": "Текст информационного баннера",
"subHappSubInfoTextDesc": "Пользовательский баннер в верхней части приложения Happ (до 200 символов).",
"subHappSubInfoColor": "Цвет баннера",
"subHappSubInfoColorDesc": "Цветовая тема информационного блока: blue (синий), green (зеленый), red (красный).",
"subHappSubInfoButtonText": "Текст кнопки баннера",
"subHappSubInfoButtonTextDesc": "Название кнопки действия в информационном блоке (до 25 символов).",
"subHappSubInfoButtonLink": "Ссылка кнопки баннера",
"subHappSubInfoButtonLinkDesc": "URL-адрес, открывающийся при нажатии на кнопку баннера.",
"subHappSubExpire": "Баннер об окончании подписки",
"subHappSubExpireDesc": "Отображать баннер о скором окончании или истечении срока действия подписки.",
"subHappSubExpireButtonLink": "Ссылка для продления подписки",
"subHappSubExpireButtonLinkDesc": "URL для кнопки «Продлить» при истечении срока подписки.",
"subHappNotificationExpire": "Уведомление об окончании подписки",
"subHappNotificationExpireDesc": "Отправлять напоминания пользователю за 3 дня до окончания подписки.",
"subHappNoLimit": "Режим без ограничений (No Limit)",
"subHappNoLimitDesc": "Увеличивает лимит оперативной памяти и снимает ограничения на количество правил.",
"subHappAlwaysHwid": "Обязательный HWID",
"subHappAlwaysHwidDesc": "Запрещает пользователю отключать передачу идентификатора устройства (HWID).",
"subHappTunMode": "Режим TUN",
"subHappTunModeDesc": "Сетевой стек для TUN: system (системный) или gvisor (пользовательский стек).",
"subHappTunType": "Ядро туنнеля (TUN Type)",
"subHappTunTypeDesc": "Выбор ядра туннеля: singbox, tun2proxy, default (Happ TUN) или xray.",
"subHappExcludeRoutes": "Исключения маршрутов (CIDR)",
"subHappExcludeRoutesDesc": "Список подсетей и IP-адресов через запятую, трафик которых идет мимо туннеля.",
"subHappExcludeApns": "Исключить push-уведомления Apple (APNS)",
"subHappExcludeApnsDesc": "Трафик уведомлений Apple направляется напрямую для надежной доставки на iOS.",
"subHappColorProfile": "Цветовая тема клиента",
"subHappColorProfileDesc": "Тема оформления интерфейса Happ: violet, turquoise, cyberpunk или свой JSON.",
"subHappPingType": "Метод проверки пинга",
"subHappPingTypeDesc": "Тип проверки задержки: via Proxy (GET), via Proxy (HEAD), TCP или ICMP.",
"subHappAutoConnect": "Автоподключение при запуске",
"subHappAutoConnectDesc": "Автоматически подключаться к серверу при запуске приложения.",
"subHappAutoConnectType": "Критерий автоподключения",
"subHappAutoConnectTypeDesc": "Сервер для автоподключения: lowestdelay (наименьший пинг), lastused (последний) или random.",
"subHappPerAppMode": "Прокси для приложений (Android)",
"subHappPerAppModeDesc": "Режим раздельного туннелирования: off (выкл), on (только выбранные) или bypass (все кроме выбранных).",
"subHappPerAppList": "Пакеты приложений Android",
"subHappPerAppListDesc": "Список идентификаторов пакетов через запятую (например, org.telegram.messenger).",
"subHappPresetIran": "Обход сайтов Ирана (Iran Bypass)",
"subHappPresetChina": "Обход сайтов Китая (China Direct)",
"subHappPresetAdblock": "Блокировка рекламы (AdBlock)",
"subHappPresetGlobal": "Полный прокси (Global)",
"subHappPresetOff": "Отключить маршрутизацию (happ://routing/off)",
"subHappColorBlue": "Синий (стандартный / по умолчанию)",
"subHappColorGreen": "Зеленый (успех)",
"subHappColorRed": "Красный (предупреждение / опасность)",
"subHappTunModeDefault": "По умолчанию",
"subHappTunModeSystem": "Системный (стандартный стек ОС)",
"subHappTunModeGvisor": "gVisor (пользовательский стек)",
"subHappTunTypeSingbox": "sing-box",
"subHappTunTypeTun2proxy": "tun2proxy",
"subHappTunTypeDefault": "По умолчанию (Happ TUN)",
"subHappTunTypeXray": "Xray TUN",
"subHappPingProxy": "Через прокси (задержка GET)",
"subHappPingProxyHead": "Через прокси (задержка HEAD)",
"subHappPingTcp": "TCP-рукопожатие (пинг)",
"subHappPingIcmp": "ICMP-пинг",
"subHappAutoConnectLowestDelay": "Минимальная задержка (быстрый узел)",
"subHappAutoConnectLastUsed": "Последний использованный узел",
"subHappAutoConnectRandom": "Случайный узел",
"subHappPerAppOff": "Выкл",
"subHappPerAppOn": "Вкл (только выбранные приложения)",
"subHappPerAppBypass": "Обход (исключить выбранные приложения)",
"subHappPresetApplied": "Пресет маршрутизации Happ успешно применен",
"subHappPresets": "Пресеты маршрутизации",
"subHappPresetsDesc": "Готовые конфигурации маршрутизации для клиентов Happ.",
"subHappVisualBuilder": "Визуальный конструктор правил",
"subHappVisualBuilderDesc": "Генератор диплинков маршрутизации на основе списков доменов и IP.",
"subHappBuildDeeplink": "Сгенерировать диплинк",
"subHappModalTitle": "Визуальный конструктор правил маршрутизации Happ",
"subHappDirectDomains": "Прямые домены (Direct)",
"subHappProxyDomains": "Проксируемые домены (Proxy)",
"subHappBlockDomains": "Заблокированные домены (Block)",
"subHappDirectIPs": "Прямые IP / CIDR",
"subHappProxyIPs": "Проксируемые IP / CIDR",
"subHappBlockIPs": "Заблокированные IP / CIDR",
"subHappDeeplinkGenerated": "Диплинк сгенерирован и применен к правилам маршрутизации",
"subHappGroupRouting": "Маршрутизация и правила",
"subHappGroupBanners": "Баннеры и уведомления",
"subHappGroupNetwork": "Сетевые настройки и TUN",
"subHappGroupThemes": "Внешний вид и темы",
"subHappGroupFailover": "Миграция и управление",
"subHappGroupAndroid": "Прокси приложений Android"
},
"xray": {
"importRules": "Импорт правил",