diff options
-rw-r--r-- | main.go | 37 | ||||
-rw-r--r-- | main_test.go | 67 | ||||
-rw-r--r-- | testdata/TestServedFeed.golden | 92 |
3 files changed, 181 insertions, 15 deletions
@@ -52,6 +52,8 @@ var ( episodeUrlRe = regexp.MustCompile(`<a href="/brand/(.+?)?" class="title`) outputPath, programNumber string + + errBadEpisode = fmt.Errorf("bad episode") ) func main() { @@ -59,22 +61,27 @@ func main() { flag.StringVar(&programNumber, "brand", "57083", "brand number (defaults to Aerostat)") flag.Parse() - programUrl := "http://www.radiorus.ru/brand/" + programNumber + "/episodes" + url := "http://www.radiorus.ru/brand/" + programNumber + "/episodes" + + feed := processURL(url) + + feed.Created = time.Now() + output := createFeed(feed) + outputFile := outputPath + "radiorus-" + programNumber + ".rss" + + writeFile(output, outputFile) +} - feed := getFeed(programUrl) +func processURL(url string) *feeds.Feed { + feed := getFeed(url) var wg sync.WaitGroup wg.Add(1) go describeFeed(feed, &wg) describeEpisodes(feed) - - feed.Created = time.Now() wg.Wait() - output := createFeed(feed) - - outputFile := outputPath + "radiorus-" + programNumber + ".rss" - writeFile(output, outputFile) + return feed } func createFeed(feed *feeds.Feed) []byte { @@ -98,9 +105,12 @@ func getFeed(url string) (feed *feeds.Feed) { for { page := getPage(url) - if err := populateFeed(feed, page); err != nil { + if err := populateFeed(feed, page); err == errBadEpisode { time.Sleep(15 * 60 * time.Second) continue + } else if err != nil { + err = fmt.Errorf("could not process %v: %w", url, err) + log.Fatal(err) } break } @@ -109,7 +119,12 @@ func getFeed(url string) (feed *feeds.Feed) { } func populateFeed(feed *feeds.Feed, page []byte) (err error) { - feed.Title = string(programNameRe.FindSubmatch(page)[1]) + titleMatch := programNameRe.FindSubmatch(page) + if len(titleMatch) < 1 { + return fmt.Errorf("bad program page") + } + + feed.Title = string(titleMatch[1]) programImage := programImageRe.FindSubmatch(page) feed.Image = &feeds.Image{ Link: feed.Link.Href, @@ -121,7 +136,7 @@ func populateFeed(feed *feeds.Feed, page []byte) (err error) { for _, episode := range episodes { if len(episodeUrlRe.FindAllSubmatch(episode, -1)) > 1 { - return fmt.Errorf("bad episode") + return errBadEpisode } episodeUrl := "http://www.radiorus.ru/brand/" + string(episodeUrlRe.FindSubmatch(episode)[1]) episodeTitle := string(episodeTitleRe.FindSubmatch(episode)[1]) diff --git a/main_test.go b/main_test.go index 4a5e53f..819f9d0 100644 --- a/main_test.go +++ b/main_test.go @@ -18,14 +18,24 @@ package main import ( "bytes" "flag" + "fmt" "io/ioutil" + "net/http" + "net/http/httptest" + "os" "path/filepath" + "sync" "testing" "github.com/gorilla/feeds" ) -var update = flag.Bool("update", false, "update .golden files") +var ( + update = flag.Bool("update", false, "update .golden files") + fakeURL = `**localhost**` +) + +const pth = "testdata/brand/57083" func helperLoadBytes(t *testing.T, name string) []byte { t.Helper() @@ -56,9 +66,30 @@ func TestFeed(t *testing.T) { actual := createFeed(feed) golden := filepath.Join("testdata", t.Name()+".golden") if *update { - if err := ioutil.WriteFile(golden, actual, 0644); err != nil { - t.Fatal(err) - } + writeFile(actual, golden) + } + expected, _ := ioutil.ReadFile(golden) + + if !bytes.Equal(actual, expected) { + t.Fail() + } +} + +func TestServedFeed(t *testing.T) { + server := helperMockServer(t) + defer helperCleanupServer(t) + + feed := getFeed(fmt.Sprintf("%s/brand/57083/episodes", server.URL)) + + var wg sync.WaitGroup + wg.Add(1) + describeFeed(feed, &wg) + wg.Wait() + + actual := bytes.ReplaceAll(createFeed(feed), []byte(server.URL), []byte(fakeURL)) + golden := filepath.Join("testdata", t.Name()+".golden") + if *update { + writeFile(actual, golden) } expected, _ := ioutil.ReadFile(golden) @@ -66,3 +97,31 @@ func TestFeed(t *testing.T) { t.Fail() } } + +func helperMockServer(t *testing.T) *httptest.Server { + t.Helper() + + fileserver := http.FileServer(http.Dir("testdata")) + server := httptest.NewServer(fileserver) + + episodes := helperLoadBytes(t, "episodes") + writeFile(episodes, filepath.Join(pth, "episodes")) + + about := helperLoadBytes(t, "about") + writeFile(about, filepath.Join(pth, "about")) + + return server +} + +func helperCleanupServer(t *testing.T) { + t.Helper() + helperCleanupFile(t, "episodes") + helperCleanupFile(t, "about") +} + +func helperCleanupFile(t *testing.T, name string) { + t.Helper() + if err := os.Remove(filepath.Join(pth, name)); err != nil { + t.Fatal(err) + } +} diff --git a/testdata/TestServedFeed.golden b/testdata/TestServedFeed.golden new file mode 100644 index 0000000..a2301fa --- /dev/null +++ b/testdata/TestServedFeed.golden @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"> + <channel> + <title><a href="/brand/57083">"Аэростат"</a></title> + <link>**localhost**/brand/57083/episodes</link> + <description>Вы не можете быть до конца уверены, что на этот раз вам откроет БГ – будь то взгляд на группу Doors или столь глобальные вопросы, как: что такое новое время, как делится история мира в соответствии с древней индийской космогонией, стоит ли ждать ветра перемен, ждет ли нас духовное возрождение, где граница между прошлым и будущим. А может и вовсе не стоит искать ответы на эти вопросы? Потому что это не те вопросы, а потому и ответы не приведут вас к истине...

Прислушаемся к Борису Гребенщикову, который с улыбкой говорит всем нам "Здравствуйте!" и находит самые простые ответы...</description> + <image> + <url>https://cdn-st4.rtr-vesti.ru/vh/pictures/xw/124/617/1.jpg</url> + <title>"Аэростат"</title> + <link>**localhost**/brand/57083/episodes</link> + </image> + <item> + <title>Новые имена 27</title> + <link>http://www.radiorus.ru/brand/57083/episode/2237849</link> + <description></description> + <enclosure url="https://audio.vgtrk.com/download?id=2467579" length="1024" type="audio/mpeg"></enclosure> + <guid>http://www.radiorus.ru/brand/57083/episode/2237849</guid> + <pubDate>Sun, 26 Jan 2020 14:10:00 +0300</pubDate> + </item> + <item> + <title>The Cure</title> + <link>http://www.radiorus.ru/brand/57083/episode/2237781</link> + <description></description> + <enclosure url="https://audio.vgtrk.com/download?id=2466052" length="1024" type="audio/mpeg"></enclosure> + <guid>http://www.radiorus.ru/brand/57083/episode/2237781</guid> + <pubDate>Sun, 19 Jan 2020 14:10:00 +0300</pubDate> + </item> + <item> + <title>Новые песни января</title> + <link>http://www.radiorus.ru/brand/57083/episode/2236152</link> + <description></description> + <enclosure url="https://audio.vgtrk.com/download?id=2464622" length="1024" type="audio/mpeg"></enclosure> + <guid>http://www.radiorus.ru/brand/57083/episode/2236152</guid> + <pubDate>Sun, 12 Jan 2020 14:10:00 +0300</pubDate> + </item> + <item> + <title>Новогодние притчи</title> + <link>http://www.radiorus.ru/brand/57083/episode/2234173</link> + <description></description> + <enclosure url="https://audio.vgtrk.com/download?id=2463470" length="1024" type="audio/mpeg"></enclosure> + <guid>http://www.radiorus.ru/brand/57083/episode/2234173</guid> + <pubDate>Sun, 05 Jan 2020 14:10:00 +0300</pubDate> + </item> + <item> + <title>С наступающим!</title> + <link>http://www.radiorus.ru/brand/57083/episode/2233216</link> + <description></description> + <enclosure url="https://audio.vgtrk.com/download?id=2462338" length="1024" type="audio/mpeg"></enclosure> + <guid>http://www.radiorus.ru/brand/57083/episode/2233216</guid> + <pubDate>Sun, 29 Dec 2019 14:10:00 +0300</pubDate> + </item> + <item> + <title>Рождество</title> + <link>http://www.radiorus.ru/brand/57083/episode/2231513</link> + <description></description> + <enclosure url="https://audio.vgtrk.com/download?id=2460859" length="1024" type="audio/mpeg"></enclosure> + <guid>http://www.radiorus.ru/brand/57083/episode/2231513</guid> + <pubDate>Sun, 22 Dec 2019 14:10:00 +0300</pubDate> + </item> + <item> + <title>"То да сё # 6" (Сила музыки)</title> + <link>http://www.radiorus.ru/brand/57083/episode/2229234</link> + <description></description> + <enclosure url="https://audio.vgtrk.com/download?id=2459405" length="1024" type="audio/mpeg"></enclosure> + <guid>http://www.radiorus.ru/brand/57083/episode/2229234</guid> + <pubDate>Sun, 15 Dec 2019 14:10:00 +0300</pubDate> + </item> + <item> + <title>Новые песни декабря</title> + <link>http://www.radiorus.ru/brand/57083/episode/2226836</link> + <description></description> + <enclosure url="https://audio.vgtrk.com/download?id=2457932" length="1024" type="audio/mpeg"></enclosure> + <guid>http://www.radiorus.ru/brand/57083/episode/2226836</guid> + <pubDate>Sun, 08 Dec 2019 14:10:00 +0300</pubDate> + </item> + <item> + <title>То да сё № 5</title> + <link>http://www.radiorus.ru/brand/57083/episode/2223937</link> + <description></description> + <enclosure url="https://audio.vgtrk.com/download?id=2456411" length="1024" type="audio/mpeg"></enclosure> + <guid>http://www.radiorus.ru/brand/57083/episode/2223937</guid> + <pubDate>Sun, 01 Dec 2019 14:10:00 +0300</pubDate> + </item> + <item> + <title>ELO: "Из ниоткуда" 2019</title> + <link>http://www.radiorus.ru/brand/57083/episode/2222868</link> + <description></description> + <enclosure url="https://audio.vgtrk.com/download?id=2454907" length="1024" type="audio/mpeg"></enclosure> + <guid>http://www.radiorus.ru/brand/57083/episode/2222868</guid> + <pubDate>Sun, 24 Nov 2019 14:10:00 +0300</pubDate> + </item> + </channel> +</rss>
\ No newline at end of file |