feed.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // Copyright 2017 Frédéric Guillot. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package model // import "miniflux.app/model"
  5. import (
  6. "fmt"
  7. "math"
  8. "time"
  9. "miniflux.app/config"
  10. "miniflux.app/http/client"
  11. )
  12. // Feed represents a feed in the application.
  13. type Feed struct {
  14. ID int64 `json:"id"`
  15. UserID int64 `json:"user_id"`
  16. FeedURL string `json:"feed_url"`
  17. SiteURL string `json:"site_url"`
  18. Title string `json:"title"`
  19. CheckedAt time.Time `json:"checked_at"`
  20. NextCheckAt time.Time `json:"next_check_at"`
  21. EtagHeader string `json:"etag_header"`
  22. LastModifiedHeader string `json:"last_modified_header"`
  23. ParsingErrorMsg string `json:"parsing_error_message"`
  24. ParsingErrorCount int `json:"parsing_error_count"`
  25. ScraperRules string `json:"scraper_rules"`
  26. RewriteRules string `json:"rewrite_rules"`
  27. Crawler bool `json:"crawler"`
  28. BlocklistRules string `json:"blocklist_rules"`
  29. KeeplistRules string `json:"keeplist_rules"`
  30. UserAgent string `json:"user_agent"`
  31. Username string `json:"username"`
  32. Password string `json:"password"`
  33. Disabled bool `json:"disabled"`
  34. IgnoreHTTPCache bool `json:"ignore_http_cache"`
  35. FetchViaProxy bool `json:"fetch_via_proxy"`
  36. Category *Category `json:"category,omitempty"`
  37. Entries Entries `json:"entries,omitempty"`
  38. Icon *FeedIcon `json:"icon"`
  39. UnreadCount int `json:"-"`
  40. ReadCount int `json:"-"`
  41. }
  42. // List of supported schedulers.
  43. const (
  44. SchedulerRoundRobin = "round_robin"
  45. SchedulerEntryFrequency = "entry_frequency"
  46. )
  47. func (f *Feed) String() string {
  48. return fmt.Sprintf("ID=%d, UserID=%d, FeedURL=%s, SiteURL=%s, Title=%s, Category={%s}",
  49. f.ID,
  50. f.UserID,
  51. f.FeedURL,
  52. f.SiteURL,
  53. f.Title,
  54. f.Category,
  55. )
  56. }
  57. // WithClientResponse updates feed attributes from an HTTP request.
  58. func (f *Feed) WithClientResponse(response *client.Response) {
  59. f.EtagHeader = response.ETag
  60. f.LastModifiedHeader = response.LastModified
  61. f.FeedURL = response.EffectiveURL
  62. }
  63. // WithCategoryID initializes the category attribute of the feed.
  64. func (f *Feed) WithCategoryID(categoryID int64) {
  65. f.Category = &Category{ID: categoryID}
  66. }
  67. // WithBrowsingParameters defines browsing parameters.
  68. func (f *Feed) WithBrowsingParameters(crawler bool, userAgent, username, password, scraperRules, rewriteRules, blocklistRules, keeplistRules string, fetchViaProxy bool) {
  69. f.Crawler = crawler
  70. f.UserAgent = userAgent
  71. f.Username = username
  72. f.Password = password
  73. f.ScraperRules = scraperRules
  74. f.RewriteRules = rewriteRules
  75. f.FetchViaProxy = fetchViaProxy
  76. f.BlocklistRules = blocklistRules
  77. f.KeeplistRules = keeplistRules
  78. }
  79. // WithError adds a new error message and increment the error counter.
  80. func (f *Feed) WithError(message string) {
  81. f.ParsingErrorCount++
  82. f.ParsingErrorMsg = message
  83. }
  84. // ResetErrorCounter removes all previous errors.
  85. func (f *Feed) ResetErrorCounter() {
  86. f.ParsingErrorCount = 0
  87. f.ParsingErrorMsg = ""
  88. }
  89. // CheckedNow set attribute values when the feed is refreshed.
  90. func (f *Feed) CheckedNow() {
  91. f.CheckedAt = time.Now()
  92. if f.SiteURL == "" {
  93. f.SiteURL = f.FeedURL
  94. }
  95. }
  96. // ScheduleNextCheck set "next_check_at" of a feed based on the scheduler selected from the configuration.
  97. func (f *Feed) ScheduleNextCheck(weeklyCount int) {
  98. switch config.Opts.PollingScheduler() {
  99. case SchedulerEntryFrequency:
  100. var intervalMinutes int
  101. if weeklyCount == 0 {
  102. intervalMinutes = config.Opts.SchedulerEntryFrequencyMaxInterval()
  103. } else {
  104. intervalMinutes = int(math.Round(float64(7*24*60) / float64(weeklyCount)))
  105. }
  106. intervalMinutes = int(math.Min(float64(intervalMinutes), float64(config.Opts.SchedulerEntryFrequencyMaxInterval())))
  107. intervalMinutes = int(math.Max(float64(intervalMinutes), float64(config.Opts.SchedulerEntryFrequencyMinInterval())))
  108. f.NextCheckAt = time.Now().Add(time.Minute * time.Duration(intervalMinutes))
  109. default:
  110. f.NextCheckAt = time.Now()
  111. }
  112. }
  113. // Feeds is a list of feed
  114. type Feeds []*Feed