aboutsummaryrefslogtreecommitdiff
path: root/internal/reader/atom/atom_03_adapter.go
blob: 02d78ec8b342da1b017d6d76600cfa4b71e8cbab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package atom // import "miniflux.app/v2/internal/reader/atom"

import (
	"log/slog"
	"time"

	"miniflux.app/v2/internal/crypto"
	"miniflux.app/v2/internal/model"
	"miniflux.app/v2/internal/reader/date"
	"miniflux.app/v2/internal/reader/sanitizer"
	"miniflux.app/v2/internal/urllib"
)

type Atom03Adapter struct {
	atomFeed *Atom03Feed
}

func NewAtom03Adapter(atomFeed *Atom03Feed) *Atom03Adapter {
	return &Atom03Adapter{atomFeed}
}

func (a *Atom03Adapter) BuildFeed(baseURL string) *model.Feed {
	feed := new(model.Feed)

	// Populate the feed URL.
	feedURL := a.atomFeed.Links.firstLinkWithRelation("self")
	if feedURL != "" {
		if absoluteFeedURL, err := urllib.AbsoluteURL(baseURL, feedURL); err == nil {
			feed.FeedURL = absoluteFeedURL
		}
	} else {
		feed.FeedURL = baseURL
	}

	// Populate the site URL.
	siteURL := a.atomFeed.Links.OriginalLink()
	if siteURL != "" {
		if absoluteSiteURL, err := urllib.AbsoluteURL(baseURL, siteURL); err == nil {
			feed.SiteURL = absoluteSiteURL
		}
	} else {
		feed.SiteURL = baseURL
	}

	// Populate the feed title.
	feed.Title = a.atomFeed.Title.Content()
	if feed.Title == "" {
		feed.Title = feed.SiteURL
	}

	for _, atomEntry := range a.atomFeed.Entries {
		entry := model.NewEntry()

		// Populate the entry URL.
		entry.URL = atomEntry.Links.OriginalLink()
		if entry.URL != "" {
			if absoluteEntryURL, err := urllib.AbsoluteURL(feed.SiteURL, entry.URL); err == nil {
				entry.URL = absoluteEntryURL
			}
		}

		// Populate the entry content.
		entry.Content = atomEntry.Content.Content()
		if entry.Content == "" {
			entry.Content = atomEntry.Summary.Content()
		}

		// Populate the entry title.
		entry.Title = atomEntry.Title.Content()
		if entry.Title == "" {
			entry.Title = sanitizer.TruncateHTML(entry.Content, 100)
		}
		if entry.Title == "" {
			entry.Title = entry.URL
		}

		// Populate the entry author.
		entry.Author = atomEntry.Author.PersonName()
		if entry.Author == "" {
			entry.Author = a.atomFeed.Author.PersonName()
		}

		// Populate the entry date.
		for _, value := range []string{atomEntry.Issued, atomEntry.Modified, atomEntry.Created} {
			if parsedDate, err := date.Parse(value); err == nil {
				entry.Date = parsedDate
				break
			} else {
				slog.Debug("Unable to parse date from Atom 0.3 feed",
					slog.String("date", value),
					slog.String("id", atomEntry.ID),
					slog.Any("error", err),
				)
			}
		}
		if entry.Date.IsZero() {
			entry.Date = time.Now()
		}

		// Generate the entry hash.
		for _, value := range []string{atomEntry.ID, atomEntry.Links.OriginalLink()} {
			if value != "" {
				entry.Hash = crypto.Hash(value)
				break
			}
		}

		feed.Entries = append(feed.Entries, entry)
	}

	return feed
}