122 lines
3.2 KiB
Go
122 lines
3.2 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"watch-party-backend/internal/core/episode"
|
|
)
|
|
|
|
// Service implements the episode.UseCases port.
|
|
type Service struct {
|
|
repo episode.Repository
|
|
}
|
|
|
|
func NewEpisodeService(r episode.Repository) *Service {
|
|
return &Service{repo: r}
|
|
}
|
|
|
|
func (s *Service) ListAll(ctx context.Context) ([]episode.Episode, error) {
|
|
c, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
defer cancel()
|
|
return s.repo.ListAll(c)
|
|
}
|
|
|
|
func (s *Service) ListArchive(ctx context.Context) ([]episode.ArchiveEpisode, error) {
|
|
c, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
defer cancel()
|
|
return s.repo.ListArchive(c)
|
|
}
|
|
|
|
func (s *Service) GetCurrent(ctx context.Context) (episode.Episode, error) {
|
|
c, cancel := context.WithTimeout(ctx, 3*time.Second)
|
|
defer cancel()
|
|
return s.repo.GetCurrent(c)
|
|
}
|
|
|
|
var hhmmss = regexp.MustCompile(`^(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$`)
|
|
|
|
const defaultStartTime = "22:00:00"
|
|
|
|
func parseHHMMSSToDuration(hhmmss string) (time.Duration, error) {
|
|
parts := strings.Split(hhmmss, ":")
|
|
if len(parts) != 3 {
|
|
return 0, episode.ErrInvalidPlayback
|
|
}
|
|
hours, err := time.ParseDuration(parts[0] + "h")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
mins, err := time.ParseDuration(parts[1] + "m")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
secs, err := time.ParseDuration(parts[2] + "s")
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return hours + mins + secs, nil
|
|
}
|
|
|
|
func (s *Service) SetCurrent(ctx context.Context, id int64, start string) (episode.Episode, error) {
|
|
if !hhmmss.MatchString(start) {
|
|
return episode.Episode{}, episode.ErrInvalidStartTime
|
|
}
|
|
c, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
defer cancel()
|
|
if err := s.repo.SetCurrent(c, id, start); err != nil {
|
|
return episode.Episode{}, err
|
|
}
|
|
return s.repo.GetCurrent(c)
|
|
}
|
|
|
|
func (s *Service) Create(ctx context.Context, in episode.NewShowInput) (episode.Episode, error) {
|
|
if in.EpNum <= 0 || strings.TrimSpace(in.EpTitle) == "" || strings.TrimSpace(in.SeasonName) == "" {
|
|
return episode.Episode{}, episode.ErrInvalidShowInput
|
|
}
|
|
in.StartTime = strings.TrimSpace(in.StartTime)
|
|
if in.StartTime == "" {
|
|
in.StartTime = defaultStartTime
|
|
}
|
|
if !hhmmss.MatchString(in.StartTime) {
|
|
return episode.Episode{}, episode.ErrInvalidStartTime
|
|
}
|
|
if !hhmmss.MatchString(in.PlaybackLength) {
|
|
return episode.Episode{}, episode.ErrInvalidPlayback
|
|
}
|
|
dur, err := parseHHMMSSToDuration(in.PlaybackLength)
|
|
if err != nil || dur <= 0 {
|
|
return episode.Episode{}, episode.ErrInvalidPlayback
|
|
}
|
|
|
|
c, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
defer cancel()
|
|
return s.repo.Create(c, in)
|
|
}
|
|
|
|
func (s *Service) MoveToArchive(ctx context.Context, ids []int64) (episode.MoveResult, error) {
|
|
uniq := make([]int64, 0, len(ids))
|
|
seen := make(map[int64]struct{}, len(ids))
|
|
for _, id := range ids {
|
|
if _, ok := seen[id]; !ok {
|
|
seen[id] = struct{}{}
|
|
uniq = append(uniq, id)
|
|
}
|
|
}
|
|
if len(uniq) == 0 {
|
|
return episode.MoveResult{}, episode.ErrEmptyIDs
|
|
}
|
|
|
|
c, cancel := context.WithTimeout(ctx, 10*time.Second)
|
|
defer cancel()
|
|
return s.repo.MoveToArchive(c, uniq)
|
|
}
|
|
|
|
func (s *Service) Delete(ctx context.Context, id int64) error {
|
|
c, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
defer cancel()
|
|
return s.repo.Delete(c, id)
|
|
}
|