|
@@ -4,6 +4,7 @@ import (
|
|
|
"encoding/base64"
|
|
"encoding/base64"
|
|
|
"fmt"
|
|
"fmt"
|
|
|
"strings"
|
|
"strings"
|
|
|
|
|
+ "strconv"
|
|
|
|
|
|
|
|
"github.com/mhsanaei/3x-ui/v2/config"
|
|
"github.com/mhsanaei/3x-ui/v2/config"
|
|
|
|
|
|
|
@@ -12,12 +13,17 @@ import (
|
|
|
|
|
|
|
|
// SUBController handles HTTP requests for subscription links and JSON configurations.
|
|
// SUBController handles HTTP requests for subscription links and JSON configurations.
|
|
|
type SUBController struct {
|
|
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
|
|
subService *SubService
|
|
|
subJsonService *SubJsonService
|
|
subJsonService *SubJsonService
|
|
@@ -38,18 +44,28 @@ func NewSUBController(
|
|
|
jsonMux string,
|
|
jsonMux string,
|
|
|
jsonRules string,
|
|
jsonRules string,
|
|
|
subTitle string,
|
|
subTitle string,
|
|
|
|
|
+ subSupportUrl string,
|
|
|
|
|
+ subProfileUrl string,
|
|
|
|
|
+ subAnnounce string,
|
|
|
|
|
+ subEnableRouting bool,
|
|
|
|
|
+ subRoutingRules string,
|
|
|
) *SUBController {
|
|
) *SUBController {
|
|
|
sub := NewSubService(showInfo, rModel)
|
|
sub := NewSubService(showInfo, rModel)
|
|
|
a := &SUBController{
|
|
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)
|
|
a.initRouter(g)
|
|
|
return a
|
|
return a
|
|
@@ -127,7 +143,7 @@ func (a *SUBController) subs(c *gin.Context) {
|
|
|
|
|
|
|
|
// Add headers
|
|
// Add headers
|
|
|
header := fmt.Sprintf("upload=%d; download=%d; total=%d; expire=%d", traffic.Up, traffic.Down, traffic.Total, traffic.ExpiryTime/1000)
|
|
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 {
|
|
if a.subEncrypt {
|
|
|
c.String(200, base64.StdEncoding.EncodeToString([]byte(result)))
|
|
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 {
|
|
if err != nil || len(jsonSub) == 0 {
|
|
|
c.String(400, "Error!")
|
|
c.String(400, "Error!")
|
|
|
} else {
|
|
} else {
|
|
|
-
|
|
|
|
|
// Add headers
|
|
// 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)
|
|
c.String(200, jsonSub)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ApplyCommonHeaders sets common HTTP headers for subscription responses including user info, update interval, and profile title.
|
|
// 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("Subscription-Userinfo", header)
|
|
|
c.Writer.Header().Set("Profile-Update-Interval", updateInterval)
|
|
c.Writer.Header().Set("Profile-Update-Interval", updateInterval)
|
|
|
c.Writer.Header().Set("Profile-Title", "base64:"+base64.StdEncoding.EncodeToString([]byte(profileTitle)))
|
|
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)
|
|
|
}
|
|
}
|