use enum for PodcastEpisodeStatus and PodcastAutoDownload

This commit is contained in:
sentriz
2021-03-04 19:26:24 +00:00
committed by Senan Kelly
parent 512d967dfa
commit 3c926aab99
6 changed files with 1091 additions and 1075 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -179,21 +179,21 @@
<table id="podcast-preferences"> <table id="podcast-preferences">
{{ range $pref := .Podcasts }} {{ range $pref := .Podcasts }}
<tr> <tr>
<form id="podcast-{{ $pref.ID }}-delete" action="{{ printf "/admin/delete_podcast_do?id=%d" $pref.ID | path }}" method="post"></form>
<form id="podcast-{{ $pref.ID }}-download" action="{{ printf "/admin/download_podcast_do?id=%d" $pref.ID | path }}" method="post"></form> <form id="podcast-{{ $pref.ID }}-download" action="{{ printf "/admin/download_podcast_do?id=%d" $pref.ID | path }}" method="post"></form>
<form id="podcast-{{ $pref.ID }}-autodl" action="{{ printf "/admin/update_podcast_do?id=%d" $pref.ID | path }}" method="post"></form> <form id="podcast-{{ $pref.ID }}-auto-download" action="{{ printf "/admin/update_podcast_do?id=%d" $pref.ID | path }}" method="post"></form>
<form id="podcast-{{ $pref.ID }}-delete" action="{{ printf "/admin/delete_podcast_do?id=%d" $pref.ID | path }}" method="post"></form>
<td>{{ $pref.Title }}</td> <td>{{ $pref.Title }}</td>
<td><select form="podcast-{{ $pref.ID }}-autodl" name="auto_dl"> <td><select form="podcast-{{ $pref.ID }}-auto-download" name="setting">
{{ if eq $pref.AutoDownload "dl_latest" }} {{ if eq $pref.AutoDownload "latest" }}
<option value="dl_latest" selected="selected">download latest</option> <option value="latest" selected="selected">download latest</option>
<option value="dl_none">no auto download</option> <option value="none">no auto download</option>
{{ else }} {{ else }}
<option value="dl_none" selected="selected" >no auto download</option> <option value="none" selected="selected" >no auto download</option>
<option value="dl_latest">download latest</option> <option value="latest">download latest</option>
{{ end }} {{ end }}
</select></td> </select></td>
<td><input form="podcast-{{ $pref.ID }}-download" type="submit" value="download all"></td> <td><input form="podcast-{{ $pref.ID }}-download" type="submit" value="download all"></td>
<td><input form="podcast-{{ $pref.ID }}-autodl" type="submit" value="save"></td> <td><input form="podcast-{{ $pref.ID }}-auto-download" type="submit" value="save"></td>
<td><input form="podcast-{{ $pref.ID }}-delete" type="submit" value="delete"></td> <td><input form="podcast-{{ $pref.ID }}-delete" type="submit" value="delete"></td>
</tr> </tr>
{{ end }} {{ end }}

View File

@@ -470,16 +470,28 @@ func (c *Controller) ServePodcastUpdateDo(r *http.Request) *Response {
code: 400, code: 400,
} }
} }
autoDlSetting := r.FormValue("auto_dl") setting := db.PodcastAutoDownload(r.FormValue("setting"))
if err := c.Podcasts.SetAutoDownload(id, autoDlSetting); err != nil { var message string
switch setting {
case db.PodcastAutoDownloadLatest:
message = "future podcast episodes will be automatically downloaded"
case db.PodcastAutoDownloadNone:
message = "future podcast episodes will not be downloaded"
default:
return &Response{ return &Response{
err: "please provide a valid podcast id and dl setting", err: "please provide a valid podcast download type",
code: 400,
}
}
if err := c.Podcasts.SetAutoDownload(id, setting); err != nil {
return &Response{
flashW: []string{fmt.Sprintf("could not update auto download setting: %v", err)},
code: 400, code: 400,
} }
} }
return &Response{ return &Response{
redirect: "/admin/home", redirect: "/admin/home",
flashN: []string{"future podcast episodes will be automatically downloaded"}, flashN: []string{message},
} }
} }

View File

@@ -30,7 +30,7 @@ func NewPodcastEpisode(p *db.Podcast, e *db.PodcastEpisode) *PodcastEpisode {
ChannelID: p.SID(), ChannelID: p.SID(),
Title: e.Title, Title: e.Title,
Description: e.Description, Description: e.Description,
Status: e.Status, Status: string(e.Status),
CoverArt: p.SID(), CoverArt: p.SID(),
PublishDate: *e.PublishDate, PublishDate: *e.PublishDate,
Genre: "Podcast", Genre: "Podcast",

View File

@@ -289,6 +289,13 @@ type AlbumGenre struct {
GenreID int `gorm:"not null; unique_index:idx_album_id_genre_id" sql:"default: null; type:int REFERENCES genres(id) ON DELETE CASCADE"` GenreID int `gorm:"not null; unique_index:idx_album_id_genre_id" sql:"default: null; type:int REFERENCES genres(id) ON DELETE CASCADE"`
} }
type PodcastAutoDownload string
const (
PodcastAutoDownloadLatest PodcastAutoDownload = "latest"
PodcastAutoDownloadNone PodcastAutoDownload = "none"
)
type Podcast struct { type Podcast struct {
ID int `gorm:"primary_key"` ID int `gorm:"primary_key"`
UpdatedAt time.Time UpdatedAt time.Time
@@ -301,7 +308,7 @@ type Podcast struct {
ImagePath string ImagePath string
Error string Error string
Episodes []*PodcastEpisode Episodes []*PodcastEpisode
AutoDownload string AutoDownload PodcastAutoDownload
} }
func (p *Podcast) Fullpath(podcastPath string) string { func (p *Podcast) Fullpath(podcastPath string) string {
@@ -313,6 +320,15 @@ func (p *Podcast) SID() *specid.ID {
return &specid.ID{Type: specid.Podcast, Value: p.ID} return &specid.ID{Type: specid.Podcast, Value: p.ID}
} }
type PodcastEpisodeStatus string
const (
PodcastEpisodeStatusDownloading PodcastEpisodeStatus = "downloading"
PodcastEpisodeStatusSkipped PodcastEpisodeStatus = "skipped"
PodcastEpisodeStatusDeleted PodcastEpisodeStatus = "deleted"
PodcastEpisodeStatusCompleted PodcastEpisodeStatus = "completed"
)
type PodcastEpisode struct { type PodcastEpisode struct {
ID int `gorm:"primary_key"` ID int `gorm:"primary_key"`
CreatedAt time.Time CreatedAt time.Time
@@ -328,7 +344,7 @@ type PodcastEpisode struct {
Size int Size int
Path string Path string
Filename string Filename string
Status string Status PodcastEpisodeStatus
Error string Error string
} }

View File

@@ -24,21 +24,13 @@ import (
"go.senan.xyz/gonic/server/scanner/tags" "go.senan.xyz/gonic/server/scanner/tags"
) )
const DownloadAllWaitInterval = 3 * time.Second
type Podcasts struct { type Podcasts struct {
DB *db.DB DB *db.DB
PodcastBasePath string PodcastBasePath string
} }
const (
episodeDownloading = "downloading"
episodeSkipped = "skipped"
episodeDeleted = "deleted"
episodeCompleted = "completed"
autoDlLatest = "dl_latest"
autoDlNone = "dl_none"
)
func (p *Podcasts) GetPodcastOrAll(userID int, id int, includeEpisodes bool) ([]*db.Podcast, error) { func (p *Podcasts) GetPodcastOrAll(userID int, id int, includeEpisodes bool) ([]*db.Podcast, error) {
podcasts := []*db.Podcast{} podcasts := []*db.Podcast{}
q := p.DB.Where("user_id=?", userID) q := p.DB.Where("user_id=?", userID)
@@ -102,9 +94,7 @@ func (p *Podcasts) AddNewPodcast(rssURL string, feed *gofeed.Feed,
return &podcast, nil return &podcast, nil
} }
var errNoSuchAutoDlOption = errors.New("invalid autodownload setting") func (p *Podcasts) SetAutoDownload(podcastID int, setting db.PodcastAutoDownload) error {
func (p *Podcasts) SetAutoDownload(podcastID int, setting string) error {
podcast := db.Podcast{} podcast := db.Podcast{}
err := p.DB. err := p.DB.
Where("id=?", podcastID). Where("id=?", podcastID).
@@ -113,15 +103,11 @@ func (p *Podcasts) SetAutoDownload(podcastID int, setting string) error {
if err != nil { if err != nil {
return err return err
} }
switch setting { podcast.AutoDownload = setting
case autoDlLatest: if err := p.DB.Save(&podcast).Error; err != nil {
podcast.AutoDownload = autoDlLatest return fmt.Errorf("save setting: %w", err)
return p.DB.Save(&podcast).Error
case autoDlNone:
podcast.AutoDownload = autoDlNone
return p.DB.Save(&podcast).Error
} }
return errNoSuchAutoDlOption return nil
} }
func getEntriesAfterDate(feed []*gofeed.Item, after time.Time) []*gofeed.Item { func getEntriesAfterDate(feed []*gofeed.Item, after time.Time) []*gofeed.Item {
@@ -160,8 +146,8 @@ func (p *Podcasts) AddNewEpisodes(podcast *db.Podcast, items []*gofeed.Item) err
if err != nil { if err != nil {
return err return err
} }
if podcast.AutoDownload == autoDlLatest && if podcast.AutoDownload == db.PodcastAutoDownloadLatest &&
(episode.Status != episodeCompleted && episode.Status != episodeDownloading) { (episode.Status != db.PodcastEpisodeStatusCompleted && episode.Status != db.PodcastEpisodeStatusDownloading) {
if err := p.DownloadEpisode(episode.ID); err != nil { if err := p.DownloadEpisode(episode.ID); err != nil {
return err return err
} }
@@ -240,7 +226,7 @@ func itemToEpisode(podcastID, size, duration int, audio string,
Size: size, Size: size,
PublishDate: item.PublishedParsed, PublishDate: item.PublishedParsed,
AudioURL: audio, AudioURL: audio,
Status: episodeSkipped, Status: db.PodcastEpisodeStatusSkipped,
} }
} }
@@ -327,14 +313,16 @@ func (p *Podcasts) DownloadPodcastAll(podcastID int) error {
} }
go func() { go func() {
for _, episode := range podcastEpisodes { for _, episode := range podcastEpisodes {
if episode.Status == episodeDownloading || episode.Status == episodeCompleted { if episode.Status == db.PodcastEpisodeStatusDownloading || episode.Status == db.PodcastEpisodeStatusCompleted {
log.Println("skipping episode is in progress or already downloaded") log.Println("skipping episode is in progress or already downloaded")
continue continue
} }
if err := p.DownloadEpisode(episode.ID); err != nil { if err := p.DownloadEpisode(episode.ID); err != nil {
log.Println(err) log.Printf("error downloading episode: %v", err)
continue
} }
log.Printf("Finished downloading episode: \"%s\"", episode.Title) log.Printf("finished downloading episode: %q", episode.Title)
time.Sleep(DownloadAllWaitInterval)
} }
}() }()
return nil return nil
@@ -357,11 +345,11 @@ func (p *Podcasts) DownloadEpisode(episodeID int) error {
if err != nil { if err != nil {
return fmt.Errorf("get podcast by id: %w", err) return fmt.Errorf("get podcast by id: %w", err)
} }
if podcastEpisode.Status == episodeDownloading { if podcastEpisode.Status == db.PodcastEpisodeStatusDownloading {
log.Printf("Already downloading podcast episode with id %d", episodeID) log.Printf("Already downloading podcast episode with id %d", episodeID)
return nil return nil
} }
podcastEpisode.Status = episodeDownloading podcastEpisode.Status = db.PodcastEpisodeStatusDownloading
p.DB.Save(&podcastEpisode) p.DB.Save(&podcastEpisode)
// nolint: bodyclose // nolint: bodyclose
resp, err := http.Get(podcastEpisode.AudioURL) resp, err := http.Get(podcastEpisode.AudioURL)
@@ -475,7 +463,7 @@ func (p *Podcasts) doPodcastDownload(podcastEpisode *db.PodcastEpisode, file *os
return nil return nil
} }
podcastEpisode.Bitrate = podcastTags.Bitrate() podcastEpisode.Bitrate = podcastTags.Bitrate()
podcastEpisode.Status = episodeCompleted podcastEpisode.Status = db.PodcastEpisodeStatusCompleted
podcastEpisode.Length = podcastTags.Length() podcastEpisode.Length = podcastTags.Length()
podcastEpisode.Size = int(stat.Size()) podcastEpisode.Size = int(stat.Size())
return p.DB.Save(podcastEpisode).Error return p.DB.Save(podcastEpisode).Error
@@ -517,7 +505,7 @@ func (p *Podcasts) DeletePodcastEpisode(podcastEpisodeID int) error {
if err != nil { if err != nil {
return err return err
} }
episode.Status = episodeDeleted episode.Status = db.PodcastEpisodeStatusDeleted
p.DB.Save(&episode) p.DB.Save(&episode)
if err := os.Remove(filepath.Join(p.PodcastBasePath, episode.Path)); err != nil { if err := os.Remove(filepath.Join(p.PodcastBasePath, episode.Path)); err != nil {
return err return err