| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- package sub
- import (
- "regexp"
- "strings"
- "github.com/gin-gonic/gin"
- )
- var happUserAgentRegex = regexp.MustCompile(`(?i)\bhapp\b`)
- // HappConfig holds all Happ client customization parameters.
- type HappConfig struct {
- AutoDetect bool
- ProviderId string
- NewUrl string
- FallbackUrl string
- SubInfoColor string
- SubInfoText string
- SubInfoButtonText string
- SubInfoButtonLink string
- SubExpire bool
- SubExpireButtonLink string
- NotificationExpire bool
- NoLimit bool
- AlwaysHwid bool
- TunMode string
- TunType string
- ExcludeRoutes string
- ExcludeApns bool
- ColorProfile string
- PingType string
- AutoConnect bool
- AutoConnectType string
- PerAppMode string
- PerAppList string
- }
- // IsHappClient checks if the client user-agent identifies as Happ.
- func IsHappClient(userAgent string) bool {
- return happUserAgentRegex.MatchString(userAgent)
- }
- // ApplyHappHeaders sets standard and advanced Happ subscription headers.
- func ApplyHappHeaders(c *gin.Context, cfg HappConfig, isHapp bool) {
- if c == nil || c.Writer == nil || !cfg.AutoDetect || !isHapp {
- return
- }
- if cfg.ProviderId != "" {
- c.Writer.Header().Set("ProviderID", cfg.ProviderId)
- }
- if cfg.NewUrl != "" {
- c.Writer.Header().Set("New-Url", cfg.NewUrl)
- }
- if cfg.FallbackUrl != "" {
- c.Writer.Header().Set("Fallback-Url", cfg.FallbackUrl)
- }
- if text := strings.TrimSpace(cfg.SubInfoText); text != "" {
- color := strings.TrimSpace(cfg.SubInfoColor)
- switch strings.ToLower(color) {
- case "primary", "info":
- color = "blue"
- case "success":
- color = "green"
- case "warning", "danger":
- color = "red"
- case "":
- color = "blue"
- }
- c.Writer.Header().Set("Sub-Info-Color", color)
- c.Writer.Header().Set("Sub-Info-Text", text)
- if btnText := strings.TrimSpace(cfg.SubInfoButtonText); btnText != "" {
- c.Writer.Header().Set("Sub-Info-Button-Text", btnText)
- }
- if btnLink := strings.TrimSpace(cfg.SubInfoButtonLink); btnLink != "" {
- c.Writer.Header().Set("Sub-Info-Button-Link", btnLink)
- }
- }
- if cfg.SubExpire {
- c.Writer.Header().Set("Sub-Expire", "1")
- if link := strings.TrimSpace(cfg.SubExpireButtonLink); link != "" {
- c.Writer.Header().Set("Sub-Expire-Button-Link", link)
- }
- }
- if cfg.NotificationExpire {
- c.Writer.Header().Set("Notification-Subs-Expire", "1")
- }
- if cfg.NoLimit {
- c.Writer.Header().Set("No-Limit-Enabled", "1")
- }
- if cfg.AlwaysHwid {
- c.Writer.Header().Set("Subscription-Always-Hwid-Enable", "1")
- }
- if cfg.TunMode != "" {
- c.Writer.Header().Set("Tun-Mode", cfg.TunMode)
- }
- if cfg.TunType != "" {
- c.Writer.Header().Set("Tun-Type", cfg.TunType)
- }
- if routes := strings.TrimSpace(cfg.ExcludeRoutes); routes != "" {
- c.Writer.Header().Set("Exclude-Routes", routes)
- }
- if cfg.ExcludeApns {
- c.Writer.Header().Set("Exclude-Apns-Enable", "true")
- }
- if profile := strings.TrimSpace(cfg.ColorProfile); profile != "" {
- profile = strings.ReplaceAll(strings.ReplaceAll(profile, "\r", ""), "\n", "")
- c.Writer.Header().Set("Color-Profile", profile)
- }
- if ping := strings.TrimSpace(cfg.PingType); ping != "" {
- if strings.EqualFold(ping, "http") {
- ping = "proxy"
- }
- c.Writer.Header().Set("Ping-Type", ping)
- }
- if cfg.AutoConnect {
- c.Writer.Header().Set("Subscription-Autoconnect", "1")
- autoType := strings.TrimSpace(cfg.AutoConnectType)
- switch strings.ToLower(autoType) {
- case "fastest":
- autoType = "lowestdelay"
- case "last":
- autoType = "lastused"
- }
- if autoType != "" {
- c.Writer.Header().Set("Subscription-Autoconnect-Type", autoType)
- }
- }
- if mode := strings.TrimSpace(cfg.PerAppMode); mode != "" && mode != "off" {
- switch strings.ToLower(mode) {
- case "include":
- mode = "on"
- case "exclude":
- mode = "bypass"
- }
- c.Writer.Header().Set("Per-App-Proxy-Mode", mode)
- if list := strings.TrimSpace(cfg.PerAppList); list != "" {
- c.Writer.Header().Set("Per-App-Proxy-List", list)
- }
- }
- }
|