Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
var Tpl = template.Must(template.New("").Parse(`
<!DOCTYPE html><html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="data:image/x-icon;base64,AAABAAEAEBAQAAAAAAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAhFAUAVUCzAJSHhQD1PycAo6OjAFmWqADo6e0ARCPZAFdUUQDe3t4AL5E6AHvF2wBIgbAAAAAAAAAAAAAAAAAAOqqqaZmZbMyqOqNoSEhszGZmZmZmZmZmiEhIZxEXaEiZmZlnEXdpmYSEhGN3c2SEmZmZYztzaZmISEhjuyNoSJmZmWO7U2mZhISEY4iDZIRmZmZmZmZmZgYAYABgYGAABgBgZgBgBmAGYGAGBgYGAABgYGYGBgYGAGBgBgZmBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" rel="icon" type="image/x-icon" />
<title>News</title>
<style type="text/css">
html {
padding: 0;
margin: 0;
}
body {
padding: 2em 0;
margin: 0;
font-family: sans-serif;
font-size: 16px;
background-color:#282828;
}
.container {
max-width: 1024px;
margin: 0 auto;
text-align: center;
}
.item {
display: block;
font-size: 18px;
padding: 1em 0.5em 0.5em 0.5em;
color: #000;
font-weight: bold;
background: #ddd;
border-bottom: 1px solid #ccc;
}
.tag {
float: right;
border: 1px solid #ccc;
border-radius: 3px;
padding: 5px;
margin: -10px 0 0 5px;
background-color: #ddd;
font-weight: normal;
}
.item:first-child {
border-top: 1px solid #aaa;
}
.item:visited {
color: #873B3B;
}
.item, .item:visited {
text-decoration: none;
text-align: left;
}
.item:hover, .item:active {
text-decoration: underline;
}
.next {
display: inline-block;
margin: 20px auto;
font-size: 24px;
padding: 0.5em;
color: #000;
font-weight: bold;
background: #EEE;
border-bottom: 1px solid #ccc;
border-radius: 5px;
text-decoration: none;
}
.next:hover, .next:active {
text-decoration: underline;
}
.feed {
display: none;
}
</style>
</head>
<body>
{{range $url, $title := .Feeds}}
<a class="feed" href="{{$url}}">{{$title}}</a>{{end}}
<div class="container">{{range .Items}}
<a class="item" target="_blank" href="{{.URL}}">{{if .Tag}}<div class="tag">{{.Tag}}</div>{{end}}{{.Title}}</a>{{end}}
{{if gt .NextPage 1}}<a class="next" href="page{{.NextPage}}.html">Next</a>{{end}}
</div>
</body>
</html>`))
Tpl is the default template used to generate index.html and page.html files. Can be customized using -template command-line argument.
Functions ¶
func MakeURLFetcher ¶
func MakeURLFetcher(log *logrus.Logger, minDomainRequestInterval time.Duration, client *http.Client) func(URL string) (content []byte, err error)
MakeURLFetcher is the default HTTP client used to fetch feed XML. The other one is fakeURLFetcher() used for testing. There's also a retired makeCachedURLFetcher() which was using during initial phases of development and is kept in misc.go
Types ¶
type Aggregator ¶
type Aggregator struct { Items []Item // Ordered from newest to oldest. Always prepend new items. // Feeds is a map of URLs -> Titles for feeds. This needs to be stored somewhere so reader knows from where to fetch news Feeds map[string]string // We store item URLs so we know when something new appears KnownItems map[string]bool Directory string URLFetcher func(url string) ([]byte, error) ItemsPerPage int NextPage int // contains filtered or unexported fields }
Aggregator is the core structure than fetches feeds and saves them to html. See Aggregator.Update()
func New ¶
func New(directory string) (*Aggregator, error)
New creates an Aggregator with default URL fetcher
func NewWithCustom ¶
func NewWithCustom(log *logrus.Logger, directory string, itemsPerPage int, URLFetcher func(URL string) ([]byte, error)) (*Aggregator, error)
NewWithCustom allows for creating customized Aggregators such as custom URL fetcher for testing or with custom http.client minDomainRequestInterval is the minimum time we must wait between calls to same domain. Aka debouncer. For cases like multiple reddit.com feeds.
func (*Aggregator) ImportOPMLFile ¶ added in v1.2.0
func (agg *Aggregator) ImportOPMLFile(filePath string) (importedFeeds int, err error)
func (*Aggregator) Update ¶
func (agg *Aggregator) Update() (err error)
Update reads feed URLs from index.html, fetches RSS/Atom feed from each URL found and save everything back to index.html. Also generates new pageX.html files when index.html is too large.
type CustomRSSTranslator ¶
type CustomRSSTranslator struct {
// contains filtered or unexported fields
}
CustomRSSTranslator is currently used to instruct mmcdole/gofeed to parse <comments> as item link in Reddit's feed
func NewCustomRSSTranslator ¶
func NewCustomRSSTranslator() *CustomRSSTranslator
NewCustomRSSTranslator creates a new XML feed translator to be used by our instance of mmcdole/gofeed
type Item ¶
Item represents a link retrieved from feed
func (*Item) SetTag ¶
func (item *Item) SetTag()
SetTag fills .Tag based on the URL. Examples: /r/programming for https://www.reddit.com/r/programming/comments/9p07bh/convert_string_to_int_in_java/ slashdot for https://science.slashdot.org/story/18/10/17/1552218/the-results-of-your-genetic-test-are-reassuring-but-that-can-change Hacker News for https://news.ycombinator.com/item?id=18240182 domain.com for https://www.domain.com/item123