subController.go 3.7 KB

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