refactor: 更新项目引用路径从perfect-panel/ppanel-server到perfect-panel/server
Build docker and publish / build (20.15.1) (push) Failing after 6m27s
Build docker and publish / build (20.15.1) (push) Failing after 6m27s
feat: 添加版本和构建时间变量 fix: 修正短信队列类型注释错误 style: 清理未使用的代码和测试文件 docs: 更新安装文档中的下载链接 chore: 迁移数据库脚本添加日志和订阅配置
This commit is contained in:
@@ -1,3 +1,86 @@
|
||||
package server
|
||||
|
||||
const Unchanged = "Unchanged"
|
||||
const (
|
||||
Unchanged = "Unchanged"
|
||||
ShadowSocks = "shadowsocks"
|
||||
Vmess = "vmess"
|
||||
Vless = "vless"
|
||||
Trojan = "trojan"
|
||||
AnyTLS = "anytls"
|
||||
Tuic = "tuic"
|
||||
Hysteria = "hysteria"
|
||||
// Deprecated: Hysteria2 is deprecated, use Hysteria instead
|
||||
// TODO: remove in future versions
|
||||
Hysteria2 = "hysteria2"
|
||||
)
|
||||
|
||||
type SecurityConfig struct {
|
||||
SNI string `json:"sni"`
|
||||
AllowInsecure *bool `json:"allow_insecure"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
RealityServerAddress string `json:"reality_server_addr"`
|
||||
RealityServerPort int `json:"reality_server_port"`
|
||||
RealityPrivateKey string `json:"reality_private_key"`
|
||||
RealityPublicKey string `json:"reality_public_key"`
|
||||
RealityShortId string `json:"reality_short_id"`
|
||||
RealityMldsa65seed string `json:"reality_mldsa65seed"`
|
||||
}
|
||||
|
||||
type TransportConfig struct {
|
||||
Path string `json:"path"`
|
||||
Host string `json:"host"`
|
||||
ServiceName string `json:"service_name"`
|
||||
DisableSNI bool `json:"disable_sni"`
|
||||
ReduceRtt bool `json:"reduce_rtt"`
|
||||
UDPRelayMode string `json:"udp_relay_mode"`
|
||||
CongestionController string `json:"congestion_controller"`
|
||||
}
|
||||
|
||||
type VlessNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
Flow string `json:"flow"`
|
||||
Network string `json:"transport"`
|
||||
TransportConfig *TransportConfig `json:"transport_config"`
|
||||
Security string `json:"security"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
type VmessNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
Network string `json:"transport"`
|
||||
TransportConfig *TransportConfig `json:"transport_config"`
|
||||
Security string `json:"security"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
type ShadowsocksNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
Cipher string `json:"method"`
|
||||
ServerKey string `json:"server_key"`
|
||||
}
|
||||
|
||||
type TrojanNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
Network string `json:"transport"`
|
||||
TransportConfig *TransportConfig `json:"transport_config"`
|
||||
Security string `json:"security"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
type AnyTLSNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
type TuicNode struct {
|
||||
Port uint16 `json:"port"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
type Hysteria2Node struct {
|
||||
Port uint16 `json:"port"`
|
||||
HopPorts string `json:"hop_ports"`
|
||||
HopInterval int `json:"hop_interval"`
|
||||
ObfsPassword string `json:"obfs_password"`
|
||||
SecurityConfig *SecurityConfig `json:"security_config"`
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/model/node"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/internal/types"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/xerr"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
)
|
||||
|
||||
type GetServerConfigLogic struct {
|
||||
@@ -20,7 +21,7 @@ type GetServerConfigLogic struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get server config
|
||||
// NewGetServerConfigLogic Get server config
|
||||
func NewGetServerConfigLogic(ctx *gin.Context, svcCtx *svc.ServiceContext) *GetServerConfigLogic {
|
||||
return &GetServerConfigLogic{
|
||||
Logger: logger.WithContext(ctx.Request.Context()),
|
||||
@@ -30,7 +31,7 @@ func NewGetServerConfigLogic(ctx *gin.Context, svcCtx *svc.ServiceContext) *GetS
|
||||
}
|
||||
|
||||
func (l *GetServerConfigLogic) GetServerConfig(req *types.GetServerConfigRequest) (resp *types.GetServerConfigResponse, err error) {
|
||||
cacheKey := fmt.Sprintf("%s%d", config.ServerConfigCacheKey, req.ServerId)
|
||||
cacheKey := fmt.Sprintf("%s%d:%s", node.ServerConfigCacheKey, req.ServerId, req.Protocol)
|
||||
cache, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err == nil {
|
||||
if cache != "" {
|
||||
@@ -41,7 +42,7 @@ func (l *GetServerConfigLogic) GetServerConfig(req *types.GetServerConfigRequest
|
||||
return nil, xerr.StatusNotModified
|
||||
}
|
||||
l.ctx.Header("ETag", etag)
|
||||
resp := &types.GetServerConfigResponse{}
|
||||
resp = &types.GetServerConfigResponse{}
|
||||
err = json.Unmarshal([]byte(cache), resp)
|
||||
if err != nil {
|
||||
l.Errorw("[ServerConfigCacheKey] json unmarshal error", logger.Field("error", err.Error()))
|
||||
@@ -50,34 +51,191 @@ func (l *GetServerConfigLogic) GetServerConfig(req *types.GetServerConfigRequest
|
||||
return resp, nil
|
||||
}
|
||||
}
|
||||
nodeInfo, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.ServerId)
|
||||
data, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||
if err != nil {
|
||||
l.Errorw("[GetServerConfig] FindOne error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
cfg := make(map[string]interface{})
|
||||
err = json.Unmarshal([]byte(nodeInfo.Config), &cfg)
|
||||
|
||||
// compatible hysteria2, remove in future versions
|
||||
protocolRequest := req.Protocol
|
||||
if protocolRequest == Hysteria2 {
|
||||
protocolRequest = Hysteria
|
||||
}
|
||||
|
||||
protocols, err := data.UnmarshalProtocols()
|
||||
if err != nil {
|
||||
l.Errorw("[GetServerConfig] json unmarshal error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
var cfg map[string]interface{}
|
||||
for _, protocol := range protocols {
|
||||
if protocol.Type == protocolRequest {
|
||||
cfg = l.compatible(protocol)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
resp = &types.GetServerConfigResponse{
|
||||
Basic: types.ServerBasic{
|
||||
PullInterval: l.svcCtx.Config.Node.NodePullInterval,
|
||||
PushInterval: l.svcCtx.Config.Node.NodePushInterval,
|
||||
},
|
||||
Protocol: nodeInfo.Protocol,
|
||||
Protocol: req.Protocol,
|
||||
Config: cfg,
|
||||
}
|
||||
data, err := json.Marshal(resp)
|
||||
c, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
l.Errorw("[GetServerConfig] json marshal error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
etag := tool.GenerateETag(data)
|
||||
etag := tool.GenerateETag(c)
|
||||
l.ctx.Header("ETag", etag)
|
||||
if err = l.svcCtx.Redis.Set(l.ctx, cacheKey, data, -1).Err(); err != nil {
|
||||
if err = l.svcCtx.Redis.Set(l.ctx, cacheKey, c, -1).Err(); err != nil {
|
||||
l.Errorw("[GetServerConfig] redis set error", logger.Field("error", err.Error()))
|
||||
}
|
||||
// Check If-None-Match header
|
||||
match := l.ctx.GetHeader("If-None-Match")
|
||||
if match == etag {
|
||||
return nil, xerr.StatusNotModified
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (l *GetServerConfigLogic) compatible(config node.Protocol) map[string]interface{} {
|
||||
var result interface{}
|
||||
switch config.Type {
|
||||
case ShadowSocks:
|
||||
result = ShadowsocksNode{
|
||||
Port: config.Port,
|
||||
Cipher: config.Cipher,
|
||||
ServerKey: base64.StdEncoding.EncodeToString([]byte(config.ServerKey)),
|
||||
}
|
||||
case Vless:
|
||||
result = VlessNode{
|
||||
Port: config.Port,
|
||||
Flow: config.Flow,
|
||||
Network: config.Transport,
|
||||
TransportConfig: &TransportConfig{
|
||||
Path: config.Path,
|
||||
Host: config.Host,
|
||||
ServiceName: config.ServiceName,
|
||||
DisableSNI: config.DisableSNI,
|
||||
ReduceRtt: config.ReduceRtt,
|
||||
UDPRelayMode: config.UDPRelayMode,
|
||||
CongestionController: config.CongestionController,
|
||||
},
|
||||
Security: config.Security,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
case Vmess:
|
||||
result = VmessNode{
|
||||
Port: config.Port,
|
||||
Network: config.Transport,
|
||||
TransportConfig: &TransportConfig{
|
||||
Path: config.Path,
|
||||
Host: config.Host,
|
||||
ServiceName: config.ServiceName,
|
||||
DisableSNI: config.DisableSNI,
|
||||
ReduceRtt: config.ReduceRtt,
|
||||
UDPRelayMode: config.UDPRelayMode,
|
||||
CongestionController: config.CongestionController,
|
||||
},
|
||||
Security: config.Security,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
case Trojan:
|
||||
result = TrojanNode{
|
||||
Port: config.Port,
|
||||
Network: config.Transport,
|
||||
TransportConfig: &TransportConfig{
|
||||
Path: config.Path,
|
||||
Host: config.Host,
|
||||
ServiceName: config.ServiceName,
|
||||
DisableSNI: config.DisableSNI,
|
||||
ReduceRtt: config.ReduceRtt,
|
||||
UDPRelayMode: config.UDPRelayMode,
|
||||
CongestionController: config.CongestionController,
|
||||
},
|
||||
Security: config.Security,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
case AnyTLS:
|
||||
result = AnyTLSNode{
|
||||
Port: config.Port,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
case Tuic:
|
||||
result = TuicNode{
|
||||
Port: config.Port,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
case Hysteria:
|
||||
result = Hysteria2Node{
|
||||
Port: config.Port,
|
||||
HopPorts: config.HopPorts,
|
||||
HopInterval: config.HopInterval,
|
||||
ObfsPassword: config.ObfsPassword,
|
||||
SecurityConfig: &SecurityConfig{
|
||||
SNI: config.SNI,
|
||||
AllowInsecure: &config.AllowInsecure,
|
||||
Fingerprint: config.Fingerprint,
|
||||
RealityServerAddress: config.RealityServerAddr,
|
||||
RealityServerPort: config.RealityServerPort,
|
||||
RealityPrivateKey: config.RealityPrivateKey,
|
||||
RealityPublicKey: config.RealityPublicKey,
|
||||
RealityShortId: config.RealityShortId,
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
var resp map[string]interface{}
|
||||
s, _ := json.Marshal(result)
|
||||
_ = json.Unmarshal(s, &resp)
|
||||
return resp
|
||||
}
|
||||
|
||||
@@ -3,16 +3,18 @@ package server
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/perfect-panel/server/internal/model/node"
|
||||
"github.com/perfect-panel/server/internal/model/subscribe"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/config"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/internal/types"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/uuidx"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/xerr"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
"github.com/perfect-panel/server/pkg/uuidx"
|
||||
"github.com/perfect-panel/server/pkg/xerr"
|
||||
)
|
||||
|
||||
type GetServerUserListLogic struct {
|
||||
@@ -21,7 +23,7 @@ type GetServerUserListLogic struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Get user list
|
||||
// NewGetServerUserListLogic Get user list
|
||||
func NewGetServerUserListLogic(ctx *gin.Context, svcCtx *svc.ServiceContext) *GetServerUserListLogic {
|
||||
return &GetServerUserListLogic{
|
||||
Logger: logger.WithContext(ctx.Request.Context()),
|
||||
@@ -31,30 +33,53 @@ func NewGetServerUserListLogic(ctx *gin.Context, svcCtx *svc.ServiceContext) *Ge
|
||||
}
|
||||
|
||||
func (l *GetServerUserListLogic) GetServerUserList(req *types.GetServerUserListRequest) (resp *types.GetServerUserListResponse, err error) {
|
||||
cacheKey := fmt.Sprintf("%s%d", config.ServerUserListCacheKey, req.ServerId)
|
||||
cacheKey := fmt.Sprintf("%s%d", node.ServerUserListCacheKey, req.ServerId)
|
||||
cache, err := l.svcCtx.Redis.Get(l.ctx, cacheKey).Result()
|
||||
if err == nil {
|
||||
if cache != "" {
|
||||
etag := tool.GenerateETag([]byte(cache))
|
||||
resp := &types.GetServerUserListResponse{}
|
||||
// Check If-None-Match header
|
||||
if match := l.ctx.GetHeader("If-None-Match"); match == etag {
|
||||
return nil, xerr.StatusNotModified
|
||||
}
|
||||
l.ctx.Header("ETag", etag)
|
||||
err = json.Unmarshal([]byte(cache), resp)
|
||||
if err != nil {
|
||||
l.Errorw("[ServerUserListCacheKey] json unmarshal error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
if cache != "" {
|
||||
etag := tool.GenerateETag([]byte(cache))
|
||||
resp = &types.GetServerUserListResponse{}
|
||||
// Check If-None-Match header
|
||||
if match := l.ctx.GetHeader("If-None-Match"); match == etag {
|
||||
return nil, xerr.StatusNotModified
|
||||
}
|
||||
l.ctx.Header("ETag", etag)
|
||||
err = json.Unmarshal([]byte(cache), resp)
|
||||
if err != nil {
|
||||
l.Errorw("[ServerUserListCacheKey] json unmarshal error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
server, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.ServerId)
|
||||
server, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subs, err := l.svcCtx.SubscribeModel.QuerySubscribeIdsByServerIdAndServerGroupId(l.ctx, server.Id, server.GroupId)
|
||||
|
||||
_, nodes, err := l.svcCtx.NodeModel.FilterNodeList(l.ctx, &node.FilterNodeParams{
|
||||
Page: 1,
|
||||
Size: 1000,
|
||||
ServerId: []int64{server.Id},
|
||||
Protocol: req.Protocol,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("FilterNodeList error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
var nodeTag []string
|
||||
var nodeIds []int64
|
||||
for _, n := range nodes {
|
||||
nodeIds = append(nodeIds, n.Id)
|
||||
if n.Tags != "" {
|
||||
nodeTag = append(nodeTag, strings.Split(n.Tags, ",")...)
|
||||
}
|
||||
}
|
||||
|
||||
_, subs, err := l.svcCtx.SubscribeModel.FilterList(l.ctx, &subscribe.FilterParams{
|
||||
Page: 1,
|
||||
Size: 9999,
|
||||
Node: nodeIds,
|
||||
Tags: nodeTag,
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("QuerySubscribeIdsByServerIdAndServerGroupId error", logger.Field("error", err.Error()))
|
||||
return nil, err
|
||||
@@ -76,16 +101,10 @@ func (l *GetServerUserListLogic) GetServerUserList(req *types.GetServerUserListR
|
||||
return nil, err
|
||||
}
|
||||
for _, datum := range data {
|
||||
speedLimit := server.SpeedLimit
|
||||
if (int(sub.SpeedLimit) < server.SpeedLimit && sub.SpeedLimit != 0) ||
|
||||
(int(sub.SpeedLimit) > server.SpeedLimit && sub.SpeedLimit == 0) {
|
||||
speedLimit = int(sub.SpeedLimit)
|
||||
}
|
||||
|
||||
users = append(users, types.ServerUser{
|
||||
Id: datum.Id,
|
||||
UUID: datum.UUID,
|
||||
SpeedLimit: int64(speedLimit),
|
||||
SpeedLimit: sub.SpeedLimit,
|
||||
DeviceLimit: sub.DeviceLimit,
|
||||
})
|
||||
}
|
||||
@@ -106,5 +125,9 @@ func (l *GetServerUserListLogic) GetServerUserList(req *types.GetServerUserListR
|
||||
if err != nil {
|
||||
l.Errorw("[ServerUserListCacheKey] redis set error", logger.Field("error", err.Error()))
|
||||
}
|
||||
// Check If-None-Match header
|
||||
if match := l.ctx.GetHeader("If-None-Match"); match == etag {
|
||||
return nil, xerr.StatusNotModified
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/model/cache"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/internal/types"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/perfect-panel/server/internal/model/node"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type PushOnlineUsersLogic struct {
|
||||
@@ -40,26 +40,30 @@ func (l *PushOnlineUsersLogic) PushOnlineUsers(req *types.OnlineUsersRequest) er
|
||||
}
|
||||
|
||||
// Find server info
|
||||
_, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.ServerId)
|
||||
_, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||
if err != nil {
|
||||
l.Errorw("[PushOnlineUsers] FindOne error", logger.Field("error", err))
|
||||
return fmt.Errorf("server not found: %w", err)
|
||||
}
|
||||
|
||||
userOnlineIp := make([]cache.NodeOnlineUser, 0)
|
||||
onlineUsers := make(node.OnlineUserSubscribe)
|
||||
for _, user := range req.Users {
|
||||
userOnlineIp = append(userOnlineIp, cache.NodeOnlineUser{
|
||||
SID: user.SID,
|
||||
IP: user.IP,
|
||||
})
|
||||
if online, ok := onlineUsers[user.SID]; ok {
|
||||
// If user already exists, update IP if different
|
||||
online = append(online, user.IP)
|
||||
onlineUsers[user.SID] = online
|
||||
} else {
|
||||
// New user, add to map
|
||||
onlineUsers[user.SID] = []string{user.IP}
|
||||
}
|
||||
}
|
||||
err = l.svcCtx.NodeCache.AddOnlineUserIP(l.ctx, userOnlineIp)
|
||||
err = l.svcCtx.NodeModel.UpdateOnlineUserSubscribe(l.ctx, req.ServerId, req.Protocol, onlineUsers)
|
||||
if err != nil {
|
||||
l.Errorw("[PushOnlineUsers] cache operation error", logger.Field("error", err))
|
||||
return err
|
||||
}
|
||||
|
||||
err = l.svcCtx.NodeCache.UpdateNodeOnlineUser(l.ctx, req.ServerId, userOnlineIp)
|
||||
err = l.svcCtx.NodeModel.UpdateOnlineUserSubscribeGlobal(l.ctx, onlineUsers)
|
||||
|
||||
if err != nil {
|
||||
l.Errorw("[PushOnlineUsers] cache operation error", logger.Field("error", err))
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
)
|
||||
|
||||
type QueryServerProtocolConfigLogic struct {
|
||||
logger.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// NewQueryServerProtocolConfigLogic Get Server Protocol Config
|
||||
func NewQueryServerProtocolConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryServerProtocolConfigLogic {
|
||||
return &QueryServerProtocolConfigLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *QueryServerProtocolConfigLogic) QueryServerProtocolConfig(req *types.QueryServerConfigRequest) (resp *types.QueryServerConfigResponse, err error) {
|
||||
// find server
|
||||
data, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerID)
|
||||
if err != nil {
|
||||
l.Errorf("[GetServerProtocols] FindOneServer Error: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// handler protocols
|
||||
var protocols []types.Protocol
|
||||
dst, err := data.UnmarshalProtocols()
|
||||
if err != nil {
|
||||
l.Errorf("[FilterServerList] UnmarshalProtocols Error: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
tool.DeepCopy(&protocols, dst)
|
||||
|
||||
// filter by req.Protocols
|
||||
|
||||
if len(req.Protocols) > 0 {
|
||||
var filtered []types.Protocol
|
||||
protocolSet := make(map[string]struct{})
|
||||
for _, p := range req.Protocols {
|
||||
protocolSet[p] = struct{}{}
|
||||
}
|
||||
for _, p := range protocols {
|
||||
if _, exists := protocolSet[p.Type]; exists {
|
||||
filtered = append(filtered, p)
|
||||
}
|
||||
}
|
||||
protocols = filtered
|
||||
}
|
||||
|
||||
var dns []types.NodeDNS
|
||||
if len(l.svcCtx.Config.Node.DNS) > 0 {
|
||||
for _, d := range l.svcCtx.Config.Node.DNS {
|
||||
dns = append(dns, types.NodeDNS{
|
||||
Proto: d.Proto,
|
||||
Address: d.Address,
|
||||
Domains: d.Domains,
|
||||
})
|
||||
}
|
||||
}
|
||||
var outbound []types.NodeOutbound
|
||||
if len(l.svcCtx.Config.Node.Outbound) > 0 {
|
||||
for _, o := range l.svcCtx.Config.Node.Outbound {
|
||||
outbound = append(outbound, types.NodeOutbound{
|
||||
Name: o.Name,
|
||||
Protocol: o.Protocol,
|
||||
Address: o.Address,
|
||||
Port: o.Port,
|
||||
Password: o.Password,
|
||||
Rules: o.Rules,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &types.QueryServerConfigResponse{
|
||||
TrafficReportThreshold: l.svcCtx.Config.Node.TrafficReportThreshold,
|
||||
IPStrategy: l.svcCtx.Config.Node.IPStrategy,
|
||||
DNS: dns,
|
||||
Block: l.svcCtx.Config.Node.Block,
|
||||
Outbound: outbound,
|
||||
Protocols: protocols,
|
||||
Total: int64(len(protocols)),
|
||||
}, nil
|
||||
}
|
||||
@@ -3,11 +3,12 @@ package server
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/perfect-panel/ppanel-server/internal/model/cache"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/internal/types"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/perfect-panel/server/internal/model/node"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
)
|
||||
|
||||
type ServerPushStatusLogic struct {
|
||||
@@ -16,7 +17,7 @@ type ServerPushStatusLogic struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// Push server status
|
||||
// NewServerPushStatusLogic Push server status
|
||||
func NewServerPushStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ServerPushStatusLogic {
|
||||
return &ServerPushStatusLogic{
|
||||
Logger: logger.WithContext(ctx),
|
||||
@@ -27,12 +28,12 @@ func NewServerPushStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
|
||||
|
||||
func (l *ServerPushStatusLogic) ServerPushStatus(req *types.ServerPushStatusRequest) error {
|
||||
// Find server info
|
||||
serverInfo, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.ServerId)
|
||||
serverInfo, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||
if err != nil || serverInfo.Id <= 0 {
|
||||
l.Errorw("[PushOnlineUsers] FindOne error", logger.Field("error", err))
|
||||
return errors.New("server not found")
|
||||
}
|
||||
err = l.svcCtx.NodeCache.UpdateNodeStatus(l.ctx, req.ServerId, cache.NodeStatus{
|
||||
err = l.svcCtx.NodeModel.UpdateStatusCache(l.ctx, req.ServerId, &node.Status{
|
||||
Cpu: req.Cpu,
|
||||
Mem: req.Mem,
|
||||
Disk: req.Disk,
|
||||
@@ -42,5 +43,14 @@ func (l *ServerPushStatusLogic) ServerPushStatus(req *types.ServerPushStatusRequ
|
||||
l.Errorw("[ServerPushStatus] UpdateNodeStatus error", logger.Field("error", err))
|
||||
return errors.New("update node status failed")
|
||||
}
|
||||
now := time.Now()
|
||||
serverInfo.LastReportedAt = &now
|
||||
|
||||
err = l.svcCtx.NodeModel.UpdateServer(l.ctx, serverInfo)
|
||||
if err != nil {
|
||||
l.Errorw("[ServerPushStatus] UpdateServer error", logger.Field("error", err))
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@ package server
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/hibiken/asynq"
|
||||
"github.com/perfect-panel/ppanel-server/internal/model/cache"
|
||||
"github.com/perfect-panel/ppanel-server/internal/svc"
|
||||
"github.com/perfect-panel/ppanel-server/internal/types"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/logger"
|
||||
"github.com/perfect-panel/ppanel-server/pkg/tool"
|
||||
task "github.com/perfect-panel/ppanel-server/queue/types"
|
||||
"github.com/perfect-panel/server/internal/svc"
|
||||
"github.com/perfect-panel/server/internal/types"
|
||||
"github.com/perfect-panel/server/pkg/logger"
|
||||
"github.com/perfect-panel/server/pkg/tool"
|
||||
task "github.com/perfect-panel/server/queue/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -32,7 +32,7 @@ func NewServerPushUserTrafficLogic(ctx context.Context, svcCtx *svc.ServiceConte
|
||||
|
||||
func (l *ServerPushUserTrafficLogic) ServerPushUserTraffic(req *types.ServerPushUserTrafficRequest) error {
|
||||
// Find server info
|
||||
serverInfo, err := l.svcCtx.ServerModel.FindOne(l.ctx, req.ServerId)
|
||||
serverInfo, err := l.svcCtx.NodeModel.FindOneServer(l.ctx, req.ServerId)
|
||||
if err != nil {
|
||||
l.Errorw("[PushOnlineUsers] FindOne error", logger.Field("error", err))
|
||||
return errors.New("server not found")
|
||||
@@ -40,23 +40,10 @@ func (l *ServerPushUserTrafficLogic) ServerPushUserTraffic(req *types.ServerPush
|
||||
|
||||
// Create traffic task
|
||||
var request task.TrafficStatistics
|
||||
var userTraffic []cache.UserTraffic
|
||||
request.ServerId = serverInfo.Id
|
||||
request.Protocol = req.Protocol
|
||||
tool.DeepCopy(&request.Logs, req.Traffic)
|
||||
tool.DeepCopy(&userTraffic, req.Traffic)
|
||||
|
||||
// update today traffic rank
|
||||
err = l.svcCtx.NodeCache.AddNodeTodayTraffic(l.ctx, serverInfo.Id, userTraffic)
|
||||
if err != nil {
|
||||
l.Errorw("[ServerPushUserTraffic] AddNodeTodayTraffic error", logger.Field("error", err))
|
||||
return errors.New("add node today traffic error")
|
||||
}
|
||||
for _, user := range req.Traffic {
|
||||
if err = l.svcCtx.NodeCache.AddUserTodayTraffic(l.ctx, user.SID, user.Upload, user.Download); err != nil {
|
||||
l.Errorw("[ServerPushUserTraffic] AddUserTodayTraffic error", logger.Field("error", err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
// Push traffic task
|
||||
val, _ := json.Marshal(request)
|
||||
t := asynq.NewTask(task.ForthwithTrafficStatistics, val, asynq.MaxRetry(3))
|
||||
@@ -66,5 +53,15 @@ func (l *ServerPushUserTrafficLogic) ServerPushUserTraffic(req *types.ServerPush
|
||||
} else {
|
||||
l.Infow("[ServerPushUserTraffic] Push traffic task success", logger.Field("task", t), logger.Field("info", info))
|
||||
}
|
||||
|
||||
// Update server last reported time
|
||||
now := time.Now()
|
||||
serverInfo.LastReportedAt = &now
|
||||
|
||||
err = l.svcCtx.NodeModel.UpdateServer(l.ctx, serverInfo)
|
||||
if err != nil {
|
||||
l.Errorw("[ServerPushUserTraffic] UpdateServer error", logger.Field("error", err))
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user