134 lines
2.8 KiB
Go
134 lines
2.8 KiB
Go
package history
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Item represents a single downloaded torrent in history.
|
|
type Item struct {
|
|
InfoHash string `json:"info_hash"`
|
|
Name string `json:"name"`
|
|
TorrentPath string `json:"torrent_path"` // Magnet link or path to .torrent file
|
|
OutputDir string `json:"output_dir"`
|
|
Status string `json:"status"` // e.g. "downloading", "seeding", "stopped", "completed"
|
|
Progress float64 `json:"progress"`
|
|
Size int64 `json:"size"`
|
|
AddedAt time.Time `json:"added_at"`
|
|
}
|
|
|
|
var (
|
|
mu sync.Mutex
|
|
)
|
|
|
|
// getHistoryPath returns the path to ~/.ztrr/history.json
|
|
func getHistoryPath() (string, error) {
|
|
home, err := os.UserHomeDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
dir := filepath.Join(home, ".ztrr")
|
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
return "", err
|
|
}
|
|
return filepath.Join(dir, "history.json"), nil
|
|
}
|
|
|
|
// Load reads all items from the history file.
|
|
func Load() ([]Item, error) {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
path, err := getHistoryPath()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return []Item{}, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
var items []Item
|
|
if err := json.Unmarshal(data, &items); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
// Save writes all items to the history file.
|
|
func Save(items []Item) error {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
|
|
path, err := getHistoryPath()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
data, err := json.MarshalIndent(items, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return os.WriteFile(path, data, 0644)
|
|
}
|
|
|
|
// Update adds or updates an item in the history.
|
|
func Update(item Item) error {
|
|
items, err := Load()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load history: %v", err)
|
|
}
|
|
|
|
found := false
|
|
for i, existing := range items {
|
|
if existing.InfoHash == item.InfoHash || (existing.InfoHash == "" && existing.TorrentPath == item.TorrentPath) {
|
|
// Maintain original added_at if we are updating
|
|
item.AddedAt = existing.AddedAt
|
|
if item.InfoHash == "" {
|
|
item.InfoHash = existing.InfoHash
|
|
}
|
|
items[i] = item
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
if item.AddedAt.IsZero() {
|
|
item.AddedAt = time.Now()
|
|
}
|
|
items = append(items, item)
|
|
}
|
|
|
|
return Save(items)
|
|
}
|
|
|
|
// Remove deletes an item from the history.
|
|
func Remove(infoHash, torrentPath string) error {
|
|
items, err := Load()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load history: %v", err)
|
|
}
|
|
|
|
var newItems []Item
|
|
for _, existing := range items {
|
|
if existing.InfoHash == infoHash && existing.InfoHash != "" {
|
|
continue
|
|
}
|
|
if existing.TorrentPath == torrentPath && infoHash == "" {
|
|
continue
|
|
}
|
|
newItems = append(newItems, existing)
|
|
}
|
|
|
|
return Save(newItems)
|
|
}
|