package service import ( "context" "errors" "strconv" "strings" "time" "gorm.io/gorm" "github.com/ShukeBta/MediaStationGo/internal/model" ) // SetFavorite 把 mediaID 标为 userID 的收藏。 func (e *EmbyService) SetFavorite(ctx context.Context, userID, mediaID string, favorite bool) error { if favorite { var f model.Favorite err := e.repo.DB.WithContext(ctx). Where("user_id = ? AND media_id = ?", userID, mediaID).First(&f).Error if errors.Is(err, gorm.ErrRecordNotFound) { return e.repo.DB.WithContext(ctx).Create(&model.Favorite{ UserID: userID, MediaID: mediaID, }).Error } return err } return e.repo.DB.WithContext(ctx). Where("user_id = ? AND media_id = ?", userID, mediaID). Delete(&model.Favorite{}).Error } // MarkPlayed 把 mediaID 标为已看(写一个 100% 进度的 history 行)。 func (e *EmbyService) MarkPlayed(ctx context.Context, userID, mediaID string, played bool) error { if !played { return e.repo.DB.WithContext(ctx). Where("user_id = ? AND media_id = ?", userID, mediaID). Delete(&model.PlaybackHistory{}).Error } m, err := e.repo.Media.FindByID(ctx, mediaID) if err != nil || m == nil { return errors.New("media not found") } dur := int64(m.DurationSec) * 1000 if dur <= 0 { dur = 1 } return e.repo.History.Upsert(ctx, &model.PlaybackHistory{ UserID: userID, MediaID: mediaID, PositionMs: dur, DurationMs: dur, WatchedAt: time.Now(), Completed: true, }) } // RecordProgress 记录播放进度(来自 Emby 客户端的 /Sessions/Playing/Progress)。 func (e *EmbyService) RecordProgress(ctx context.Context, userID, mediaID string, positionTicks, runtimeTicks int64) error { pos := positionTicks / 10_000 dur := runtimeTicks / 10_000 if dur <= 0 { // runtimeTicks 缺失时回退到 media.DurationSec if m, _ := e.repo.Media.FindByID(ctx, mediaID); m != nil { dur = int64(m.DurationSec) * 1000 } } completed := dur > 0 && pos >= dur*9/10 return e.repo.History.Upsert(ctx, &model.PlaybackHistory{ UserID: userID, MediaID: mediaID, PositionMs: pos, DurationMs: dur, WatchedAt: time.Now(), Completed: completed, }) } func splitCSV(s string) []string { if strings.TrimSpace(s) == "" { return []string{} } parts := strings.Split(s, ",") out := make([]string, 0, len(parts)) for _, p := range parts { p = strings.TrimSpace(p) if p != "" { out = append(out, p) } } return out } func intToStr(v int) string { if v == 0 { return "" } return strconv.Itoa(v) }