Compare commits

..

1 commit

Author SHA1 Message Date
Vadim Iskuchekov
3e63d4e545
Merge d15c4e3526 into 5408a2f82c 2025-09-14 22:28:18 +02:00
2 changed files with 49 additions and 19 deletions

View file

@ -2,7 +2,6 @@ package sub
import ( import (
"encoding/base64" "encoding/base64"
"fmt"
"strings" "strings"
"x-ui/config" "x-ui/config"
@ -60,7 +59,7 @@ func (a *SUBController) initRouter(g *gin.RouterGroup) {
func (a *SUBController) subs(c *gin.Context) { func (a *SUBController) subs(c *gin.Context) {
subId := c.Param("subid") subId := c.Param("subid")
scheme, host, hostWithPort, hostHeader := a.subService.ResolveRequest(c) scheme, host, hostWithPort, hostHeader := a.subService.ResolveRequest(c)
subs, lastOnline, traffic, err := a.subService.GetSubs(subId, host) subs, header, lastOnline, err := a.subService.GetSubs(subId, host)
if err != nil || len(subs) == 0 { if err != nil || len(subs) == 0 {
c.String(400, "Error!") c.String(400, "Error!")
} else { } else {
@ -74,7 +73,7 @@ func (a *SUBController) subs(c *gin.Context) {
if strings.Contains(strings.ToLower(accept), "text/html") || c.Query("html") == "1" || strings.EqualFold(c.Query("view"), "html") { if strings.Contains(strings.ToLower(accept), "text/html") || c.Query("html") == "1" || strings.EqualFold(c.Query("view"), "html") {
// Build page data in service // Build page data in service
subURL, subJsonURL := a.subService.BuildURLs(scheme, hostWithPort, a.subPath, a.subJsonPath, subId) subURL, subJsonURL := a.subService.BuildURLs(scheme, hostWithPort, a.subPath, a.subJsonPath, subId)
page := a.subService.BuildPageData(subId, hostHeader, traffic, lastOnline, subs, subURL, subJsonURL) page := a.subService.BuildPageData(subId, hostHeader, header, lastOnline, subs, subURL, subJsonURL)
c.HTML(200, "subscription.html", gin.H{ c.HTML(200, "subscription.html", gin.H{
"title": "subscription.title", "title": "subscription.title",
"cur_ver": config.GetVersion(), "cur_ver": config.GetVersion(),
@ -100,7 +99,6 @@ 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)
a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle) a.ApplyCommonHeaders(c, header, a.updateInterval, a.subTitle)
if a.subEncrypt { if a.subEncrypt {

View file

@ -37,19 +37,20 @@ func NewSubService(showInfo bool, remarkModel string) *SubService {
} }
} }
func (s *SubService) GetSubs(subId string, host string) ([]string, int64, xray.ClientTraffic, error) { func (s *SubService) GetSubs(subId string, host string) ([]string, string, int64, error) {
s.address = host s.address = host
var result []string var result []string
var header string
var traffic xray.ClientTraffic var traffic xray.ClientTraffic
var lastOnline int64 var lastOnline int64
var clientTraffics []xray.ClientTraffic var clientTraffics []xray.ClientTraffic
inbounds, err := s.getInboundsBySubId(subId) inbounds, err := s.getInboundsBySubId(subId)
if err != nil { if err != nil {
return nil, 0, traffic, err return nil, "", 0, err
} }
if len(inbounds) == 0 { if len(inbounds) == 0 {
return nil, 0, traffic, common.NewError("No inbounds found with ", subId) return nil, "", 0, common.NewError("No inbounds found with ", subId)
} }
s.datepicker, err = s.settingService.GetDatepicker() s.datepicker, err = s.settingService.GetDatepicker()
@ -107,7 +108,8 @@ func (s *SubService) GetSubs(subId string, host string) ([]string, int64, xray.C
} }
} }
} }
return result, lastOnline, traffic, nil header = fmt.Sprintf("upload=%d; download=%d; total=%d; expire=%d", traffic.Up, traffic.Down, traffic.Total, traffic.ExpiryTime/1000)
return result, header, lastOnline, nil
} }
func (s *SubService) getInboundsBySubId(subId string) ([]*model.Inbound, error) { func (s *SubService) getInboundsBySubId(subId string) ([]*model.Inbound, error) {
@ -1088,15 +1090,45 @@ func (s *SubService) BuildURLs(scheme, hostWithPort, subPath, subJsonPath, subId
} }
// BuildPageData parses header and prepares the template view model. // BuildPageData parses header and prepares the template view model.
func (s *SubService) BuildPageData(subId string, hostHeader string, traffic xray.ClientTraffic, lastOnline int64, subs []string, subURL, subJsonURL string) PageData { func (s *SubService) BuildPageData(subId, hostHeader, header string, lastOnline int64, subs []string, subURL, subJsonURL string) PageData {
download := common.FormatTraffic(traffic.Down) // Parse header values
upload := common.FormatTraffic(traffic.Up) var uploadByte, downloadByte, totalByte, expire int64
parts := strings.Split(header, ";")
for _, p := range parts {
kv := strings.Split(strings.TrimSpace(p), "=")
if len(kv) != 2 {
continue
}
key := strings.ToLower(strings.TrimSpace(kv[0]))
val := strings.TrimSpace(kv[1])
switch key {
case "upload":
if v, err := parseInt64(val); err == nil {
uploadByte = v
}
case "download":
if v, err := parseInt64(val); err == nil {
downloadByte = v
}
case "total":
if v, err := parseInt64(val); err == nil {
totalByte = v
}
case "expire":
if v, err := parseInt64(val); err == nil {
expire = v
}
}
}
download := common.FormatTraffic(downloadByte)
upload := common.FormatTraffic(uploadByte)
total := "∞" total := "∞"
used := common.FormatTraffic(traffic.Up + traffic.Down) used := common.FormatTraffic(uploadByte + downloadByte)
remained := "" remained := ""
if traffic.Total > 0 { if totalByte > 0 {
total = common.FormatTraffic(traffic.Total) total = common.FormatTraffic(totalByte)
left := traffic.Total - (traffic.Up + traffic.Down) left := totalByte - (uploadByte + downloadByte)
if left < 0 { if left < 0 {
left = 0 left = 0
} }
@ -1117,12 +1149,12 @@ func (s *SubService) BuildPageData(subId string, hostHeader string, traffic xray
Total: total, Total: total,
Used: used, Used: used,
Remained: remained, Remained: remained,
Expire: traffic.ExpiryTime / 1000, Expire: expire,
LastOnline: lastOnline, LastOnline: lastOnline,
Datepicker: datepicker, Datepicker: datepicker,
DownloadByte: traffic.Down, DownloadByte: downloadByte,
UploadByte: traffic.Up, UploadByte: uploadByte,
TotalByte: traffic.Total, TotalByte: totalByte,
SubUrl: subURL, SubUrl: subURL,
SubJsonUrl: subJsonURL, SubJsonUrl: subJsonURL,
Result: subs, Result: subs,