Files
MeBox/internal/service/aria2_parse.go
T
2026-08-10 21:04:04 +08:00

117 lines
2.6 KiB
Go

package service
import (
"encoding/json"
"time"
)
// parseAria2Items 解析 Aria2 返回的任务列表。
func (a *Aria2Adapter) parseAria2Items(raw json.RawMessage) []TorrentInfo {
var items []map[string]interface{}
if err := json.Unmarshal(raw, &items); err != nil {
return nil
}
result := make([]TorrentInfo, 0, len(items))
for _, item := range items {
info := a.parseSingleItem(item)
if info != nil {
result = append(result, *info)
}
}
return result
}
// parseSingleItem 解析单个 Aria2 任务项。
func (a *Aria2Adapter) parseSingleItem(item map[string]interface{}) *TorrentInfo {
gid := strVal(item["gid"])
totalLength := toInt64(item["totalLength"])
completedLength := toInt64(item["completedLength"])
dlSpeed := toInt64(item["downloadSpeed"])
upSpeed := toInt64(item["uploadSpeed"])
status := strVal(item["status"])
dir := strVal(item["dir"])
numSeeders := int(toInt64(item["numSeeders"]))
connections := int(toInt64(item["connections"]))
var name string
var contentPath string
// 尝试从 bittorrent info 获取名称和 hash
if bt, ok := item["bittorrent"].(map[string]interface{}); ok {
if info, ok := bt["info"].(map[string]interface{}); ok {
name = strVal(info["name"])
}
contentPath = downloaderPayloadPath(dir, name)
}
if name == "" {
// 尝试从 files 获取文件名
if files, ok := item["files"].([]interface{}); ok && len(files) > 0 {
if f, ok := files[0].(map[string]interface{}); ok {
filePath := strVal(f["path"])
if filePath != "" {
contentPath = filePath
name = downloaderPathBase(filePath)
}
if name == "" {
name = strVal(f["uris"])
}
}
}
}
if name == "" {
name = gid
}
var progress float64
if totalLength > 0 {
progress = float64(completedLength) / float64(totalLength)
}
// Aria2 状态映射
state := canonicalTorrentState(aria2StatusStr(status), progress)
return &TorrentInfo{
Hash: gid,
Name: name,
Size: totalLength,
Progress: progress,
DLSpeed: dlSpeed,
UPSpeed: upSpeed,
State: state,
SavePath: dir,
NumSeeds: numSeeders,
NumLeechs: aria2MaxInt(connections-numSeeders, 0),
AddedOn: time.Now(),
ContentPath: contentPath,
}
}
// aria2StatusStr 将 Aria2 状态转为可读字符串。
func aria2StatusStr(status string) string {
switch status {
case "active":
return "downloading"
case "waiting":
return "queued"
case "paused":
return "paused"
case "error":
return "error"
case "complete":
return "seeding"
case "removed":
return "removed"
default:
return status
}
}
func aria2MaxInt(a, b int) int {
if a > b {
return a
}
return b
}