Browse Source

Show client info in the remark (#765)

TeleDark 1 year ago
parent
commit
64d17bee70
3 changed files with 69 additions and 15 deletions
  1. 1 0
      go.mod
  2. 2 0
      go.sum
  3. 66 15
      sub/subService.go

+ 1 - 0
go.mod

@@ -14,6 +14,7 @@ require (
 	github.com/robfig/cron/v3 v3.0.1
 	github.com/shirou/gopsutil/v3 v3.23.6
 	github.com/xtls/xray-core v1.8.3
+	github.com/yaa110/go-persian-calendar v1.1.5
 	go.uber.org/atomic v1.11.0
 	golang.org/x/text v0.11.0
 	google.golang.org/grpc v1.56.2

+ 2 - 0
go.sum

@@ -160,6 +160,8 @@ github.com/xtls/reality v0.0.0-20230613075828-e07c3b04b983 h1:AMyzgjkh54WocjQSlC
 github.com/xtls/reality v0.0.0-20230613075828-e07c3b04b983/go.mod h1:rkuAY1S9F8eI8gDiPDYvACE8e2uwkyg8qoOTuwWov7Y=
 github.com/xtls/xray-core v1.8.3 h1:lxaVklPjLKqUU4ua4qH8SBaRcAaNHlH+LmXOx0U/Ejg=
 github.com/xtls/xray-core v1.8.3/go.mod h1:i7t4JFnq828P2+XK0XjGQ8W9x78iu+EJ7jI4l3sonIw=
+github.com/yaa110/go-persian-calendar v1.1.5 h1:EUipRRhzE6bR2NZaSyZ5BEOP46LGbUjzQgdC+Ivrbe4=
+github.com/yaa110/go-persian-calendar v1.1.5/go.mod h1:qtnmHCS9u1EiwzzSCSttGoxD5NfV9ZMzymxFCBYmqfg=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=

+ 66 - 15
sub/subService.go

@@ -3,6 +3,8 @@ package sub
 import (
 	"encoding/base64"
 	"fmt"
+	"time"
+	ptime "github.com/yaa110/go-persian-calendar"
 	"net/url"
 	"strings"
 	"x-ui/database"
@@ -10,7 +12,7 @@ import (
 	"x-ui/logger"
 	"x-ui/web/service"
 	"x-ui/xray"
-
+	"x-ui/util/common"
 	"github.com/goccy/go-json"
 )
 
@@ -55,7 +57,7 @@ func (s *SubService) GetSubs(subId string, host string) ([]string, []string, err
 		}
 		for _, client := range clients {
 			if client.Enable && client.SubID == subId {
-				link := s.getLink(inbound, client.Email)
+				link := s.getLink(inbound, client.Email,client.ExpiryTime)
 				result = append(result, link)
 				clientTraffics = append(clientTraffics, s.getClientTraffics(inbound.ClientStats, client.Email))
 			}
@@ -121,25 +123,29 @@ func (s *SubService) getFallbackMaster(dest string) (*model.Inbound, error) {
 	return inbound, nil
 }
 
-func (s *SubService) getLink(inbound *model.Inbound, email string) string {
+func (s *SubService) getLink(inbound *model.Inbound, email string, expiryTime int64) string {
 	switch inbound.Protocol {
 	case "vmess":
-		return s.genVmessLink(inbound, email)
+		return s.genVmessLink(inbound, email, expiryTime)
 	case "vless":
-		return s.genVlessLink(inbound, email)
+		return s.genVlessLink(inbound, email, expiryTime)
 	case "trojan":
-		return s.genTrojanLink(inbound, email)
+		return s.genTrojanLink(inbound, email, expiryTime)
 	case "shadowsocks":
-		return s.genShadowsocksLink(inbound, email)
+		return s.genShadowsocksLink(inbound, email, expiryTime)
 	}
 	return ""
 }
 
-func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
+func (s *SubService) genVmessLink(inbound *model.Inbound, email string, expiryTime int64) string {
 	if inbound.Protocol != model.VMess {
 		return ""
 	}
-	remark := fmt.Sprintf("%s-%s", inbound.Remark, email)
+
+	remainedTraffic := s.getRemainedTraffic(email)
+	expiryTimeString :=  getExpiryTime(expiryTime)
+
+	remark := fmt.Sprintf("%s: %s- %s", email, remainedTraffic, expiryTimeString)
 	obj := map[string]interface{}{
 		"v":    "2",
 		"ps":   remark,
@@ -256,7 +262,7 @@ func (s *SubService) genVmessLink(inbound *model.Inbound, email string) string {
 	return "vmess://" + base64.StdEncoding.EncodeToString(jsonStr)
 }
 
-func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
+func (s *SubService) genVlessLink(inbound *model.Inbound, email string, expiryTime int64) string {
 	address := s.address
 	if inbound.Protocol != model.VLESS {
 		return ""
@@ -449,7 +455,10 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
 	// Set the new query values on the URL
 	url.RawQuery = q.Encode()
 
-	remark := fmt.Sprintf("%s-%s", inbound.Remark, email)
+	remainedTraffic := s.getRemainedTraffic(email)
+	expiryTimeString :=  getExpiryTime(expiryTime)
+
+	remark := fmt.Sprintf("%s: %s- %s", email, remainedTraffic, expiryTimeString)
 
 	if len(domains) > 0 {
 		links := ""
@@ -468,7 +477,7 @@ func (s *SubService) genVlessLink(inbound *model.Inbound, email string) string {
 	return url.String()
 }
 
-func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string {
+func (s *SubService) genTrojanLink(inbound *model.Inbound, email string, expiryTime int64) string {
 	address := s.address
 	if inbound.Protocol != model.Trojan {
 		return ""
@@ -658,7 +667,10 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
 	// Set the new query values on the URL
 	url.RawQuery = q.Encode()
 
-	remark := fmt.Sprintf("%s-%s", inbound.Remark, email)
+	remainedTraffic := s.getRemainedTraffic(email)
+	expiryTimeString :=  getExpiryTime(expiryTime)
+
+	remark := fmt.Sprintf("%s: %s- %s", email, remainedTraffic, expiryTimeString)
 
 	if len(domains) > 0 {
 		links := ""
@@ -678,7 +690,7 @@ func (s *SubService) genTrojanLink(inbound *model.Inbound, email string) string
 	return url.String()
 }
 
-func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) string {
+func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string, expiryTime int64) string {
 	address := s.address
 	if inbound.Protocol != model.Shadowsocks {
 		return ""
@@ -697,7 +709,11 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
 		}
 	}
 	encPart := fmt.Sprintf("%s:%s:%s", method, inboundPassword, clients[clientIndex].Password)
-	remark := fmt.Sprintf("%s-%s", inbound.Remark, clients[clientIndex].Email)
+	
+	remainedTraffic := s.getRemainedTraffic(clients[clientIndex].Email)
+	expiryTimeString :=  getExpiryTime(expiryTime)
+
+	remark := fmt.Sprintf("%s: %s- %s", clients[clientIndex].Email, remainedTraffic ,expiryTimeString)
 	return fmt.Sprintf("ss://%s@%s:%d#%s", base64.StdEncoding.EncodeToString([]byte(encPart)), address, inbound.Port, remark)
 }
 
@@ -742,3 +758,38 @@ func searchHost(headers interface{}) string {
 
 	return ""
 }
+
+func getExpiryTime(expiryTime int64) string{
+	now := time.Now().Unix()
+	expiryString := ""
+
+	timeDifference := expiryTime/1000 - now
+	
+	if expiryTime == 0 {
+			expiryString = "♾ ⏳"
+		} else if timeDifference > 172800 {
+			expiryString = fmt.Sprintf("%s ⏳", ptime.Unix((expiryTime / 1000), 0).Format("yy-MM-dd hh:mm"))
+		} else if expiryTime < 0 {
+			expiryString = fmt.Sprintf("%d ⏳", expiryTime/-86400000)
+		} else {
+			expiryString = fmt.Sprintf("%s %d ⏳", "ساعت", timeDifference/3600)
+		}
+
+	return expiryString
+}
+
+func (s *SubService) getRemainedTraffic( email string) string{
+	traffic, err := s.inboundService.GetClientTrafficByEmail(email)
+	if err != nil {
+		logger.Warning(err)
+	}
+
+	remainedTraffic := ""
+	if traffic.Total == 0 {
+		remainedTraffic = "♾ 📊"
+	} else {
+		remainedTraffic = fmt.Sprintf("%s%s" ,common.FormatTraffic(traffic.Total-(traffic.Up+traffic.Down)), "📊")
+	}
+
+	return remainedTraffic
+}