diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-17 15:08:16 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-17 15:08:16 +0300 |
| commit | 29188f031ff4c83e28b021ac5ffbc780e9a92a22 (patch) | |
| tree | 2301490c18b35f97f915ae4c575b045205d0e837 /internal/service/progress.go | |
| parent | a96f53c30341baf96ff2c791f7e5689de756ae9b (diff) | |
Add progress service completion methods
Diffstat (limited to 'internal/service/progress.go')
| -rw-r--r-- | internal/service/progress.go | 88 |
1 files changed, 84 insertions, 4 deletions
diff --git a/internal/service/progress.go b/internal/service/progress.go index ef248cf..4e79aa5 100644 --- a/internal/service/progress.go +++ b/internal/service/progress.go @@ -12,15 +12,17 @@ import ( // progressService is the concrete implementation of ProgressService. type progressService struct { - store repository.ProgressServiceStore - clock clock.Clock + store repository.ProgressServiceStore + helper *accessHelper + clock clock.Clock } // NewProgressService creates a concrete ProgressService. func NewProgressService(store repository.ProgressServiceStore, clk clock.Clock) *progressService { return &progressService{ - store: store, - clock: clk, + store: store, + helper: NewAccessHelper(store), + clock: clk, } } @@ -82,3 +84,81 @@ func (s *progressService) UpdateProgress(ctx context.Context, sessionID string, return nil } + +func (s *progressService) MarkFinished(ctx context.Context, userID, mediaID int64) error { + if mediaID == 0 { + return errors.New("media_id required") + } + + media, err := s.helper.verifyAccess(ctx, mediaID, userID) + if err != nil { + return err + } + + if err := s.store.UpsertProgress(ctx, &model.PlaybackProgress{ + UserID: userID, + MediaID: mediaID, + PositionSeconds: media.Duration, + Finished: true, + UpdatedAt: s.clock.Now(), + }); err != nil { + return fmt.Errorf("mark finished: %w", err) + } + + return nil +} + +func (s *progressService) MarkNotStarted(ctx context.Context, userID, mediaID int64) error { + if mediaID == 0 { + return errors.New("media_id required") + } + + if _, err := s.helper.verifyAccess(ctx, mediaID, userID); err != nil { + return err + } + + if err := s.store.DeleteProgress(ctx, userID, mediaID); err != nil { + return fmt.Errorf("delete progress: %w", err) + } + if err := s.store.DeleteAccumulatorByMedia(ctx, mediaID); err != nil { + return fmt.Errorf("delete accumulator: %w", err) + } + + return nil +} + +func (s *progressService) ListInProgress(ctx context.Context, userID int64) ([]model.Media, error) { + allowed, err := s.helper.allowedSetIDs(ctx, userID) + if err != nil { + return nil, err + } + if allowed != nil && len(allowed) == 0 { + return []model.Media{}, nil + } + + return s.store.ListInProgressMedia(ctx, userID, repository.MediaFilter{ + AllowedSetIDs: allowed, + }) +} + +func (h *accessHelper) allowedSetIDs(ctx context.Context, userID int64) ([]int64, error) { + user, err := h.store.GetUserByID(ctx, userID) + if err != nil { + return nil, fmt.Errorf("get user: %w", err) + } + if user != nil && user.IsAdmin { + return nil, nil + } + + perms, err := h.store.ListPermissionsByUser(ctx, userID) + if err != nil { + return nil, fmt.Errorf("list permissions: %w", err) + } + + allowed := make([]int64, 0, len(perms)) + for _, p := range perms { + allowed = append(allowed, p.SetID) + } + + return allowed, nil +} |
