mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-10 15:26:38 +08:00
refactor: split modules and harden scraping workflows
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ShukeBta/MediaStationGo/internal/model"
|
||||
)
|
||||
|
||||
type embySeriesGroup struct {
|
||||
ID string
|
||||
LibraryID string
|
||||
Name string
|
||||
PosterURL string
|
||||
BackdropURL string
|
||||
Overview string
|
||||
Rating float32
|
||||
Year int
|
||||
TMDbID int
|
||||
BangumiID int
|
||||
CreatedAt time.Time
|
||||
Episodes []model.Media
|
||||
}
|
||||
|
||||
type embySeasonGroup struct {
|
||||
ID string
|
||||
SeriesID string
|
||||
LibraryID string
|
||||
Name string
|
||||
SeasonNum int
|
||||
Series embySeriesGroup
|
||||
Episodes []model.Media
|
||||
}
|
||||
|
||||
func (e *EmbyService) findSeriesGroup(ctx context.Context, id, userID string) (embySeriesGroup, bool, error) {
|
||||
if strings.TrimSpace(id) == "" {
|
||||
return embySeriesGroup{}, false, nil
|
||||
}
|
||||
if strings.HasPrefix(id, embyVirtualSeriesPrefix) {
|
||||
if group, ok := e.cachedSeriesGroup(id); ok {
|
||||
return group, true, nil
|
||||
}
|
||||
}
|
||||
var rows []model.Media
|
||||
q := e.repo.DB.WithContext(ctx).Model(&model.Media{}).Where("season_num > 0 OR episode_num > 0")
|
||||
q = e.applyUserMediaVisibility(ctx, q, userID)
|
||||
if !strings.HasPrefix(id, embyVirtualSeriesPrefix) {
|
||||
q = q.Where("series_id = ?", id)
|
||||
}
|
||||
if err := q.Order("media.season_num asc, media.episode_num asc, media.created_at asc").Limit(embySeriesGroupingLimit).Find(&rows).Error; err != nil {
|
||||
return embySeriesGroup{}, false, err
|
||||
}
|
||||
for _, group := range e.seriesGroupsFromMedia(rows) {
|
||||
if group.ID == id {
|
||||
e.rememberSeriesGroup(group)
|
||||
return group, true, nil
|
||||
}
|
||||
}
|
||||
if !strings.HasPrefix(id, embyVirtualSeriesPrefix) {
|
||||
if series, err := e.repo.Series.FindByID(ctx, id); err != nil {
|
||||
return embySeriesGroup{}, false, err
|
||||
} else if series != nil {
|
||||
return embySeriesGroup{
|
||||
ID: series.ID,
|
||||
LibraryID: series.LibraryID,
|
||||
Name: series.Title,
|
||||
PosterURL: series.PosterURL,
|
||||
BackdropURL: series.BackdropURL,
|
||||
Overview: series.Overview,
|
||||
Rating: series.Rating,
|
||||
Year: series.Year,
|
||||
TMDbID: series.TMDbID,
|
||||
BangumiID: series.BangumiID,
|
||||
CreatedAt: series.CreatedAt,
|
||||
}, true, nil
|
||||
}
|
||||
}
|
||||
return embySeriesGroup{}, false, nil
|
||||
}
|
||||
|
||||
func (e *EmbyService) findSeasonGroup(ctx context.Context, id, userID string) (embySeasonGroup, bool, error) {
|
||||
if strings.TrimSpace(id) == "" || !strings.HasPrefix(id, embyVirtualSeasonPrefix) {
|
||||
return embySeasonGroup{}, false, nil
|
||||
}
|
||||
if season, ok := e.cachedSeasonGroup(id); ok {
|
||||
return season, true, nil
|
||||
}
|
||||
var rows []model.Media
|
||||
q := e.repo.DB.WithContext(ctx).Model(&model.Media{}).
|
||||
Where("season_num > 0 OR episode_num > 0")
|
||||
q = e.applyUserMediaVisibility(ctx, q, userID)
|
||||
if err := q.
|
||||
Order("media.season_num asc, media.episode_num asc, media.created_at asc").
|
||||
Limit(embySeriesGroupingLimit).
|
||||
Find(&rows).Error; err != nil {
|
||||
return embySeasonGroup{}, false, err
|
||||
}
|
||||
for _, series := range e.seriesGroupsFromMedia(rows) {
|
||||
for _, season := range e.seasonsForSeries(series) {
|
||||
if season.ID == id {
|
||||
e.rememberSeriesGroup(series)
|
||||
return season, true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return embySeasonGroup{}, false, nil
|
||||
}
|
||||
|
||||
func (e *EmbyService) seriesGroupsFromMedia(rows []model.Media) []embySeriesGroup {
|
||||
byID := map[string]*embySeriesGroup{}
|
||||
order := []string{}
|
||||
for _, row := range rows {
|
||||
row := row
|
||||
seriesID := e.seriesIDForMedia(&row)
|
||||
group, ok := byID[seriesID]
|
||||
if !ok {
|
||||
group = &embySeriesGroup{
|
||||
ID: seriesID,
|
||||
LibraryID: row.LibraryID,
|
||||
Name: e.seriesNameForMedia(&row),
|
||||
Year: row.Year,
|
||||
TMDbID: row.TMDbID,
|
||||
BangumiID: row.BangumiID,
|
||||
CreatedAt: row.CreatedAt,
|
||||
}
|
||||
byID[seriesID] = group
|
||||
order = append(order, seriesID)
|
||||
}
|
||||
if row.CreatedAt.After(group.CreatedAt) {
|
||||
group.CreatedAt = row.CreatedAt
|
||||
}
|
||||
if group.PosterURL == "" && row.PosterURL != "" {
|
||||
group.PosterURL = row.PosterURL
|
||||
}
|
||||
if group.BackdropURL == "" && row.BackdropURL != "" {
|
||||
group.BackdropURL = row.BackdropURL
|
||||
}
|
||||
if group.Overview == "" && row.Overview != "" {
|
||||
group.Overview = row.Overview
|
||||
}
|
||||
if group.Rating == 0 && row.Rating > 0 {
|
||||
group.Rating = row.Rating
|
||||
}
|
||||
if group.Year == 0 && row.Year > 0 {
|
||||
group.Year = row.Year
|
||||
}
|
||||
group.Episodes = append(group.Episodes, row)
|
||||
}
|
||||
groups := make([]embySeriesGroup, 0, len(order))
|
||||
for _, id := range order {
|
||||
group := *byID[id]
|
||||
sort.SliceStable(group.Episodes, func(i, j int) bool {
|
||||
if group.Episodes[i].SeasonNum != group.Episodes[j].SeasonNum {
|
||||
return group.Episodes[i].SeasonNum < group.Episodes[j].SeasonNum
|
||||
}
|
||||
if group.Episodes[i].EpisodeNum != group.Episodes[j].EpisodeNum {
|
||||
return group.Episodes[i].EpisodeNum < group.Episodes[j].EpisodeNum
|
||||
}
|
||||
return group.Episodes[i].CreatedAt.Before(group.Episodes[j].CreatedAt)
|
||||
})
|
||||
groups = append(groups, group)
|
||||
}
|
||||
return groups
|
||||
}
|
||||
|
||||
func (e *EmbyService) seasonsForSeries(series embySeriesGroup) []embySeasonGroup {
|
||||
bySeason := map[int]*embySeasonGroup{}
|
||||
order := []int{}
|
||||
for _, episode := range series.Episodes {
|
||||
seasonNum := episode.SeasonNum
|
||||
if seasonNum < 0 {
|
||||
seasonNum = 1
|
||||
}
|
||||
season, ok := bySeason[seasonNum]
|
||||
if !ok {
|
||||
season = &embySeasonGroup{
|
||||
ID: seasonID(series.ID, seasonNum),
|
||||
SeriesID: series.ID,
|
||||
LibraryID: series.LibraryID,
|
||||
Name: seasonName(seasonNum),
|
||||
SeasonNum: seasonNum,
|
||||
Series: series,
|
||||
}
|
||||
bySeason[seasonNum] = season
|
||||
order = append(order, seasonNum)
|
||||
}
|
||||
season.Episodes = append(season.Episodes, episode)
|
||||
}
|
||||
sort.Ints(order)
|
||||
out := make([]embySeasonGroup, 0, len(order))
|
||||
for _, seasonNum := range order {
|
||||
out = append(out, *bySeason[seasonNum])
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user