mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 11:36:36 +08:00
refactor download add responsibilities
This commit is contained in:
@@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ShukeBta/MediaStationGo/internal/model"
|
||||
)
|
||||
@@ -151,306 +150,6 @@ func (d *DownloadService) resolveDownloadSavePath(ctx context.Context, explicitS
|
||||
return downloadSavePathCategoryRoot(base, sanitizeFilename(category)), category
|
||||
}
|
||||
|
||||
func (d *DownloadService) localMediaAlreadyExists(ctx context.Context, title string) bool {
|
||||
rows, ok := d.localMediaAvailabilityRows(ctx, title)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return localMediaRowsMatchDownloadTitle(title, rows)
|
||||
}
|
||||
|
||||
func (d *DownloadService) localMediaAvailabilityRows(ctx context.Context, title string) ([]model.Media, bool) {
|
||||
if d == nil || d.repo == nil || d.repo.DB == nil {
|
||||
return nil, false
|
||||
}
|
||||
if !d.repo.DB.Migrator().HasTable(&model.Media{}) {
|
||||
return nil, false
|
||||
}
|
||||
queries := localAvailabilityTitleCandidates(title)
|
||||
if len(queries) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
var rows []model.Media
|
||||
db := d.repo.DB.WithContext(ctx).Model(&model.Media{})
|
||||
for i, query := range queries {
|
||||
like := "%" + query + "%"
|
||||
clause := "title LIKE ? OR original_name LIKE ? OR path LIKE ?"
|
||||
if i == 0 {
|
||||
db = db.Where(clause, like, like, like)
|
||||
} else {
|
||||
db = db.Or(clause, like, like, like)
|
||||
}
|
||||
}
|
||||
if err := db.
|
||||
Order("season_num asc, episode_num asc, created_at desc").
|
||||
Limit(200).
|
||||
Find(&rows).Error; err != nil || len(rows) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
return rows, true
|
||||
}
|
||||
|
||||
func localMediaRowsMatchDownloadTitle(title string, rows []model.Media) bool {
|
||||
wanted := episodeRefsFromTitle(title)
|
||||
if len(wanted) == 0 {
|
||||
return true
|
||||
}
|
||||
existing := map[string]struct{}{}
|
||||
hasSeriesPack := false
|
||||
for _, row := range rows {
|
||||
rowSeason, rowEpisode := localMediaRowSeasonEpisode(row)
|
||||
if rowEpisode > 0 {
|
||||
existing[episodeKey(rowSeason, rowEpisode)] = struct{}{}
|
||||
continue
|
||||
}
|
||||
if rowEpisode <= 0 && isSeriesPackTitle(row.Title+" "+row.OriginalName+" "+row.Path) {
|
||||
hasSeriesPack = true
|
||||
}
|
||||
}
|
||||
if hasSeriesPack {
|
||||
return len(wanted) == 0
|
||||
}
|
||||
for _, ref := range wanted {
|
||||
if _, ok := existing[episodeKey(ref.Season, ref.Episode)]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func localMediaRowSeasonEpisode(row model.Media) (int, int) {
|
||||
rowSeason := row.SeasonNum
|
||||
rowEpisode := row.EpisodeNum
|
||||
if rowSeason <= 0 || rowEpisode <= 0 {
|
||||
parsedSeason, parsedEpisode := ParseEpisode(row.Path)
|
||||
if rowSeason <= 0 {
|
||||
rowSeason = parsedSeason
|
||||
}
|
||||
if rowEpisode <= 0 {
|
||||
rowEpisode = parsedEpisode
|
||||
}
|
||||
}
|
||||
if rowSeason <= 0 {
|
||||
rowSeason = 1
|
||||
}
|
||||
return rowSeason, rowEpisode
|
||||
}
|
||||
|
||||
func (d *DownloadService) findExistingDownloadTask(ctx context.Context, req downloadAddRequest) (*model.DownloadTask, bool) {
|
||||
key := downloadTaskIdentityKey(req.title)
|
||||
if key == "" || d == nil || d.repo == nil || d.repo.Download == nil {
|
||||
return nil, false
|
||||
}
|
||||
rows, err := d.repo.Download.List(ctx)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
subscriptionID := strings.TrimSpace(req.meta.SubscriptionID)
|
||||
for i := range rows {
|
||||
if subscriptionID != "" {
|
||||
if !downloadTaskBlocksReadd(rows[i].Status) {
|
||||
continue
|
||||
}
|
||||
if !downloadTaskInSubscriptionScope(rows[i], req) {
|
||||
continue
|
||||
}
|
||||
if !d.subscriptionDownloadTaskStillLive(ctx, rows[i]) {
|
||||
continue
|
||||
}
|
||||
} else if !downloadTaskBlocksDuplicate(rows[i].Status) {
|
||||
continue
|
||||
}
|
||||
current := downloadTaskIdentityKey(rows[i].Title)
|
||||
if downloadTaskCoversAddRequest(rows[i].Title, req) || current == key {
|
||||
return &rows[i], true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (d *DownloadService) subscriptionDownloadTaskStillLive(ctx context.Context, row model.DownloadTask) bool {
|
||||
live, ok := d.liveTorrentSnapshot(30 * time.Second)
|
||||
if !ok && d != nil && d.qb != nil && d.qb.IsConfigured() {
|
||||
var err error
|
||||
live, err = d.qb.List(ctx, "")
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
ok = true
|
||||
}
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
for _, torrent := range live {
|
||||
if downloadTaskMatchesLiveTorrent(row, torrent) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func downloadTaskMatchesLiveTorrent(row model.DownloadTask, torrent QBitTorrent) bool {
|
||||
torrentName := strings.TrimSpace(torrent.Name)
|
||||
if torrentName == "" {
|
||||
return false
|
||||
}
|
||||
req := downloadAddRequest{
|
||||
title: row.Title,
|
||||
savePath: row.SavePath,
|
||||
meta: DownloadTaskMeta{
|
||||
SubscriptionID: row.SubscriptionID,
|
||||
},
|
||||
}
|
||||
if downloadTaskCoversAddRequest(torrentName, req) {
|
||||
return true
|
||||
}
|
||||
rowKey := downloadTaskIdentityKey(row.Title)
|
||||
torrentKey := downloadTaskIdentityKey(torrentName)
|
||||
if rowKey != "" && torrentKey != "" {
|
||||
return rowKey == torrentKey
|
||||
}
|
||||
if len(episodeRefsFromTitle(row.Title)) > 0 || len(episodeRefsFromTitle(torrentName)) > 0 {
|
||||
return false
|
||||
}
|
||||
rowTorrentKey := normalizeTorrentName(row.Title)
|
||||
liveTorrentKey := normalizeTorrentName(torrentName)
|
||||
return rowTorrentKey != "" && rowTorrentKey == liveTorrentKey
|
||||
}
|
||||
|
||||
func downloadTaskCoversAddRequest(existing string, req downloadAddRequest) bool {
|
||||
if subscriptionRequestHasExplicitEpisodes(req) {
|
||||
return downloadExplicitEpisodesCoverRequest(existing, req.title)
|
||||
}
|
||||
return downloadTitleCoversRequest(existing, req.title)
|
||||
}
|
||||
|
||||
func subscriptionRequestHasExplicitEpisodes(req downloadAddRequest) bool {
|
||||
return strings.TrimSpace(req.meta.SubscriptionID) != "" && len(episodeRefsFromTitle(req.title)) > 0
|
||||
}
|
||||
|
||||
func downloadExplicitEpisodesCoverRequest(existing, requested string) bool {
|
||||
current := parseDownloadMediaIdentity(existing)
|
||||
want := parseDownloadMediaIdentity(requested)
|
||||
if current.TitleKey == "" || want.TitleKey == "" {
|
||||
return false
|
||||
}
|
||||
if current.TitleKey != want.TitleKey {
|
||||
return false
|
||||
}
|
||||
if current.Year > 0 && want.Year > 0 && current.Year != want.Year {
|
||||
return false
|
||||
}
|
||||
if len(current.Episodes) == 0 || len(want.Episodes) == 0 {
|
||||
return false
|
||||
}
|
||||
currentEpisodes := map[string]struct{}{}
|
||||
for _, ref := range current.Episodes {
|
||||
currentEpisodes[episodeKey(ref.Season, ref.Episode)] = struct{}{}
|
||||
}
|
||||
for _, ref := range want.Episodes {
|
||||
if _, ok := currentEpisodes[episodeKey(ref.Season, ref.Episode)]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func downloadTaskInSubscriptionScope(row model.DownloadTask, req downloadAddRequest) bool {
|
||||
subscriptionID := strings.TrimSpace(req.meta.SubscriptionID)
|
||||
if subscriptionID == "" {
|
||||
return true
|
||||
}
|
||||
rowSubscriptionID := strings.TrimSpace(row.SubscriptionID)
|
||||
if rowSubscriptionID != "" {
|
||||
return rowSubscriptionID == subscriptionID
|
||||
}
|
||||
rowSavePath := strings.TrimSpace(row.SavePath)
|
||||
requestSavePath := strings.TrimSpace(req.savePath)
|
||||
if rowSavePath == "" || requestSavePath == "" {
|
||||
return false
|
||||
}
|
||||
return sameOrChildPath(rowSavePath, requestSavePath) || sameOrChildPath(requestSavePath, rowSavePath)
|
||||
}
|
||||
|
||||
func (d *DownloadService) torrentExistsByIdentity(ctx context.Context, req downloadAddRequest) bool {
|
||||
query := downloadTaskIdentityKey(req.title)
|
||||
if query == "" {
|
||||
return false
|
||||
}
|
||||
live, err := d.qb.List(ctx, "")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, torrent := range live {
|
||||
if !torrentInDownloadRequestScope(torrent, req) {
|
||||
continue
|
||||
}
|
||||
if downloadTaskCoversAddRequest(torrent.Name, req) {
|
||||
return true
|
||||
}
|
||||
current := downloadTaskIdentityKey(torrent.Name)
|
||||
if current == "" {
|
||||
continue
|
||||
}
|
||||
if current == query {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func torrentInDownloadRequestScope(torrent QBitTorrent, req downloadAddRequest) bool {
|
||||
if strings.TrimSpace(req.meta.SubscriptionID) == "" {
|
||||
return true
|
||||
}
|
||||
requestSavePath := strings.TrimSpace(req.savePath)
|
||||
torrentSavePath := strings.TrimSpace(torrent.SavePath)
|
||||
if requestSavePath == "" || torrentSavePath == "" {
|
||||
return false
|
||||
}
|
||||
return sameOrChildPath(torrentSavePath, requestSavePath) || sameOrChildPath(requestSavePath, torrentSavePath)
|
||||
}
|
||||
|
||||
func (d *DownloadService) linkExistingDownloadTaskToSubscription(ctx context.Context, task *model.DownloadTask, req downloadAddRequest) {
|
||||
subscriptionID := strings.TrimSpace(req.meta.SubscriptionID)
|
||||
if d == nil || d.repo == nil || d.repo.DB == nil || task == nil || subscriptionID == "" || strings.TrimSpace(task.ID) == "" {
|
||||
return
|
||||
}
|
||||
updates := map[string]any{}
|
||||
if strings.TrimSpace(task.SubscriptionID) == "" {
|
||||
updates["subscription_id"] = subscriptionID
|
||||
task.SubscriptionID = subscriptionID
|
||||
}
|
||||
if strings.TrimSpace(task.MediaType) == "" && strings.TrimSpace(req.meta.MediaType) != "" {
|
||||
updates["media_type"] = req.meta.MediaType
|
||||
task.MediaType = req.meta.MediaType
|
||||
}
|
||||
if strings.TrimSpace(task.MediaCategory) == "" && strings.TrimSpace(req.meta.MediaCategory) != "" {
|
||||
updates["media_category"] = req.meta.MediaCategory
|
||||
task.MediaCategory = req.meta.MediaCategory
|
||||
}
|
||||
if strings.TrimSpace(task.PosterURL) == "" && strings.TrimSpace(req.meta.PosterURL) != "" {
|
||||
updates["poster_url"] = req.meta.PosterURL
|
||||
task.PosterURL = req.meta.PosterURL
|
||||
}
|
||||
if strings.TrimSpace(task.BackdropURL) == "" && strings.TrimSpace(req.meta.BackdropURL) != "" {
|
||||
updates["backdrop_url"] = req.meta.BackdropURL
|
||||
task.BackdropURL = req.meta.BackdropURL
|
||||
}
|
||||
if strings.TrimSpace(task.Overview) == "" && strings.TrimSpace(req.meta.Overview) != "" {
|
||||
updates["overview"] = req.meta.Overview
|
||||
task.Overview = req.meta.Overview
|
||||
}
|
||||
if !task.AllowExistingLibrary && req.meta.AllowExistingLibrary {
|
||||
updates["allow_existing_library"] = true
|
||||
task.AllowExistingLibrary = true
|
||||
}
|
||||
if len(updates) == 0 {
|
||||
return
|
||||
}
|
||||
_ = d.repo.DB.WithContext(ctx).Model(&model.DownloadTask{}).Where("id = ?", task.ID).Updates(updates).Error
|
||||
}
|
||||
|
||||
func (d *DownloadService) createTask(ctx context.Context, userID, urlStr, savePath string, meta DownloadTaskMeta) (*model.DownloadTask, error) {
|
||||
title := strings.TrimSpace(meta.Title)
|
||||
if title == "" {
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ShukeBta/MediaStationGo/internal/model"
|
||||
)
|
||||
|
||||
func (d *DownloadService) findExistingDownloadTask(ctx context.Context, req downloadAddRequest) (*model.DownloadTask, bool) {
|
||||
key := downloadTaskIdentityKey(req.title)
|
||||
if key == "" || d == nil || d.repo == nil || d.repo.Download == nil {
|
||||
return nil, false
|
||||
}
|
||||
rows, err := d.repo.Download.List(ctx)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
subscriptionID := strings.TrimSpace(req.meta.SubscriptionID)
|
||||
for i := range rows {
|
||||
if subscriptionID != "" {
|
||||
if !downloadTaskBlocksReadd(rows[i].Status) {
|
||||
continue
|
||||
}
|
||||
if !downloadTaskInSubscriptionScope(rows[i], req) {
|
||||
continue
|
||||
}
|
||||
if !d.subscriptionDownloadTaskStillLive(ctx, rows[i]) {
|
||||
continue
|
||||
}
|
||||
} else if !downloadTaskBlocksDuplicate(rows[i].Status) {
|
||||
continue
|
||||
}
|
||||
current := downloadTaskIdentityKey(rows[i].Title)
|
||||
if downloadTaskCoversAddRequest(rows[i].Title, req) || current == key {
|
||||
return &rows[i], true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (d *DownloadService) subscriptionDownloadTaskStillLive(ctx context.Context, row model.DownloadTask) bool {
|
||||
live, ok := d.liveTorrentSnapshot(30 * time.Second)
|
||||
if !ok && d != nil && d.qb != nil && d.qb.IsConfigured() {
|
||||
var err error
|
||||
live, err = d.qb.List(ctx, "")
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
ok = true
|
||||
}
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
for _, torrent := range live {
|
||||
if downloadTaskMatchesLiveTorrent(row, torrent) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func downloadTaskMatchesLiveTorrent(row model.DownloadTask, torrent QBitTorrent) bool {
|
||||
torrentName := strings.TrimSpace(torrent.Name)
|
||||
if torrentName == "" {
|
||||
return false
|
||||
}
|
||||
req := downloadAddRequest{
|
||||
title: row.Title,
|
||||
savePath: row.SavePath,
|
||||
meta: DownloadTaskMeta{
|
||||
SubscriptionID: row.SubscriptionID,
|
||||
},
|
||||
}
|
||||
if downloadTaskCoversAddRequest(torrentName, req) {
|
||||
return true
|
||||
}
|
||||
rowKey := downloadTaskIdentityKey(row.Title)
|
||||
torrentKey := downloadTaskIdentityKey(torrentName)
|
||||
if rowKey != "" && torrentKey != "" {
|
||||
return rowKey == torrentKey
|
||||
}
|
||||
if len(episodeRefsFromTitle(row.Title)) > 0 || len(episodeRefsFromTitle(torrentName)) > 0 {
|
||||
return false
|
||||
}
|
||||
rowTorrentKey := normalizeTorrentName(row.Title)
|
||||
liveTorrentKey := normalizeTorrentName(torrentName)
|
||||
return rowTorrentKey != "" && rowTorrentKey == liveTorrentKey
|
||||
}
|
||||
|
||||
func downloadTaskCoversAddRequest(existing string, req downloadAddRequest) bool {
|
||||
if subscriptionRequestHasExplicitEpisodes(req) {
|
||||
return downloadExplicitEpisodesCoverRequest(existing, req.title)
|
||||
}
|
||||
return downloadTitleCoversRequest(existing, req.title)
|
||||
}
|
||||
|
||||
func subscriptionRequestHasExplicitEpisodes(req downloadAddRequest) bool {
|
||||
return strings.TrimSpace(req.meta.SubscriptionID) != "" && len(episodeRefsFromTitle(req.title)) > 0
|
||||
}
|
||||
|
||||
func downloadExplicitEpisodesCoverRequest(existing, requested string) bool {
|
||||
current := parseDownloadMediaIdentity(existing)
|
||||
want := parseDownloadMediaIdentity(requested)
|
||||
if current.TitleKey == "" || want.TitleKey == "" {
|
||||
return false
|
||||
}
|
||||
if current.TitleKey != want.TitleKey {
|
||||
return false
|
||||
}
|
||||
if current.Year > 0 && want.Year > 0 && current.Year != want.Year {
|
||||
return false
|
||||
}
|
||||
if len(current.Episodes) == 0 || len(want.Episodes) == 0 {
|
||||
return false
|
||||
}
|
||||
currentEpisodes := map[string]struct{}{}
|
||||
for _, ref := range current.Episodes {
|
||||
currentEpisodes[episodeKey(ref.Season, ref.Episode)] = struct{}{}
|
||||
}
|
||||
for _, ref := range want.Episodes {
|
||||
if _, ok := currentEpisodes[episodeKey(ref.Season, ref.Episode)]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func downloadTaskInSubscriptionScope(row model.DownloadTask, req downloadAddRequest) bool {
|
||||
subscriptionID := strings.TrimSpace(req.meta.SubscriptionID)
|
||||
if subscriptionID == "" {
|
||||
return true
|
||||
}
|
||||
rowSubscriptionID := strings.TrimSpace(row.SubscriptionID)
|
||||
if rowSubscriptionID != "" {
|
||||
return rowSubscriptionID == subscriptionID
|
||||
}
|
||||
rowSavePath := strings.TrimSpace(row.SavePath)
|
||||
requestSavePath := strings.TrimSpace(req.savePath)
|
||||
if rowSavePath == "" || requestSavePath == "" {
|
||||
return false
|
||||
}
|
||||
return sameOrChildPath(rowSavePath, requestSavePath) || sameOrChildPath(requestSavePath, rowSavePath)
|
||||
}
|
||||
|
||||
func (d *DownloadService) torrentExistsByIdentity(ctx context.Context, req downloadAddRequest) bool {
|
||||
query := downloadTaskIdentityKey(req.title)
|
||||
if query == "" {
|
||||
return false
|
||||
}
|
||||
live, err := d.qb.List(ctx, "")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for _, torrent := range live {
|
||||
if !torrentInDownloadRequestScope(torrent, req) {
|
||||
continue
|
||||
}
|
||||
if downloadTaskCoversAddRequest(torrent.Name, req) {
|
||||
return true
|
||||
}
|
||||
current := downloadTaskIdentityKey(torrent.Name)
|
||||
if current == "" {
|
||||
continue
|
||||
}
|
||||
if current == query {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func torrentInDownloadRequestScope(torrent QBitTorrent, req downloadAddRequest) bool {
|
||||
if strings.TrimSpace(req.meta.SubscriptionID) == "" {
|
||||
return true
|
||||
}
|
||||
requestSavePath := strings.TrimSpace(req.savePath)
|
||||
torrentSavePath := strings.TrimSpace(torrent.SavePath)
|
||||
if requestSavePath == "" || torrentSavePath == "" {
|
||||
return false
|
||||
}
|
||||
return sameOrChildPath(torrentSavePath, requestSavePath) || sameOrChildPath(requestSavePath, torrentSavePath)
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ShukeBta/MediaStationGo/internal/model"
|
||||
)
|
||||
|
||||
func (d *DownloadService) localMediaAlreadyExists(ctx context.Context, title string) bool {
|
||||
rows, ok := d.localMediaAvailabilityRows(ctx, title)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return localMediaRowsMatchDownloadTitle(title, rows)
|
||||
}
|
||||
|
||||
func (d *DownloadService) localMediaAvailabilityRows(ctx context.Context, title string) ([]model.Media, bool) {
|
||||
if d == nil || d.repo == nil || d.repo.DB == nil {
|
||||
return nil, false
|
||||
}
|
||||
if !d.repo.DB.Migrator().HasTable(&model.Media{}) {
|
||||
return nil, false
|
||||
}
|
||||
queries := localAvailabilityTitleCandidates(title)
|
||||
if len(queries) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
var rows []model.Media
|
||||
db := d.repo.DB.WithContext(ctx).Model(&model.Media{})
|
||||
for i, query := range queries {
|
||||
like := "%" + query + "%"
|
||||
clause := "title LIKE ? OR original_name LIKE ? OR path LIKE ?"
|
||||
if i == 0 {
|
||||
db = db.Where(clause, like, like, like)
|
||||
} else {
|
||||
db = db.Or(clause, like, like, like)
|
||||
}
|
||||
}
|
||||
if err := db.
|
||||
Order("season_num asc, episode_num asc, created_at desc").
|
||||
Limit(200).
|
||||
Find(&rows).Error; err != nil || len(rows) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
return rows, true
|
||||
}
|
||||
|
||||
func localMediaRowsMatchDownloadTitle(title string, rows []model.Media) bool {
|
||||
wanted := episodeRefsFromTitle(title)
|
||||
if len(wanted) == 0 {
|
||||
return true
|
||||
}
|
||||
existing := map[string]struct{}{}
|
||||
hasSeriesPack := false
|
||||
for _, row := range rows {
|
||||
rowSeason, rowEpisode := localMediaRowSeasonEpisode(row)
|
||||
if rowEpisode > 0 {
|
||||
existing[episodeKey(rowSeason, rowEpisode)] = struct{}{}
|
||||
continue
|
||||
}
|
||||
if rowEpisode <= 0 && isSeriesPackTitle(row.Title+" "+row.OriginalName+" "+row.Path) {
|
||||
hasSeriesPack = true
|
||||
}
|
||||
}
|
||||
if hasSeriesPack {
|
||||
return len(wanted) == 0
|
||||
}
|
||||
for _, ref := range wanted {
|
||||
if _, ok := existing[episodeKey(ref.Season, ref.Episode)]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func localMediaRowSeasonEpisode(row model.Media) (int, int) {
|
||||
rowSeason := row.SeasonNum
|
||||
rowEpisode := row.EpisodeNum
|
||||
if rowSeason <= 0 || rowEpisode <= 0 {
|
||||
parsedSeason, parsedEpisode := ParseEpisode(row.Path)
|
||||
if rowSeason <= 0 {
|
||||
rowSeason = parsedSeason
|
||||
}
|
||||
if rowEpisode <= 0 {
|
||||
rowEpisode = parsedEpisode
|
||||
}
|
||||
}
|
||||
if rowSeason <= 0 {
|
||||
rowSeason = 1
|
||||
}
|
||||
return rowSeason, rowEpisode
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/ShukeBta/MediaStationGo/internal/model"
|
||||
)
|
||||
|
||||
func (d *DownloadService) linkExistingDownloadTaskToSubscription(ctx context.Context, task *model.DownloadTask, req downloadAddRequest) {
|
||||
subscriptionID := strings.TrimSpace(req.meta.SubscriptionID)
|
||||
if d == nil || d.repo == nil || d.repo.DB == nil || task == nil || subscriptionID == "" || strings.TrimSpace(task.ID) == "" {
|
||||
return
|
||||
}
|
||||
updates := map[string]any{}
|
||||
if strings.TrimSpace(task.SubscriptionID) == "" {
|
||||
updates["subscription_id"] = subscriptionID
|
||||
task.SubscriptionID = subscriptionID
|
||||
}
|
||||
if strings.TrimSpace(task.MediaType) == "" && strings.TrimSpace(req.meta.MediaType) != "" {
|
||||
updates["media_type"] = req.meta.MediaType
|
||||
task.MediaType = req.meta.MediaType
|
||||
}
|
||||
if strings.TrimSpace(task.MediaCategory) == "" && strings.TrimSpace(req.meta.MediaCategory) != "" {
|
||||
updates["media_category"] = req.meta.MediaCategory
|
||||
task.MediaCategory = req.meta.MediaCategory
|
||||
}
|
||||
if strings.TrimSpace(task.PosterURL) == "" && strings.TrimSpace(req.meta.PosterURL) != "" {
|
||||
updates["poster_url"] = req.meta.PosterURL
|
||||
task.PosterURL = req.meta.PosterURL
|
||||
}
|
||||
if strings.TrimSpace(task.BackdropURL) == "" && strings.TrimSpace(req.meta.BackdropURL) != "" {
|
||||
updates["backdrop_url"] = req.meta.BackdropURL
|
||||
task.BackdropURL = req.meta.BackdropURL
|
||||
}
|
||||
if strings.TrimSpace(task.Overview) == "" && strings.TrimSpace(req.meta.Overview) != "" {
|
||||
updates["overview"] = req.meta.Overview
|
||||
task.Overview = req.meta.Overview
|
||||
}
|
||||
if !task.AllowExistingLibrary && req.meta.AllowExistingLibrary {
|
||||
updates["allow_existing_library"] = true
|
||||
task.AllowExistingLibrary = true
|
||||
}
|
||||
if len(updates) == 0 {
|
||||
return
|
||||
}
|
||||
_ = d.repo.DB.WithContext(ctx).Model(&model.DownloadTask{}).Where("id = ?", task.ID).Updates(updates).Error
|
||||
}
|
||||
Reference in New Issue
Block a user