summaryrefslogtreecommitdiff
path: root/internal/feed
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--internal/feed/cache.go131
-rw-r--r--internal/feed/cache_v1.go116
-rw-r--r--internal/feed/feed.go5
3 files changed, 131 insertions, 121 deletions
diff --git a/internal/feed/cache.go b/internal/feed/cache.go
index 411ed47..4a0bfe7 100644
--- a/internal/feed/cache.go
+++ b/internal/feed/cache.go
@@ -2,151 +2,40 @@ package feed
import (
"bufio"
- "crypto/sha256"
"encoding/gob"
"errors"
"fmt"
"os"
- "time"
"github.com/Necoro/feed2imap-go/pkg/log"
)
+type Version byte
+
const (
- currentVersion byte = 1
- startFeedId uint64 = 1
+ currentVersion Version = 1
)
type Cache interface {
findItem(*Feed) CachedFeed
- Version() byte
+ Version() Version
transformToCurrent() (Cache, error)
}
-type feedId uint64
-
-type feedDescriptor struct {
- Name string
- Url string
-}
-
type CachedFeed interface {
Checked(withFailure bool)
Failures() uint
}
-type cachedFeed struct {
- LastCheck time.Time
- NumFailures uint // can't be named `Failures` b/c it'll collide with the interface
- Items []cachedItem
-}
-
-func (cf *cachedFeed) Checked(withFailure bool) {
- cf.LastCheck = time.Now()
- if withFailure {
- cf.NumFailures++
- } else {
- cf.NumFailures = 0
- }
-}
-
-func (cf *cachedFeed) Failures() uint {
- return cf.NumFailures
-}
-
-type itemHash [sha256.Size]byte
-
-type cachedItem struct {
- Uid string
- Title string
- Link string
- Date time.Time
- Updated time.Time
- Creator string
- Hash itemHash
-}
-
-type v1Cache struct {
- version byte
- Ids map[feedDescriptor]feedId
- NextId uint64
- Feeds map[feedId]*cachedFeed
-}
-
-func (cache *v1Cache) Version() byte {
- return cache.version
-}
-
-func newCache() Cache {
- cache := v1Cache{
- Ids: map[feedDescriptor]feedId{},
- Feeds: map[feedId]*cachedFeed{},
- NextId: startFeedId,
- }
- cache.version = currentVersion
- return &cache
-}
-
-func cacheForVersion(version byte) (Cache, error) {
+func cacheForVersion(version Version) (Cache, error) {
switch version {
- case 1:
- return newCache(), nil
+ case v1Version:
+ return newV1Cache(), nil
default:
return nil, fmt.Errorf("unknown cache version '%d'", version)
}
}
-func (cache *v1Cache) transformToCurrent() (Cache, error) {
- return cache, nil
-}
-
-func (cache *v1Cache) getItem(id feedId) CachedFeed {
- feed, ok := cache.Feeds[id]
- if !ok {
- feed = &cachedFeed{}
- cache.Feeds[id] = feed
- }
- return feed
-}
-
-func (cache *v1Cache) findItem(feed *Feed) CachedFeed {
- if feed.cached != nil {
- return feed.cached.(*cachedFeed)
- }
-
- fDescr := feed.descriptor()
- id, ok := cache.Ids[fDescr]
- if !ok {
- var otherId feedDescriptor
- changed := false
- for otherId, id = range cache.Ids {
- if otherId.Name == fDescr.Name {
- log.Warnf("Feed %s seems to have changed URLs: newCache '%s', old '%s'. Updating.",
- fDescr.Name, fDescr.Url, otherId.Url)
- changed = true
- break
- } else if otherId.Url == fDescr.Url {
- log.Warnf("Feed with URL '%s' seems to have changed its name: newCache '%s', old '%s'. Updating",
- fDescr.Url, fDescr.Name, otherId.Name)
- changed = true
- break
- }
- }
- if changed {
- delete(cache.Ids, otherId)
- } else {
- id = feedId(cache.NextId)
- cache.NextId++
- }
-
- cache.Ids[fDescr] = id
- }
-
- item := cache.getItem(id)
- feed.cached = item
- return item
-}
-
func storeCache(cache Cache, fileName string) error {
if cache == nil {
return fmt.Errorf("trying to store nil cache")
@@ -162,7 +51,7 @@ func storeCache(cache Cache, fileName string) error {
defer f.Close()
writer := bufio.NewWriter(f)
- if err = writer.WriteByte(currentVersion); err != nil {
+ if err = writer.WriteByte(byte(currentVersion)); err != nil {
return fmt.Errorf("writing to '%s': %w", fileName, err)
}
@@ -182,7 +71,7 @@ func loadCache(fileName string) (Cache, error) {
if err != nil {
if errors.Is(err, os.ErrNotExist) {
// no cache there yet -- make new
- return newCache(), nil
+ return cacheForVersion(currentVersion)
}
return nil, fmt.Errorf("opening cache at '%s': %w", fileName, err)
}
@@ -196,7 +85,7 @@ func loadCache(fileName string) (Cache, error) {
return nil, fmt.Errorf("reading from '%s': %w", fileName, err)
}
- cache, err := cacheForVersion(version)
+ cache, err := cacheForVersion(Version(version))
if err != nil {
return nil, err
}
diff --git a/internal/feed/cache_v1.go b/internal/feed/cache_v1.go
new file mode 100644
index 0000000..3d46084
--- /dev/null
+++ b/internal/feed/cache_v1.go
@@ -0,0 +1,116 @@
+package feed
+
+import (
+ "crypto/sha256"
+ "time"
+
+ "github.com/Necoro/feed2imap-go/pkg/log"
+)
+
+const (
+ v1Version Version = 1
+ startFeedId uint64 = 1
+)
+
+type feedId uint64
+
+type v1Cache struct {
+ Ids map[feedDescriptor]feedId
+ NextId uint64
+ Feeds map[feedId]*cachedFeed
+}
+
+type cachedFeed struct {
+ LastCheck time.Time
+ NumFailures uint // can't be named `Failures` b/c it'll collide with the interface
+ Items []cachedItem
+}
+
+type itemHash [sha256.Size]byte
+
+type cachedItem struct {
+ Uid string
+ Title string
+ Link string
+ Date time.Time
+ Updated time.Time
+ Creator string
+ Hash itemHash
+}
+
+func (cf *cachedFeed) Checked(withFailure bool) {
+ cf.LastCheck = time.Now()
+ if withFailure {
+ cf.NumFailures++
+ } else {
+ cf.NumFailures = 0
+ }
+}
+
+func (cf *cachedFeed) Failures() uint {
+ return cf.NumFailures
+}
+
+func (cache *v1Cache) Version() Version {
+ return v1Version
+}
+
+func newV1Cache() *v1Cache {
+ cache := v1Cache{
+ Ids: map[feedDescriptor]feedId{},
+ Feeds: map[feedId]*cachedFeed{},
+ NextId: startFeedId,
+ }
+ return &cache
+}
+
+func (cache *v1Cache) transformToCurrent() (Cache, error) {
+ return cache, nil
+}
+
+func (cache *v1Cache) getItem(id feedId) CachedFeed {
+ feed, ok := cache.Feeds[id]
+ if !ok {
+ feed = &cachedFeed{}
+ cache.Feeds[id] = feed
+ }
+ return feed
+}
+
+func (cache *v1Cache) findItem(feed *Feed) CachedFeed {
+ if feed.cached != nil {
+ return feed.cached.(*cachedFeed)
+ }
+
+ fDescr := feed.descriptor()
+ id, ok := cache.Ids[fDescr]
+ if !ok {
+ var otherId feedDescriptor
+ changed := false
+ for otherId, id = range cache.Ids {
+ if otherId.Name == fDescr.Name {
+ log.Warnf("Feed %s seems to have changed URLs: newCache '%s', old '%s'. Updating.",
+ fDescr.Name, fDescr.Url, otherId.Url)
+ changed = true
+ break
+ } else if otherId.Url == fDescr.Url {
+ log.Warnf("Feed with URL '%s' seems to have changed its name: newCache '%s', old '%s'. Updating",
+ fDescr.Url, fDescr.Name, otherId.Name)
+ changed = true
+ break
+ }
+ }
+ if changed {
+ delete(cache.Ids, otherId)
+ } else {
+ id = feedId(cache.NextId)
+ cache.NextId++
+ }
+
+ cache.Ids[fDescr] = id
+ }
+
+ item := cache.getItem(id)
+ feed.cached = item
+ return item
+}
diff --git a/internal/feed/feed.go b/internal/feed/feed.go
index c7fdd5f..686de4c 100644
--- a/internal/feed/feed.go
+++ b/internal/feed/feed.go
@@ -16,6 +16,11 @@ type Feed struct {
cached CachedFeed
}
+type feedDescriptor struct {
+ Name string
+ Url string
+}
+
type feeditem struct {
*gofeed.Feed
*gofeed.Item