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

106 lines
3.3 KiB
Go

package service
import (
"context"
"errors"
"strings"
"github.com/ShukeBta/MediaStationGo/internal/model"
)
func (d *DownloadService) PauseDownloadTask(ctx context.Context, taskID string) error {
return d.controlDownloadTask(ctx, taskID, "paused", func(target downloadTarget, externalID string) error {
if target.legacyQB {
return d.qb.Pause(ctx, externalID)
}
return target.adapter.Pause(ctx, externalID)
})
}
func (d *DownloadService) ResumeDownloadTask(ctx context.Context, taskID string) error {
return d.controlDownloadTask(ctx, taskID, "queued", func(target downloadTarget, externalID string) error {
if target.legacyQB {
return d.qb.Resume(ctx, externalID)
}
return target.adapter.Resume(ctx, externalID)
})
}
func (d *DownloadService) controlDownloadTask(ctx context.Context, taskID, status string, operation func(downloadTarget, string) error) error {
taskID = strings.TrimSpace(taskID)
if taskID == "" {
return errors.New("task id is required")
}
var task model.DownloadTask
if d == nil || d.repo == nil || d.repo.DB == nil {
return errors.New("download repository is unavailable")
}
if err := d.repo.DB.WithContext(ctx).Where("id = ?", taskID).First(&task).Error; err != nil {
return err
}
clientID, externalID := d.resolveTaskDownloaderIdentity(ctx, &task)
if externalID == "" {
return errors.New("download task has no client task id")
}
target, err := d.downloadTargetByID(ctx, clientID)
if err != nil {
return err
}
if err := operation(target, externalID); err != nil {
return err
}
return d.repo.DB.WithContext(ctx).Model(&model.DownloadTask{}).
Where("id = ?", task.ID).
Updates(map[string]any{
"status": status,
"download_client_id": clientID,
"external_id": externalID,
"source": firstNonEmpty(target.typ, task.Source),
}).Error
}
func (d *DownloadService) resolveTaskDownloaderIdentity(ctx context.Context, task *model.DownloadTask) (string, string) {
if task == nil {
return "", ""
}
clientID := strings.TrimSpace(task.DownloadClientID)
persistedExternalID := strings.TrimSpace(task.ExternalID)
externalID := persistedExternalID
if externalID == "" {
externalID = torrentURLInfoHash(task.URL)
}
if clientID != "" && persistedExternalID != "" {
return clientID, externalID
}
live, _ := d.listLiveTorrents(ctx, "")
for _, torrent := range live {
if clientID != "" && torrent.ClientID != clientID {
continue
}
if externalID != "" && strings.EqualFold(torrent.Hash, externalID) {
clientID = firstNonEmpty(clientID, torrent.ClientID)
return clientID, torrent.Hash
}
if downloadTaskMatchesLiveTorrent(*task, torrent) {
clientID = firstNonEmpty(clientID, torrent.ClientID)
externalID = firstNonEmpty(externalID, torrent.Hash)
return clientID, externalID
}
}
if clientID == "" && d.manager != nil {
var matched []managedDownloadTarget
for _, target := range d.manager.targets() {
if strings.TrimSpace(task.Source) == "" || target.client.Type == task.Source {
matched = append(matched, target)
}
}
if len(matched) == 1 {
clientID = matched[0].client.ID
}
}
if clientID == "" && d.qb != nil && d.qb.IsConfigured() && (task.Source == "" || task.Source == "qbittorrent") {
clientID = legacyQBitDownloadClientID
}
return clientID, externalID
}