feat: order items deterministically by local date desc, hoise rss-to-link conv

This commit is contained in:
Marc 2024-09-21 15:11:41 -04:00
parent fa3ff3094e
commit b028cc1c6d
Signed by: marc
GPG key ID: 048E042F22B5DC79
5 changed files with 37 additions and 14 deletions

View file

@ -22,7 +22,12 @@ func fetchFeed(url string) {
d := ParseFeed(b) d := ParseFeed(b)
b, _ = json.Marshal(d.Channel.ItemsToLinks()) links := []Link{}
for _, feedItem := range d.Channel.Items {
links = append(links, Link{Url: feedItem.Link, Title: feedItem.Title, PublishedDate: feedItem.GetPublishedDate()})
}
b, _ = json.Marshal(links)
cacheKey := fmt.Sprintf("feeds:%s", url) cacheKey := fmt.Sprintf("feeds:%s", url)
SharedCache.Set(cacheKey, string(b)) SharedCache.Set(cacheKey, string(b))
} }

View file

@ -17,6 +17,7 @@ import (
type RenderMeta struct { type RenderMeta struct {
RenderStart time.Time RenderStart time.Time
Location string
} }
type RenderContext struct { type RenderContext struct {
@ -51,7 +52,7 @@ func Render(w io.Writer, templateName string, data interface{}) error {
return err return err
} }
renderContext := RenderContext{Data: data, Meta: RenderMeta{RenderStart: start}} renderContext := RenderContext{Data: data, Meta: RenderMeta{RenderStart: start, Location: "America/New_York"}}
return tmpl.ExecuteTemplate(w, "base", renderContext) return tmpl.ExecuteTemplate(w, "base", renderContext)
} }

View file

@ -5,14 +5,24 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"slices"
"time"
) )
type Link struct { type Link struct {
Url string `json:"url"` Url string `json:"url"`
PublishedDate string `json:"publishedDate"` PublishedDate time.Time `json:"publishedDate"`
Title string `json:"title"` Title string `json:"title"`
} }
func (l Link) GetLocalizedPublishedDate(loc string) time.Time {
if loc == "" {
loc = "America/New_York"
}
location, _ := time.LoadLocation(loc)
return l.PublishedDate.In(location)
}
// Healthcheck route // Healthcheck route
// //
// Confirms that the app is alive without guarantees // Confirms that the app is alive without guarantees
@ -39,6 +49,14 @@ func listContent(w http.ResponseWriter, r *http.Request) {
links = append(links, formattedItems...) links = append(links, formattedItems...)
} }
slices.SortStableFunc(links, func(a Link, b Link) int {
if a.PublishedDate.After(b.PublishedDate) {
return -1
}
return 1
})
Render(w, "index", links) Render(w, "index", links)
} }

15
rss.go
View file

@ -2,6 +2,7 @@ package main
import ( import (
"encoding/xml" "encoding/xml"
"time"
) )
type Document struct { type Document struct {
@ -12,7 +13,8 @@ type Item struct {
Title string `xml:"title"` Title string `xml:"title"`
Link string `xml:"link"` Link string `xml:"link"`
Description string `xml:"description"` Description string `xml:"description"`
PublishedDate string `xml:"pubDate"` PubDate string `xml:"pubDate"`
PublishedDate time.Time
} }
type Channel struct { type Channel struct {
@ -21,14 +23,11 @@ type Channel struct {
Items []Item `xml:"item"` Items []Item `xml:"item"`
} }
func (c Channel) ItemsToLinks() []Link { const DATE_FORMAT = "Mon, 02 Jan 2006 15:04:05 -0700"
formattedItems := []Link{}
for _, feedItem := range c.Items { func (i Item) GetPublishedDate() time.Time {
formattedItems = append(formattedItems, Link{Url: feedItem.Link, Title: feedItem.Title, PublishedDate: feedItem.PublishedDate}) published, _ := time.Parse(DATE_FORMAT, i.PubDate)
} return published
return formattedItems
} }
func ParseFeed(raw []byte) Document { func ParseFeed(raw []byte) Document {

View file

@ -3,7 +3,7 @@
{{ range .Data }} {{ range .Data }}
<li> <li>
<a href="{{ .Url }}">{{ .Title }}</a> <a href="{{ .Url }}">{{ .Title }}</a>
<span>{{ .PublishedDate }}</span> <span>{{ .GetLocalizedPublishedDate $.Meta.Location }}</span>
</li> </li>
{{ end }} {{ end }}
</ul> </ul>