package main import ( "fmt" "log" "net/http" "os" "path/filepath" "sync" "time" "github.com/gorilla/feeds" ) type RssEntry struct { title string url string descripiton string time time.Time } type Parser interface { Parse() []*RssEntry Title() string Description() string RootUrl() string ImageUrl() string ServerUrl() string CacheName() string CacheTimeout() int } type ParserFeed struct { parser Parser rss string mutex *sync.Mutex time time.Time } func (this ParserFeed) CachePath() string { return "./_cache/" + this.parser.CacheName() + ".rss" } func (this *ParserFeed) ReadCache() bool { path := this.CachePath() stat, err := os.Stat(path) if err != nil { return true } data, err := os.ReadFile(this.CachePath()) if err != nil { return true } this.SetFeed(string(data)) this.time = stat.ModTime() return time.Now().Sub(this.time).Seconds() > float64(this.parser.CacheTimeout()) } func (this *ParserFeed) ParseAndUpdateCache() { feed := &feeds.Feed{ Title: this.parser.Title(), Link: &feeds.Link{Href: this.parser.RootUrl()}, Description: this.parser.Description(), Created: time.Now(), Image: &feeds.Image{ Url: this.parser.ImageUrl(), Title: this.parser.Title(), Link: this.parser.RootUrl(), }, } entities := this.parser.Parse() for _, re := range entities { feed.Items = append(feed.Items, &feeds.Item{ Id: re.url, Title: re.title, Link: &feeds.Link{Href: re.url}, Description: re.descripiton, Created: re.time, }) } rssFeed, err := feed.ToRss() if err != nil { fmt.Println(err) } dir := filepath.Dir(this.CachePath()) os.MkdirAll(dir, os.ModePerm) os.WriteFile(this.CachePath(), []byte(rssFeed), os.ModePerm) this.mutex.Lock() this.rss = rssFeed this.time = time.Now() this.mutex.Unlock() } func (this *ParserFeed) RunWorker() { if this.ReadCache() { this.ParseAndUpdateCache() } for { nextmark := this.time.Add(time.Second * time.Duration(this.parser.CacheTimeout())) sleepfor := nextmark.Unix() - time.Now().Unix() if sleepfor > 0 { time.Sleep(time.Second * time.Duration(sleepfor)) } this.ParseAndUpdateCache() } } func (this *ParserFeed) SetFeed(feed string) { this.mutex.Lock() this.rss = feed this.mutex.Unlock() } func (this *ParserFeed) GetFeed() string { this.mutex.Lock() rss := this.rss this.mutex.Unlock() return rss } func main() { parsers := []*ParserFeed{ {parser: NvidiaParser{}, mutex: &sync.Mutex{}}, } for _, p := range parsers { go p.RunWorker() } rootPage := `