summaryrefslogtreecommitdiff
path: root/internal/service
diff options
context:
space:
mode:
Diffstat (limited to 'internal/service')
-rw-r--r--internal/service/browse.go2
-rw-r--r--internal/service/filename.go31
-rw-r--r--internal/service/podcast.go46
-rw-r--r--internal/service/write.go23
4 files changed, 51 insertions, 51 deletions
diff --git a/internal/service/browse.go b/internal/service/browse.go
index 230624f..d1f32cc 100644
--- a/internal/service/browse.go
+++ b/internal/service/browse.go
@@ -416,7 +416,7 @@ func (s *browseService) BrowseSet(ctx context.Context, setID, userID int64, pare
if set.IsPodcast {
feed, err := s.store.GetFeedBySetID(ctx, setID)
if err == nil && feed != nil {
- episodes, err := s.store.ListEpisodesWithStatus(ctx, userID, feed.ID, 0, 0)
+ episodes, err := s.store.ListEpisodesWithStatus(ctx, userID, feed.ID, 1000, 0)
if err == nil {
result.Episodes = episodes
}
diff --git a/internal/service/filename.go b/internal/service/filename.go
new file mode 100644
index 0000000..9303de6
--- /dev/null
+++ b/internal/service/filename.go
@@ -0,0 +1,31 @@
+package service
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+// uniqueFilename returns a non-conflicting full path by appending (n)
+// if a file with the same name already exists in dir.
+func uniqueFilename(dir, filename string) string {
+ filename = filepath.Base(filename)
+ if filename == "." || filename == ".." || filename == "" {
+ return ""
+ }
+ ext := filepath.Ext(filename)
+ base := strings.TrimSuffix(filename, ext)
+
+ candidate := filepath.Join(dir, filename)
+ if _, err := os.Stat(candidate); os.IsNotExist(err) {
+ return candidate
+ }
+
+ for i := 1; ; i++ {
+ candidate = filepath.Join(dir, fmt.Sprintf("%s(%d)%s", base, i, ext))
+ if _, err := os.Stat(candidate); os.IsNotExist(err) {
+ return candidate
+ }
+ }
+}
diff --git a/internal/service/podcast.go b/internal/service/podcast.go
index 4a6a3ae..5e56860 100644
--- a/internal/service/podcast.go
+++ b/internal/service/podcast.go
@@ -75,7 +75,12 @@ type podcastService struct {
}
// NewPodcastService creates a PodcastService with the given dependencies.
-func NewPodcastService(store PodcastServiceStore, clk clock.Clock, mediaRoot string, helper *accessHelper, prober probe.Prober, thumbGen thumb.Generator) *podcastService {
+// NewPodcastService creates a PodcastService with the given dependencies.
+// checkInterval should be the number of minutes between background feed checks.
+func NewPodcastService(store PodcastServiceStore, clk clock.Clock, mediaRoot string, helper *accessHelper, prober probe.Prober, thumbGen thumb.Generator, checkInterval int) *podcastService {
+ if checkInterval <= 0 {
+ checkInterval = 60
+ }
return &podcastService{
store: store,
clock: clk,
@@ -84,7 +89,7 @@ func NewPodcastService(store PodcastServiceStore, clk clock.Clock, mediaRoot str
prober: prober,
thumbGen: thumbGen,
httpClient: &http.Client{Timeout: 30 * time.Second},
- checkInterval: 60,
+ checkInterval: checkInterval,
}
}
@@ -166,7 +171,7 @@ func (s *podcastService) SubscribeFeed(ctx context.Context, feedURL, setName str
// Download cover image.
if parsed.ImageURL != "" {
- _ = podcast.DownloadCoverImage(parsed.ImageURL, setPath)
+ _ = podcast.DownloadCoverImage(s.httpClient, parsed.ImageURL, setPath)
}
// Insert episodes.
@@ -335,13 +340,17 @@ func (s *podcastService) DownloadEpisode(ctx context.Context, episodeID, userID
if err != nil {
return nil, fmt.Errorf("create file: %w", err)
}
- defer f.Close()
n, err := io.Copy(f, resp.Body)
if err != nil {
+ f.Close()
os.Remove(path)
return nil, fmt.Errorf("write file: %w", err)
}
+ if err := f.Close(); err != nil {
+ os.Remove(path)
+ return nil, fmt.Errorf("close file: %w", err)
+ }
// Create media row.
media := &model.Media{
@@ -369,6 +378,8 @@ func (s *podcastService) DownloadEpisode(ctx context.Context, episodeID, userID
// Link episode to media row.
if err := s.store.UpdateEpisodeMedia(ctx, episode.ID, media.ID, filepath.Base(path)); err != nil {
+ os.Remove(path)
+ _ = s.store.HardDeleteMedia(ctx, media.ID)
return nil, fmt.Errorf("update episode media: %w", err)
}
@@ -441,7 +452,7 @@ func (s *podcastService) CheckFeeds(ctx context.Context) error {
func (s *podcastService) checkFeed(ctx context.Context, feed model.PodcastFeed) error {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, feed.FeedURL, nil)
if err != nil {
- return err
+ return fmt.Errorf("build request for feed %d: %w", feed.ID, err)
}
// Conditional GET headers.
@@ -468,7 +479,7 @@ func (s *podcastService) checkFeed(ctx context.Context, feed model.PodcastFeed)
return fmt.Errorf("feed check status %d", resp.StatusCode)
}
- parsed, err := podcast.ParseFeed(feed.FeedURL)
+ parsed, err := podcast.ParseFeedReader(resp.Body)
if err != nil {
return err
}
@@ -512,7 +523,7 @@ func (s *podcastService) checkFeed(ctx context.Context, feed model.PodcastFeed)
set, err := s.store.GetSetByID(ctx, feed.SetID)
if err == nil && set != nil {
setPath := filepath.Join(s.mediaRoot, set.RootPath)
- _ = podcast.DownloadCoverImage(parsed.ImageURL, setPath)
+ _ = podcast.DownloadCoverImage(s.httpClient, parsed.ImageURL, setPath)
}
}
@@ -539,24 +550,3 @@ func sanitizeFilename(name string) string {
name = strings.TrimSpace(name)
return name
}
-
-func uniqueFilename(dir, filename string) string {
- filename = filepath.Base(filename)
- if filename == "." || filename == ".." || filename == "" {
- return ""
- }
- ext := filepath.Ext(filename)
- base := strings.TrimSuffix(filename, ext)
-
- candidate := filepath.Join(dir, filename)
- if _, err := os.Stat(candidate); os.IsNotExist(err) {
- return candidate
- }
-
- for i := 1; ; i++ {
- candidate = filepath.Join(dir, fmt.Sprintf("%s(%d)%s", base, i, ext))
- if _, err := os.Stat(candidate); os.IsNotExist(err) {
- return candidate
- }
- }
-}
diff --git a/internal/service/write.go b/internal/service/write.go
index 51abf22..a83c7e1 100644
--- a/internal/service/write.go
+++ b/internal/service/write.go
@@ -77,7 +77,7 @@ func (s *writeService) UploadMedia(ctx context.Context, setID, userID int64, fil
return nil, fmt.Errorf("mkdir: %w", err)
}
- path := s.uniqueFilename(dir, filename)
+ path := uniqueFilename(dir, filename)
if !strings.HasPrefix(filepath.Clean(path), filepath.Clean(dir)+string(filepath.Separator)) {
return nil, errors.New("invalid filename")
}
@@ -97,27 +97,6 @@ func (s *writeService) UploadMedia(ctx context.Context, setID, userID int64, fil
return media, nil
}
-func (s *writeService) uniqueFilename(dir, filename string) string {
- filename = filepath.Base(filename)
- if filename == "." || filename == ".." || filename == "" {
- return ""
- }
- ext := filepath.Ext(filename)
- base := strings.TrimSuffix(filename, ext)
-
- candidate := filepath.Join(dir, filename)
- if _, err := os.Stat(candidate); os.IsNotExist(err) {
- return candidate
- }
-
- for i := 1; ; i++ {
- candidate = filepath.Join(dir, fmt.Sprintf("%s(%d)%s", base, i, ext))
- if _, err := os.Stat(candidate); os.IsNotExist(err) {
- return candidate
- }
- }
-}
-
func (s *writeService) saveUploadedMedia(ctx context.Context, setID int64, path string, data io.Reader, size int64) (*model.Media, error) {
f, err := os.Create(path)
if err != nil {