Migrated update podcast series task.

master
Michael 1 year ago
parent 7051c7bf71
commit 86984647a2

@ -6,6 +6,7 @@ require (
github.com/hibiken/asynq v0.24.0
github.com/mmcdole/gofeed v1.2.0
gorm.io/driver/postgres v1.4.8
gorm.io/driver/sqlite v1.4.4
gorm.io/gorm v1.24.5
)
@ -23,6 +24,7 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mattn/go-sqlite3 v1.14.15 // indirect
github.com/mmcdole/goxpp v0.0.0-20200921145534-2f3784f67354 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect

@ -75,6 +75,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mmcdole/gofeed v1.2.0 h1:kuq7tJnDf0pnsDzF820ukuySHxFimAcizpG15gYHIns=
github.com/mmcdole/gofeed v1.2.0/go.mod h1:TEyTG4gw4Q5Co+Hgahx/Oi3E0JHLM8BXtWC+mkJtRsw=
github.com/mmcdole/goxpp v0.0.0-20200921145534-2f3784f67354 h1:Z6i7ND25ixRtXFBylIUggqpvLMV1I15yprcqMVB7WZA=
@ -239,6 +241,9 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/postgres v1.4.8 h1:NDWizaclb7Q2aupT0jkwK8jx1HVCNzt+PQ8v/VnxviA=
gorm.io/driver/postgres v1.4.8/go.mod h1:O9MruWGNLUBUWVYfWuBClpf3HeGjOoybY0SNmCs3wsw=
gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc=
gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.24.2/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.24.5 h1:g6OPREKqqlWq4kh/3MCQbZKImeB9e6Xgc4zD+JgNZGE=
gorm.io/gorm v1.24.5/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=

@ -0,0 +1,75 @@
package pod_index_models
import (
"database/sql"
"database/sql/driver"
"reflect"
)
type NullInt64 sql.NullInt64
func (i NullInt64) Value() (driver.Value, error) {
return i, nil
}
func (ni *NullInt64) Scan(value interface{}) error {
var i sql.NullInt64
if value == "" {
// This is an empty string in an int. Make Valid false.
*ni = NullInt64{i.Int64, false}
} else {
if err := i.Scan(value); err != nil {
return err
}
// if nil the make Valid false
if reflect.TypeOf(value) == nil {
*ni = NullInt64{i.Int64, false}
} else {
*ni = NullInt64{i.Int64, true}
}
}
return nil
}
type Podcasts struct {
ID int `gorm:"column:id;primaryKey"`
URL string `gorm:"column:url;uniqueIndex;not null"`
Title string `gorm:"column:title;not null"`
LastUpdate int `gorm:"column:lastUpdate"`
Link string `gorm:"column:link;not null"`
LastHttpStatus int `gorm:"column:lastHttpStatus"`
Dead int `gorm:"column:dead"`
Contenttype string `gorm:"column:contentType;not null"`
ItunesId NullInt64 `gorm:"column:itunesId"`
OriginalUrl string `gorm:"column:originalUrl;not null"`
ItunesAuthor string `gorm:"column:itunesAuthor;not null"`
ItunesOwnerName string `gorm:"column:itunesOwnerName;not null"`
Explicit int `gorm:"column:explicit"`
ImageUrl string `gorm:"column:imageUrl;not null"`
ItunesType string `gorm:"column:itunesType;not null"`
Generator string `gorm:"column:generator;not null"`
NewestItemPubdate int `gorm:"column:newestItemPubdate"`
Language string `gorm:"column:language;not null"`
OldestItemPubdate int `gorm:"column:oldestItemPubdate"`
EpisodeCount int `gorm:"column:episodeCount"`
PopularityScore int `gorm:"column:popularityScore"`
Priority int `gorm:"column:priority"`
CreatedOn int `gorm:"column:createdOn"`
UpdateFrequency int `gorm:"column:updateFrequency"`
Chash string `gorm:"column:chash;not null"`
Host string `gorm:"column:host;not null"`
NewestEnclosureUrl string `gorm:"column:newestEnclosureUrl;not null"`
PodcastGuid string `gorm:"column:podcastGuid;not null"`
Description string `gorm:"column:description;not null"`
Category1 string `gorm:"column:category1;not null"`
Category2 string `gorm:"column:category2;not null"`
Category3 string `gorm:"column:category3;not null"`
Category4 string `gorm:"column:category4;not null"`
Category5 string `gorm:"column:category5;not null"`
Category6 string `gorm:"column:category6;not null"`
Category7 string `gorm:"column:category7;not null"`
Category8 string `gorm:"column:category8;not null"`
Category9 string `gorm:"column:category9;not null"`
Category10 string `gorm:"column:category10;not null"`
NewestEnclosureDuration NullInt64 `gorm:"column:newestEnclosureDuration"`
}

@ -0,0 +1,25 @@
package pod_index_models
import (
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var DB *gorm.DB
func ConnectDatabase() {
database, err := gorm.Open(sqlite.Open("podcastindex_feeds.db"), &gorm.Config{})
if err != nil {
//TODO: Manage error better
panic("Failed to connect to pod index database!")
}
err = database.AutoMigrate(&Podcasts{})
if err != nil {
//TODO: Manage error better
panic("Failed to migrate pod index database!")
}
DB = database
}

@ -0,0 +1,112 @@
package tasks
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"github.com/hibiken/asynq"
models "locsi.com/server/queue/locsi_models"
"locsi.com/server/queue/pod_index_models"
)
// A list of task types.
const (
TypeUpdatePodcastSeries = "podcastSeries:update"
)
type UpdatePodcastSeriesPayload struct {
PodcastSeriesID int
}
func NewUpdatePodcastSeriesTask(podSeriesID int) (*asynq.Task, error) {
payload, err := json.Marshal(UpdatePodcastSeriesPayload{0})
if err != nil {
return nil, err
}
return asynq.NewTask(TypeUpdatePodcastSeries, payload), nil
}
// Queries our database to find podcast series that need to have their RSS feeds crawled. If then stores new episode information found in the database.
func HandleUpdatePodcastSeriesTask(ctx context.Context, t *asynq.Task) error {
var p UpdatePodcastSeriesPayload
if err := json.Unmarshal(t.Payload(), &p); err != nil {
return fmt.Errorf("json.Unmarshal failed: %v: %w", err)
}
log.Printf("Updating Series")
// Get some rows from the pod index database.
var pod_index_podcasts []pod_index_models.Podcasts
// Below: Limit controls how many results to process. Offset controls where to start. Leave Limit stable and increment Offest by Limit value for each run.
if err := pod_index_models.DB.Limit(25000).Offset(3925000).Find(&pod_index_podcasts).Error; err != nil {
log.Fatal(err.Error())
}
// Convert each row from the pod index struct to our struct
for _, pod := range pod_index_podcasts {
// podCopy := pod
podSeries := ToPodSeries(pod)
// Insert data into postgresql db using API
podSeriesJson, _ := json.Marshal(podSeries)
//podJson, _ := json.Marshal(pod)
// fmt.Println(string(podSeriesJson))
// fmt.Println(string(podJson))
resp, err := http.Post("http://localhost:8080/podcast-series", "application/json",
bytes.NewBuffer(podSeriesJson))
if err != nil || resp.StatusCode != 200 {
fmt.Printf("Failed to post the item below with response code %v.\n", resp.StatusCode)
fmt.Println(string(podSeriesJson))
resBody, _ := ioutil.ReadAll(resp.Body)
fmt.Printf("client: response body: %s\n", resBody)
log.Fatal("")
}
fmt.Printf("Inserted %v.\n", pod.ID)
}
return nil
}
func ToPodSeries(pod pod_index_models.Podcasts) models.PodcastSeries {
// Get the categories for this podcast series.
podCategories := []models.Categories{}
if pod.Category1 != "" {
podCategories = append(podCategories, models.Categories{Category: pod.Category1})
}
if pod.Category2 != "" {
podCategories = append(podCategories, models.Categories{Category: pod.Category2})
}
if pod.Category3 != "" {
podCategories = append(podCategories, models.Categories{Category: pod.Category3})
}
if pod.Category4 != "" {
podCategories = append(podCategories, models.Categories{Category: pod.Category4})
}
if pod.Category5 != "" {
podCategories = append(podCategories, models.Categories{Category: pod.Category5})
}
if pod.Category6 != "" {
podCategories = append(podCategories, models.Categories{Category: pod.Category6})
}
if pod.Category7 != "" {
podCategories = append(podCategories, models.Categories{Category: pod.Category7})
}
if pod.Category8 != "" {
podCategories = append(podCategories, models.Categories{Category: pod.Category8})
}
if pod.Category9 != "" {
podCategories = append(podCategories, models.Categories{Category: pod.Category9})
}
if pod.Category10 != "" {
podCategories = append(podCategories, models.Categories{Category: pod.Category10})
}
return models.PodcastSeries{WebFeed: pod.URL, Name: pod.Title, URL: pod.Link, Explicit: (pod.Explicit != 0), ImageURL: pod.ImageUrl, ITunesType: pod.ItunesType, InLanguage: pod.Language, GUID: pod.PodcastGuid, Description: pod.Description, Categories: podCategories}
}

@ -0,0 +1,212 @@
package tasks
import (
"fmt"
"testing"
"time"
"github.com/mmcdole/gofeed"
models "locsi.com/server/queue/locsi_models"
"locsi.com/server/queue/pod_index_models"
)
/*????? Outliers to write tests for:
-Write a test for pod series #27, #71, #80, #90 that have an empty webfeed.
-#126 is failing?
-review failed tasks in asynq to find more tests to write
-query the db to find series that don't have any episodes and write tests if there are crawl failures associated with that
*/
func TestToPodSeries(t *testing.T) {
var tests = []struct {
rowID int
expectedResult models.PodcastSeries
}{
{150, models.PodcastSeries{
ID: 150, WebFeed: "https://www.podcasts.com/rss_feed/82efb3f4ebafda0e6d0f6b186ae52a67", Name: "Metal For Dummies", URL: "https://www.podcasts.com/metal-for-dummies-1f55c63b0", Explicit: true,
ImageURL: "https://s3.amazonaws.com/podcasts-image-uploads/metal-for-dummies-1f55c63b0-large.jpg", ITunesType: "Episodic", InLanguage: "", GUID: "fc548de5-4f10-50d3-b27a-f4aaa71e0ce9",
Description: "Weekly podcast for fans of hard rock and heavy metal", Categories: []models.Categories{{Category: "music"}}}},
{6046471, models.PodcastSeries{
ID: 6046471, WebFeed: "https://feeds.transistor.fm/songs", Name: "La musica Sacra Disc 2", URL: "", Explicit: false,
ImageURL: "", ITunesType: "serial", InLanguage: "en", GUID: "90b311a3-4724-58e0-b2ea-8330308dbcd0",
Description: "Compiled Christian music", Categories: []models.Categories{}}},
}
/* {pod_index_models.Podcasts{ID: 192, URL: "https://anchor.fm/s/126f9354/podcast/rss", Title:"WeR1 Podcasts", LastUpdate:1625174829, Link:"https://anchor.fm/WeR1ministries", LastHttpStatus:200,
Dead:0, Contenttype:"application/rss+xml; charset=utf-8", ItunesId:1000697584, OriginalUrl:"https://anchor.fm/s/126f9354/podcast/rss", ItunesAuthor:"WeR1", ItunesOwnerName:"WeR1", Explicit:0,
ImageUrl:"https://d3t3ozftmdmh3i.cloudfront.net/production/podcast_uploaded_nologo/2993021/2993021-1579844602262-d344aa73c11de.jpg", ItunesType:"episodic", Generator:"Anchor Podcasts",
NewestItemPubdate:1625169406, Language:"en", OldestItemPubdate:1579643364, EpisodeCount:21, PopularityScore:0, Priority:-1, CreatedOn:1596752671, UpdateFrequency:8, Chash:"987f5774bd42be7224356de984fef0ec",
Host:"anchor.fm", NewestEnclosureUrl:"https://anchor.fm/s/126f9354/podcast/play/36536242/https%3A%2F%2Fd3ctxlq1ktw2nl.cloudfront.net%2Fstaging%2F2021-6-1%2F202128442-44100-2-1ce916ef5a35b.m4a",
PodcastGuid:"61519044-3dce-52d0-ad72-b589d55aa7de", Description:"WeR1 is a dynamic christian community located in the greater Montreal area of Quebec, Canada. Our desire is to connect everyone, everywhere to the heart of God. Expect weekly prophetic teaching, observations and discussion.",
Category1:"religion", Category2:"spirituality", Category3:"christianity", Category4:"", Category5:"", Category6:"", Category7:"", Category8:"", Category9:"", Category10:"", NewestEnclosureDuration: 1936}, 1},
{pod_index_models.Podcasts{ID: 108874, URL:"https://anchor.fm/s/13024b18/podcast/rss" , Title:"Trabajo", LastUpdate:1622766208, Link:"https://anchor.fm/I4N-271207", LastHttpStatus:200,
Dead:0, Contenttype:"application/rss+xml; charset=utf-8", ItunesId:1496348905, OriginalUrl:"https://anchor.fm/s/13024b18/podcast/rss", ItunesAuthor:"I4N 2707", ItunesOwnerName:"I4N 2707",
Explicit:0, ImageUrl:"https://d3t3ozftmdmh3i.cloudfront.net/production/podcast_uploaded/3089174/3089174-1579834852932-4c92c81adb90a.jpg", ItunesType:"episodic", Generator:"Anchor Podcasts",
NewestItemPubdate:1579834857, Language:"es", OldestItemPubdate:1579834857, EpisodeCount:1, PopularityScore:0, Priority:-1, CreatedOn:1597201402, UpdateFrequency:9, Chash:"680777660f9796d51f8bbfb3b6dac302",
Host:"anchor.fm", NewestEnclosureUrl:"https://anchor.fm/s/13024b18/podcast/play/9906738/https%3A%2F%2Fd3ctxlq1ktw2nl.cloudfront.net%2Fproduction%2F2020-0-24%2F44898569-44100-1-bbc12aee9c985.m4a",
PodcastGuid:"a38d4efe-a674-59cb-bdab-a2bafb71af86", Description:"Trabajo de tecnologia", Category1:"fiction", Category2:"science", Category3:"", Category4:"", Category5:"", Category6:"", Category7:""
, Category8:, Category9:, Category10:, NewestEnclosureDuration: 55}, 1}, */
/* {pod_index_models.Podcasts{ID: , URL: , Title:, LastUpdate:, Link:, LastHttpStatus:,
Dead:, Contenttype:, ItunesId:, OriginalUrl:, ItunesAuthor:, ItunesOwnerName:, Explicit:, ImageUrl:, ItunesType:, Generator:,
NewestItemPubdate:, Language:, OldestItemPubdate:, EpisodeCount:, PopularityScore:, Priority:, CreatedOn:, UpdateFrequency:, Chash:,
Host:, NewestEnclosureUrl:, PodcastGuid:, Description:, Category1:, Category2:, Category3:, Category4:, Category5:, Category6:, Category7:, Category8:, Category9:, Category10:, NewestEnclosureDuration: }, 1},
*/
pod_index_models.ConnectDatabase()
for _, tt := range tests {
var pod_index_podcast pod_index_models.Podcasts
testname := fmt.Sprintf("Testing id %d", tt.rowID)
t.Run(testname, func(t *testing.T) {
// Get a podcast from the db.
if err := pod_index_models.DB.Find(&pod_index_podcast, int(tt.rowID)).Error; err != nil {
fmt.Println(err.Error())
}
//fmt.Println(&pod_index_podcast)
podSeries := ToPodSeries(pod_index_podcast)
//fmt.Println(tt.expectedResult.Description)
/* if reflect.DeepEqual(podSeries, tt.expectedResult) {
t.Errorf("for %d struct: got %v, want %v", tt.rowID, podSeries, tt.expectedResult)
}
*/if podSeries.WebFeed != tt.expectedResult.WebFeed {
t.Errorf("for %d, field WebFeed: got %v, want %v", tt.rowID, podSeries.WebFeed, tt.expectedResult.WebFeed)
}
if podSeries.Name != tt.expectedResult.Name {
t.Errorf("for %d, field Name: got %v, want %v", tt.rowID, podSeries.Name, tt.expectedResult.Name)
}
if podSeries.URL != tt.expectedResult.URL {
t.Errorf("for %d, field URL: got %v, want %v", tt.rowID, podSeries.URL, tt.expectedResult.URL)
}
if podSeries.Explicit != tt.expectedResult.Explicit {
t.Errorf("for %d, field Explicit: got %v, want %v", tt.rowID, podSeries.Explicit, tt.expectedResult.Explicit)
}
if podSeries.ImageURL != tt.expectedResult.ImageURL {
t.Errorf("for %d, field ImageURL: got %v, want %v", tt.rowID, podSeries.ImageURL, tt.expectedResult.ImageURL)
}
if podSeries.ITunesType != tt.expectedResult.ITunesType {
t.Errorf("for %d, field ITunesType: got %v, want %v", tt.rowID, podSeries.ITunesType, tt.expectedResult.ITunesType)
}
if podSeries.InLanguage != tt.expectedResult.InLanguage {
t.Errorf("for %d, field InLanguage: got %v, want %v", tt.rowID, podSeries.InLanguage, tt.expectedResult.InLanguage)
}
if podSeries.GUID != tt.expectedResult.GUID {
t.Errorf("for %d, field GUID: got %v, want %v", tt.rowID, podSeries.GUID, tt.expectedResult.GUID)
}
if podSeries.Description != tt.expectedResult.Description {
t.Errorf("for %d, field Description: got %v, want %v", tt.rowID, podSeries.Description, tt.expectedResult.Description)
}
if !EqualArray(podSeries.Categories, tt.expectedResult.Categories) {
t.Errorf("for %d, field Categories: got %v, want %v", tt.rowID, podSeries.Categories, tt.expectedResult.Categories)
}
})
}
}
func BenchmarkToPodSeries(b *testing.B) {
// Get some random podcasts from the db.
pod_index_models.ConnectDatabase()
var pod_index_podcasts []pod_index_models.Podcasts
if err := pod_index_models.DB.Order("RANDOM()").Limit(b.N).Find(&pod_index_podcasts).Error; err != nil {
fmt.Println(err.Error())
}
for _, pod := range pod_index_podcasts {
ToPodSeries(pod)
}
}
func EqualArray(a, b []models.Categories) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}
func TestToPodEpisode(t *testing.T) {
type expectedResult struct {
value models.PodcastEpisode
isValid bool
}
parsedTime1, _ := time.Parse(time.RFC3339, "2015-05-29T22:59:00Z")
parsedTime2, _ := time.Parse(time.RFC3339, "0000-00-00T00:00:00Z")
var tests = []struct {
podSeriesId int
episodeGUID string
expectedResult expectedResult
}{
{6, "tag:blogger.com,1999:blog-8429222294807394803.post-5283595917266045004", expectedResult{value: models.PodcastEpisode{
Name: "June 6-7 2015 Dual Sport Events", DatePublished: parsedTime1, GUID: "tag:blogger.com,1999:blog-8429222294807394803.post-5283595917266045004", Duration: "",
Description: "<iframe allowfullscreen=\"\" frameborder=\"0\" height=\"30\" mozallowfullscreen=\"true\" src=\"https://archive.org/embed/DualSport662015\" webkitallowfullscreen=\"true\" width=\"500\"></iframe> <enclosure length=\"14,339,473\" type=\"audio/mpeg\" url=\"https://archive.org/embed/DualSport662015\"><a href=\"http://archive.org/details/mark_usdualsports_Fdx\">Link</a></enclosure> <a href=\"http://ia601505.us.archive.org/4/items/DualSport662015/Dual%20Sport%206-6-2015.mp3\">Link</a>",
ImageURL: "", ContentURL: "http://ia601505.us.archive.org/4/items/DualSport662015/Dual%20Sport%206-6-2015.mp3", PodcastSeriesID: 6}, isValid: true}},
{8, "f9b0051099697331aa933922a1cb6739", expectedResult{isValid: false}},
{120, "f9b0051099697331aa933922a1cb6739", expectedResult{isValid: false}},
{160, "http://ciep.mx/wp-content/uploads/2015/02/Podcast2_2.mp3", expectedResult{value: models.PodcastEpisode{
Name: "Podcast CIEP | #2", DatePublished: parsedTime2, GUID: "http://ciep.mx/wp-content/uploads/2015/02/Podcast2_2.mp3", Duration: "5:30",
Description: "Ajuste del gasto público: por qué se tiene que recortar el gasto y dónde estarán los recortes. Finalmente, se analiza la evolución del presupuesto asignado a la función Protección social y la improbabilidad de alcanzar una pensión universal.",
ImageURL: "", ContentURL: "http://ciep.mx/wp-content/uploads/2015/02/Podcast2_2.mp3", PodcastSeriesID: 160}, isValid: true}},
}
models.ConnectDatabase()
for _, tt := range tests {
var podcast_series models.PodcastSeries
testname := fmt.Sprintf("Testing id %v", tt.episodeGUID)
t.Run(testname, func(t *testing.T) {
// Get a podcast from the db.
if err := models.DB.Find(&podcast_series, int(tt.podSeriesId)).Error; err != nil {
t.Errorf("Failed to get podcast from db: %v", err.Error())
}
// Grab the RSS feed for this podcast.
fp := gofeed.NewParser()
feed, err := fp.ParseURL(podcast_series.WebFeed)
if err != nil {
//????? Store that this failed and have the job run again. If it fails many times, decrease poll time or stop polling altogether
t.Errorf("Failed to get the feed for %s: %v", podcast_series.WebFeed, err.Error())
} else {
// Process the RSS feed data.
for _, item := range feed.Items {
if item.GUID == tt.episodeGUID {
// This is the GUID we are trying to test.
podEpisode, err := ToPodEpisode(item, tt.podSeriesId)
if err != nil {
if tt.expectedResult.isValid == true {
t.Errorf("Failed to convert item to episode for %s, %s: %v", podcast_series.WebFeed, tt.episodeGUID, err.Error())
}
} else {
if podEpisode.Name != tt.expectedResult.value.Name {
t.Errorf("for %s, field Name: got %v, want %v", tt.episodeGUID, podEpisode.Name, tt.expectedResult.value.Name)
}
if podEpisode.DatePublished != tt.expectedResult.value.DatePublished {
t.Errorf("for %s, field DatePublished: got %v, want %v", tt.episodeGUID, podEpisode.DatePublished, tt.expectedResult.value.DatePublished)
}
if podEpisode.GUID != tt.expectedResult.value.GUID {
t.Errorf("for %s, field GUID: got %v, want %v", tt.episodeGUID, podEpisode.GUID, tt.expectedResult.value.GUID)
}
if podEpisode.Duration != tt.expectedResult.value.Duration {
t.Errorf("for %s, field Duration: got %v, want %v", tt.episodeGUID, podEpisode.Duration, tt.expectedResult.value.Duration)
}
if podEpisode.Description != tt.expectedResult.value.Description {
t.Errorf("for %s, field Description: got %v, want %v", tt.episodeGUID, podEpisode.Description, tt.expectedResult.value.Description)
}
if podEpisode.ImageURL != tt.expectedResult.value.ImageURL {
t.Errorf("for %s, field ImageURL: got %v, want %v", tt.episodeGUID, podEpisode.ImageURL, tt.expectedResult.value.ImageURL)
}
if podEpisode.ContentURL != tt.expectedResult.value.ContentURL {
t.Errorf("for %s, field ContentURL: got %v, want %v", tt.episodeGUID, podEpisode.ContentURL, tt.expectedResult.value.ContentURL)
}
if podEpisode.PodcastSeriesID != tt.expectedResult.value.PodcastSeriesID {
t.Errorf("for %s, field PodcastSeriesID: got %v, want %v", tt.episodeGUID, podEpisode.PodcastSeriesID, tt.expectedResult.value.PodcastSeriesID)
}
}
}
}
}
})
}
}
Loading…
Cancel
Save