diff options
| author | Danil S. <135337715+sh1shd@users.noreply.github.com> | 2026-01-27 01:06:01 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-27 01:06:01 +0300 |
| commit | fd5f5917378129d7a555a246d42a2a572476b948 (patch) | |
| tree | f155bce5721c3d52840548192e3c683bbd193451 /sub | |
| parent | 8a4c9a98cbf8efce7c2efd1e3daa4c996830b30c (diff) | |
feat: more subscription information fields (#3701)
* feat: more subscription information fields
* fix: incorrect translation
* feat: implement field for Happ custom routing rules
Diffstat (limited to 'sub')
| -rw-r--r-- | sub/sub.go | 28 | ||||
| -rw-r--r-- | sub/subController.go | 68 |
2 files changed, 76 insertions, 20 deletions
@@ -153,6 +153,31 @@ func (s *Server) initRouter() (*gin.Engine, error) { SubTitle = "" } + SubSupportUrl, err := s.settingService.GetSubSupportUrl() + if err != nil { + SubSupportUrl = "" + } + + SubProfileUrl, err := s.settingService.GetSubProfileUrl() + if err != nil { + SubProfileUrl = "" + } + + SubAnnounce, err := s.settingService.GetSubAnnounce() + if err != nil { + SubAnnounce = "" + } + + SubEnableRouting, err := s.settingService.GetSubEnableRouting() + if err != nil { + return nil, err + } + + SubRoutingRules, err := s.settingService.GetSubRoutingRules() + if err != nil { + SubRoutingRules = "" + } + // set per-request localizer from headers/cookies engine.Use(locale.LocalizerMiddleware()) @@ -231,7 +256,8 @@ func (s *Server) initRouter() (*gin.Engine, error) { s.sub = NewSUBController( g, LinksPath, JsonPath, subJsonEnable, Encrypt, ShowInfo, RemarkModel, SubUpdates, - SubJsonFragment, SubJsonNoises, SubJsonMux, SubJsonRules, SubTitle) + SubJsonFragment, SubJsonNoises, SubJsonMux, SubJsonRules, SubTitle, SubSupportUrl, + SubProfileUrl, SubAnnounce, SubEnableRouting, SubRoutingRules) return engine, nil } diff --git a/sub/subController.go b/sub/subController.go index ec574d6e..7653a4e1 100644 --- a/sub/subController.go +++ b/sub/subController.go @@ -4,6 +4,7 @@ import ( "encoding/base64" "fmt" "strings" + "strconv" "github.com/mhsanaei/3x-ui/v2/config" @@ -12,12 +13,17 @@ import ( // SUBController handles HTTP requests for subscription links and JSON configurations. type SUBController struct { - subTitle string - subPath string - subJsonPath string - jsonEnabled bool - subEncrypt bool - updateInterval string + subTitle string + subSupportUrl string + subProfileUrl string + subAnnounce string + subEnableRouting bool + subRoutingRules string + subPath string + subJsonPath string + jsonEnabled bool + subEncrypt bool + updateInterval string subService *SubService subJsonService *SubJsonService @@ -38,18 +44,28 @@ func NewSUBController( jsonMux string, jsonRules string, subTitle string, + subSupportUrl string, + subProfileUrl string, + subAnnounce string, + subEnableRouting bool, + subRoutingRules string, ) *SUBController { sub := NewSubService(showInfo, rModel) a := &SUBController{ - subTitle: subTitle, - subPath: subPath, - subJsonPath: jsonPath, - jsonEnabled: jsonEnabled, - subEncrypt: encrypt, - updateInterval: update, - - subService: sub, - subJsonService: NewSubJsonService(jsonFragment, jsonNoise, jsonMux, jsonRules, sub), + subTitle: subTitle, + subSupportUrl: subSupportUrl, + subProfileUrl: subProfileUrl, + subAnnounce: subAnnounce, + subEnableRouting: subEnableRouting, + subRoutingRules: subRoutingRules, + subPath: subPath, + subJsonPath: jsonPath, + jsonEnabled: jsonEnabled, + subEncrypt: encrypt, + updateInterval: update, + + subService: sub, + subJsonService: NewSubJsonService(jsonFragment, jsonNoise, jsonMux, jsonRules, sub), } a.initRouter(g) return a @@ -127,7 +143,7 @@ func (a *SUBController) subs(c *gin.Context) { // Add headers header := fmt.Sprintf("upload=%d; download=%d; total=%d; expire=%d", traffic.Up, traffic.Down, traffic.Total, traffic.ExpiryTime/1000) - a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle) + a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle, a.subSupportUrl, a.subProfileUrl, a.subAnnounce, a.subEnableRouting, a.subRoutingRules) if a.subEncrypt { c.String(200, base64.StdEncoding.EncodeToString([]byte(result))) @@ -145,17 +161,31 @@ func (a *SUBController) subJsons(c *gin.Context) { if err != nil || len(jsonSub) == 0 { c.String(400, "Error!") } else { - // Add headers - a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle) + a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle, a.subSupportUrl, a.subProfileUrl, a.subAnnounce, a.subEnableRouting, a.subRoutingRules) c.String(200, jsonSub) } } // ApplyCommonHeaders sets common HTTP headers for subscription responses including user info, update interval, and profile title. -func (a *SUBController) ApplyCommonHeaders(c *gin.Context, header, updateInterval, profileTitle string) { +func (a *SUBController) ApplyCommonHeaders( + c *gin.Context, + header, + updateInterval, + profileTitle string, + profileSupportUrl string, + profileUrl string, + profileAnnounce string, + profileEnableRouting bool, + profileRoutingRules string, +) { c.Writer.Header().Set("Subscription-Userinfo", header) c.Writer.Header().Set("Profile-Update-Interval", updateInterval) c.Writer.Header().Set("Profile-Title", "base64:"+base64.StdEncoding.EncodeToString([]byte(profileTitle))) + c.Writer.Header().Set("Support-Url", profileSupportUrl) + c.Writer.Header().Set("Profile-Web-Page-Url", profileUrl) + c.Writer.Header().Set("Announce", "base64:"+base64.StdEncoding.EncodeToString([]byte(profileAnnounce))) + c.Writer.Header().Set("Routing-Enable", strconv.FormatBool(profileEnableRouting)) + c.Writer.Header().Set("Routing", profileRoutingRules) } |
