fc3a66dc83
Go 控制面(SQLite + REST API)嵌入 Mihomo 数据面,Vue 3 多语言 Web 管理台。 含订阅/节点/规则/出站/监控/日志、OpenAPI、API Key、Gitea Actions CI(runs-on: ubuntu-latest) 与开源文档;镜像发布至 git.rc707blog.top Container Registry。 Co-authored-by: Cursor <cursoragent@cursor.com>
100 lines
2.4 KiB
Go
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
|
|
}
|