1// Copyright (C) 2013-2015 Sören Tempel2//3// This program is free software: you can redistribute it and/or modify4// it under the terms of the GNU General Public License as published by5// the Free Software Foundation, either version 3 of the License, or6// (at your option) any later version.7//8// This program is distributed in the hope that it will be useful,9// but WITHOUT ANY WARRANTY; without even the implied warranty of10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the11// GNU General Public License for more details.12//13// You should have received a copy of the GNU General Public License14// along with this program. If not, see <http://www.gnu.org/licenses/>.1516package store1718import (19 "bufio"20 "github.com/nmeum/cpod/util"21 "github.com/nmeum/go-feedparser"22 "os"23)2425// Podcast represents a Podcast loaded from the store.26type Podcast struct {27 // URL to the feed.28 URL string2930 // Feed itself.31 Feed feedparser.Feed3233 // Error if parsing failed.34 Error error35}3637// Store represents a storage backend.38type Store struct {39 // path describes the URL file location.40 path string4142 // urls contains all URLs which are part of the URL file.43 urls []string44}4546// Load returns and creates a new store with the URL file located47// at the give filepath.48func Load(path string) (s *Store, err error) {49 s = new(Store)50 s.path = path5152 file, err := os.Open(path)53 if err != nil {54 return55 }5657 defer file.Close()58 scanner := bufio.NewScanner(file)5960 for scanner.Scan() {61 s.urls = append(s.urls, scanner.Text())62 }6364 err = scanner.Err()65 return66}6768// Add appends a new URL to the store. It doesn't check if the69// given data is a valid URL and it doesn't check if the URL70// is already a part of the store either.71func (s *Store) Add(url string) {72 s.urls = append(s.urls, url)73}7475// Contains returns true if the url is already a part of the76// store. If it isn't it returns false.77func (s *Store) Contains(url string) bool {78 for _, u := range s.urls {79 if u == url {80 return true81 }82 }8384 return false85}8687// Fetch fetches all feeds form the urls and returns a channel88// which contains all podcasts.89func (s *Store) Fetch() <-chan Podcast {90 out := make(chan Podcast)91 go func() {92 for _, url := range s.urls {93 resp, err := util.Get(url)94 if err != nil {95 continue96 }9798 reader := resp.Body99 defer reader.Close()100101 f, err := feedparser.Parse(reader)102 out <- Podcast{url, f, err}103 }104105 close(out)106 }()107108 return out109}110111// Save writes the URL file to the store path.112func (s *Store) Save() error {113 file, err := os.OpenFile(s.path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)114 if err != nil {115 return err116 }117118 defer file.Close()119 for _, url := range s.urls {120 if _, err := file.WriteString(url + "\n"); err != nil {121 return err122 }123 }124125 return nil126}