Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/cmd/collectPodcastData.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ func cmdCollectPodcastData(cmd *cobra.Command, args []string) error {
}
log.Printf("Requesting 'Podcasts.GetByFeedID' data from podcast index for feed id %d ... successful", podcastInfo.PodcastIndexID)

// Once a podcast is removed from the PodcastIndex, there is nothing left to collect.
// We keep the data we collected in the past instead of failing the whole run.
if !p.Found {
log.Printf("PodcastIndex has no feed for id %d anymore. Keeping the existing data of %s", podcastInfo.PodcastIndexID, absJsonFilePath)
continue
}

// Set basic podcast data
podcastInfo.EpisodeCount = p.Feed.EpisodeCount
podcastInfo.ItunesID = p.Feed.ItunesID
Expand Down
29 changes: 28 additions & 1 deletion app/podcastindex/podcasts.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package podcastindex

import (
"context"
"encoding/json"
"fmt"
"net/http"
)
Expand All @@ -13,7 +14,33 @@ import (
type PodcastsService service

type Podcast struct {
Feed PodcastFeed `json:"feed,omitempty"`
Feed PodcastFeed

// Found reports whether the API returned a feed for the requested id.
// Once a feed is removed from the PodcastIndex, the API answers with
// an empty array ("feed": []) instead of a feed object.
Found bool
}

func (p *Podcast) UnmarshalJSON(data []byte) error {
var raw struct {
Feed json.RawMessage `json:"feed,omitempty"`
}
if err := json.Unmarshal(data, &raw); err != nil {
return err
}

// "feed": [] means: No feeds match this id.
if len(raw.Feed) == 0 || raw.Feed[0] == '[' {
return nil
}

if err := json.Unmarshal(raw.Feed, &p.Feed); err != nil {
return err
}
p.Found = true

return nil
}

type PodcastFeed struct {
Expand Down
50 changes: 50 additions & 0 deletions app/podcastindex/podcasts_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package podcastindex

import (
"encoding/json"
"testing"
)

// The PodcastIndex API returns an empty array as feed once a feed id is unknown.
// Decoding this must not fail, otherwise a single removed podcast breaks the whole data collection.
func TestPodcastUnmarshalJSON_RemovedFeed(t *testing.T) {
body := `{"status":"true","query":{"id":"685245"},"feed":[],"description":"No feeds match this id."}`

p := new(Podcast)
if err := json.Unmarshal([]byte(body), p); err != nil {
t.Fatalf("Unmarshal returned error: %v", err)
}
if p.Found {
t.Error("Found = true, want false")
}
if p.Feed.ID != 0 {
t.Errorf("Feed.ID = %d, want 0", p.Feed.ID)
}
}

func TestPodcastUnmarshalJSON_ExistingFeed(t *testing.T) {
body := `{"status":"true","query":{"id":"685245"},"feed":{"id":685245,"title":"IT@DB","artwork":"https://example.com/cover.png","itunesId":1462447493,"episodeCount":94},"description":"Found matching feed."}`

p := new(Podcast)
if err := json.Unmarshal([]byte(body), p); err != nil {
t.Fatalf("Unmarshal returned error: %v", err)
}
if !p.Found {
t.Error("Found = false, want true")
}
if p.Feed.ID != 685245 {
t.Errorf("Feed.ID = %d, want 685245", p.Feed.ID)
}
if p.Feed.Title != "IT@DB" {
t.Errorf("Feed.Title = %q, want %q", p.Feed.Title, "IT@DB")
}
if p.Feed.Artwork != "https://example.com/cover.png" {
t.Errorf("Feed.Artwork = %q, want %q", p.Feed.Artwork, "https://example.com/cover.png")
}
if p.Feed.ItunesID != 1462447493 {
t.Errorf("Feed.ItunesID = %d, want 1462447493", p.Feed.ItunesID)
}
if p.Feed.EpisodeCount != 94 {
t.Errorf("Feed.EpisodeCount = %d, want 94", p.Feed.EpisodeCount)
}
}
Loading