Files
renjue fe8ea784d0
CI / docker (push) Successful in 2m54s
feat: Prism HTTP/SOCKS5 代理网关及管理台
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 15:58:28 +08:00

100 lines
2.4 KiB
Go

package mihomoapi
import (
"encoding/json"
"fmt"
"time"
)
type ConnectionSnapshot struct {
Connections []Connection `json:"connections"`
}
type Connection struct {
ID string `json:"id"`
Metadata ConnectionMeta `json:"metadata"`
Upload int64 `json:"upload"`
Download int64 `json:"download"`
Start time.Time `json:"start"`
Chains []string `json:"chains"`
Rule string `json:"rule"`
RulePayload string `json:"rulePayload"`
}
type ConnectionMeta struct {
Network string `json:"network"`
Host string `json:"host"`
RemoteDestination string `json:"remoteDestination"`
DestinationIP string `json:"destinationIP"`
DestinationPort string `json:"destinationPort"`
SniffHost string `json:"sniffHost"`
}
func (c *Client) ConnectionSnapshot() (*ConnectionSnapshot, error) {
var snap ConnectionSnapshot
if err := c.getJSON("/connections", &snap); err != nil {
return nil, err
}
return &snap, nil
}
// ParseConnectionSnapshot decodes Mihomo /connections JSON.
func ParseConnectionSnapshot(data []byte) (*ConnectionSnapshot, error) {
var snap ConnectionSnapshot
if err := json.Unmarshal(data, &snap); err != nil {
return nil, err
}
return &snap, nil
}
func (conn *Connection) RequestHost() string {
if conn.Metadata.Host != "" {
return conn.Metadata.Host
}
if conn.Metadata.SniffHost != "" {
return conn.Metadata.SniffHost
}
if conn.Metadata.RemoteDestination != "" {
return conn.Metadata.RemoteDestination
}
if conn.Metadata.DestinationIP != "" {
return fmt.Sprintf("%s:%s", conn.Metadata.DestinationIP, conn.Metadata.DestinationPort)
}
return ""
}
func (conn *Connection) RuleLine() string {
if conn.Rule == "" {
return ""
}
if conn.RulePayload == "" {
return conn.Rule
}
return conn.Rule + "," + conn.RulePayload
}
func (conn *Connection) OutboundNode() string {
return ResolveLeafOutbound(conn.Chains, nil)
}
func (conn *Connection) LeafOutbound(policyGroups map[string]bool) string {
return ResolveLeafOutbound(conn.Chains, policyGroups)
}
func (conn *Connection) ChainString() string {
if len(conn.Chains) == 0 {
return ""
}
b, _ := json.Marshal(conn.Chains)
return string(b)
}
func (conn *Connection) IsSuccess() bool {
for _, ch := range conn.Chains {
if ch == "REJECT" || ch == "REJECT-DROP" {
return false
}
}
return conn.Upload+conn.Download > 0
}