1package service23import (4 "context"5 "errors"67 "airwaves/internal/podcast"8 "airwaves/internal/stream"9)1011// ErrNoPodcasts is returned by the Podcasts app's calls on a server12// without it.13var ErrNoPodcasts = errors.New("this Airwaves server has no podcasts")1415// Podcasts is the Podcasts app's library: its shows and their episodes.16func (s *Service) Podcasts(context.Context) (*podcast.State, error) {17 if s.podcasts == nil {18 return nil, ErrNoPodcasts19 }20 st := s.podcasts.State()21 return &st, nil22}2324// RefreshPodcasts lists every show again now, and returns the library25// as refreshed.26func (s *Service) RefreshPodcasts(ctx context.Context) (*podcast.State, error) {27 if s.podcasts == nil {28 return nil, ErrNoPodcasts29 }30 st := s.podcasts.Refresh(ctx)31 return &st, nil32}3334// SearchPodcasts finds YouTube channels to add as shows.35func (s *Service) SearchPodcasts(ctx context.Context, query string) ([]podcast.Found, error) {36 if s.podcasts == nil {37 return nil, ErrNoPodcasts38 }39 return s.podcasts.Search(ctx, query)40}4142// AddPodcast adds a show: a YouTube channel, its live streams' tab, or a43// playlist; minMinutes is the shortest video that's an episode, 0 for the44// default.45func (s *Service) AddPodcast(ctx context.Context, url string, minMinutes float64) (*podcast.Show, error) {46 if s.podcasts == nil {47 return nil, ErrNoPodcasts48 }49 show, err := s.podcasts.Add(ctx, url, minMinutes)50 if err != nil {51 return nil, err52 }53 return &show, nil54}5556// RemovePodcast takes a show out of the library.57func (s *Service) RemovePodcast(_ context.Context, id string) error {58 if s.podcasts == nil {59 return ErrNoPodcasts60 }61 return s.podcasts.Remove(id)62}6364// PlayEpisode streams an episode to client from from seconds in.65func (s *Service) PlayEpisode(ctx context.Context, client, id string, from float64) (*stream.Playback, error) {66 if s.podcasts == nil {67 return nil, ErrNoPodcasts68 }69 if s.streamErr != nil {70 return nil, s.streamErr71 }72 in, err := s.podcasts.Input(ctx, id, from)73 if err != nil {74 return nil, err75 }76 return s.streams.Start(ctx, client, in)77}7879// EpisodeProgress records how far an episode has been watched, and80// whether it has.81func (s *Service) EpisodeProgress(_ context.Context, id string, position, duration float64, watched bool) error {82 if s.podcasts == nil {83 return ErrNoPodcasts84 }85 return s.podcasts.Progress(id, position, duration, watched)86}