subController.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package sub
  2. import (
  3. "encoding/base64"
  4. "fmt"
  5. "strings"
  6. "x-ui/config"
  7. "github.com/gin-gonic/gin"
  8. )
  9. type SUBController struct {
  10. subTitle string
  11. subPath string
  12. subJsonPath string
  13. jsonEnabled bool
  14. subEncrypt bool
  15. updateInterval string
  16. subService *SubService
  17. subJsonService *SubJsonService
  18. }
  19. func NewSUBController(
  20. g *gin.RouterGroup,
  21. subPath string,
  22. jsonPath string,
  23. jsonEnabled bool,
  24. encrypt bool,
  25. showInfo bool,
  26. rModel string,
  27. update string,
  28. jsonFragment string,
  29. jsonNoise string,
  30. jsonMux string,
  31. jsonRules string,
  32. subTitle string,
  33. ) *SUBController {
  34. sub := NewSubService(showInfo, rModel)
  35. a := &SUBController{
  36. subTitle: subTitle,
  37. subPath: subPath,
  38. subJsonPath: jsonPath,
  39. jsonEnabled: jsonEnabled,
  40. subEncrypt: encrypt,
  41. updateInterval: update,
  42. subService: sub,
  43. subJsonService: NewSubJsonService(jsonFragment, jsonNoise, jsonMux, jsonRules, sub),
  44. }
  45. a.initRouter(g)
  46. return a
  47. }
  48. func (a *SUBController) initRouter(g *gin.RouterGroup) {
  49. gLink := g.Group(a.subPath)
  50. gLink.GET(":subid", a.subs)
  51. if a.jsonEnabled {
  52. gJson := g.Group(a.subJsonPath)
  53. gJson.GET(":subid", a.subJsons)
  54. }
  55. }
  56. func (a *SUBController) subs(c *gin.Context) {
  57. subId := c.Param("subid")
  58. scheme, host, hostWithPort, hostHeader := a.subService.ResolveRequest(c)
  59. subs, lastOnline, traffic, err := a.subService.GetSubs(subId, host)
  60. if err != nil || len(subs) == 0 {
  61. c.String(400, "Error!")
  62. } else {
  63. result := ""
  64. for _, sub := range subs {
  65. result += sub + "\n"
  66. }
  67. // If the request expects HTML (e.g., browser) or explicitly asked (?html=1 or ?view=html), render the info page here
  68. accept := c.GetHeader("Accept")
  69. if strings.Contains(strings.ToLower(accept), "text/html") || c.Query("html") == "1" || strings.EqualFold(c.Query("view"), "html") {
  70. // Build page data in service
  71. subURL, subJsonURL := a.subService.BuildURLs(scheme, hostWithPort, a.subPath, a.subJsonPath, subId)
  72. if !a.jsonEnabled {
  73. subJsonURL = ""
  74. }
  75. page := a.subService.BuildPageData(subId, hostHeader, traffic, lastOnline, subs, subURL, subJsonURL)
  76. c.HTML(200, "subpage.html", gin.H{
  77. "title": "subscription.title",
  78. "cur_ver": config.GetVersion(),
  79. "host": page.Host,
  80. "base_path": page.BasePath,
  81. "sId": page.SId,
  82. "download": page.Download,
  83. "upload": page.Upload,
  84. "total": page.Total,
  85. "used": page.Used,
  86. "remained": page.Remained,
  87. "expire": page.Expire,
  88. "lastOnline": page.LastOnline,
  89. "datepicker": page.Datepicker,
  90. "downloadByte": page.DownloadByte,
  91. "uploadByte": page.UploadByte,
  92. "totalByte": page.TotalByte,
  93. "subUrl": page.SubUrl,
  94. "subJsonUrl": page.SubJsonUrl,
  95. "result": page.Result,
  96. })
  97. return
  98. }
  99. // Add headers
  100. header := fmt.Sprintf("upload=%d; download=%d; total=%d; expire=%d", traffic.Up, traffic.Down, traffic.Total, traffic.ExpiryTime/1000)
  101. a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle)
  102. if a.subEncrypt {
  103. c.String(200, base64.StdEncoding.EncodeToString([]byte(result)))
  104. } else {
  105. c.String(200, result)
  106. }
  107. }
  108. }
  109. func (a *SUBController) subJsons(c *gin.Context) {
  110. subId := c.Param("subid")
  111. _, host, _, _ := a.subService.ResolveRequest(c)
  112. jsonSub, header, err := a.subJsonService.GetJson(subId, host)
  113. if err != nil || len(jsonSub) == 0 {
  114. c.String(400, "Error!")
  115. } else {
  116. // Add headers
  117. a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle)
  118. c.String(200, jsonSub)
  119. }
  120. }
  121. func (a *SUBController) ApplyCommonHeaders(c *gin.Context, header, updateInterval, profileTitle string) {
  122. c.Writer.Header().Set("Subscription-Userinfo", header)
  123. c.Writer.Header().Set("Profile-Update-Interval", updateInterval)
  124. c.Writer.Header().Set("Profile-Title", "base64:"+base64.StdEncoding.EncodeToString([]byte(profileTitle)))
  125. }