mirror of
https://github.com/makew0rld/amfora.git
synced 2024-12-04 14:46:29 -05:00
Handle multiple links per post, prefer item author over feed author
This commit is contained in:
parent
8875af6c57
commit
ef8295b0a4
3
NOTES.md
3
NOTES.md
@ -1,7 +1,8 @@
|
|||||||
# Notes
|
# Notes
|
||||||
|
|
||||||
## Feeds (temp)
|
## Feeds (temp)
|
||||||
- Feed page doesn't update automatically if you add a feed by bottom bar URL while already on the feed page
|
- Support multiple links in Atom feeds
|
||||||
|
- Display gemini one if it exist, then HTTP(S), then whatever is first
|
||||||
- TODO: remove all logger lines
|
- TODO: remove all logger lines
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
148
feeds/entries.go
Normal file
148
feeds/entries.go
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
package feeds
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/makeworld-the-better-one/amfora/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This file contains funcs for creating PageEntries, which
|
||||||
|
// are consumed by display/feeds.go
|
||||||
|
|
||||||
|
// getURL returns a URL to be used in a PageEntry, from a
|
||||||
|
// list of URLs for that item. It prefers gemini URLs, then
|
||||||
|
// HTTP(S), then by order.
|
||||||
|
func getURL(urls []string) string {
|
||||||
|
if len(urls) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var firstHTTP string
|
||||||
|
for _, u := range urls {
|
||||||
|
if strings.HasPrefix(u, "gemini://") {
|
||||||
|
return u
|
||||||
|
}
|
||||||
|
if (strings.HasPrefix(u, "http://") || strings.HasPrefix(u, "https://")) && firstHTTP == "" {
|
||||||
|
// First HTTP(S) URL in the list
|
||||||
|
firstHTTP = u
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if firstHTTP != "" {
|
||||||
|
return firstHTTP
|
||||||
|
}
|
||||||
|
return urls[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPageEntries returns the current list of PageEntries
|
||||||
|
// for use in rendering a page.
|
||||||
|
// The contents of the returned entries will never change,
|
||||||
|
// so this function needs to be called again to get updates.
|
||||||
|
// It always returns sorted entries - by post time, from newest to oldest.
|
||||||
|
func GetPageEntries() *PageEntries {
|
||||||
|
logger.Log.Println("feeds.GetPageEntries called")
|
||||||
|
|
||||||
|
var pe PageEntries
|
||||||
|
|
||||||
|
data.RLock()
|
||||||
|
|
||||||
|
for _, feed := range data.Feeds {
|
||||||
|
for _, item := range feed.Items {
|
||||||
|
if item.Links == nil || len(item.Links) == 0 {
|
||||||
|
// Ignore items without links
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set pub
|
||||||
|
|
||||||
|
var pub time.Time
|
||||||
|
|
||||||
|
// Try to use updated time first, then published
|
||||||
|
|
||||||
|
if !item.UpdatedParsed.IsZero() {
|
||||||
|
pub = *item.UpdatedParsed
|
||||||
|
} else if !item.PublishedParsed.IsZero() {
|
||||||
|
pub = *item.PublishedParsed
|
||||||
|
} else {
|
||||||
|
// No time on the post
|
||||||
|
pub = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set prefix
|
||||||
|
|
||||||
|
// Prefer using the feed title over anything else.
|
||||||
|
// Many feeds in Gemini only have this due to gemfeed's default settings.
|
||||||
|
prefix := feed.Title
|
||||||
|
|
||||||
|
if prefix == "" {
|
||||||
|
// feed.Title was empty
|
||||||
|
|
||||||
|
if item.Author != nil {
|
||||||
|
// Prefer using the item author over the feed author
|
||||||
|
prefix = item.Author.Name
|
||||||
|
} else {
|
||||||
|
if feed.Author != nil {
|
||||||
|
prefix = feed.Author.Name
|
||||||
|
} else {
|
||||||
|
prefix = "[author unknown]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// There's already a title, so add the author (if exists) to
|
||||||
|
// the end of the title in parentheses.
|
||||||
|
// Don't add the author if it's the same as the title.
|
||||||
|
|
||||||
|
if item.Author != nil && item.Author.Name != prefix {
|
||||||
|
// Prefer using the item author over the feed author
|
||||||
|
prefix += " (" + item.Author.Name + ")"
|
||||||
|
} else if feed.Author != nil && feed.Author.Name != prefix {
|
||||||
|
prefix += " (" + feed.Author.Name + ")"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pe.Entries = append(pe.Entries, &PageEntry{
|
||||||
|
Prefix: prefix,
|
||||||
|
Title: item.Title,
|
||||||
|
URL: getURL(item.Links),
|
||||||
|
Published: pub,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for u, page := range data.Pages {
|
||||||
|
parsed, _ := url.Parse(u)
|
||||||
|
|
||||||
|
// Path is title
|
||||||
|
title := parsed.Path
|
||||||
|
if strings.HasPrefix(title, "/~") {
|
||||||
|
// A user dir
|
||||||
|
title = title[2:] // Remove beginning slash and tilde
|
||||||
|
// Remove trailing slash if the root of a user dir is being tracked
|
||||||
|
if strings.Count(title, "/") <= 1 && title[len(title)-1] == '/' {
|
||||||
|
title = title[:len(title)-1]
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(title, "/users/") {
|
||||||
|
// "/users/" is removed for aesthetics when tracking hosted users
|
||||||
|
title = strings.TrimPrefix(title, "/users/")
|
||||||
|
title = strings.TrimPrefix(title, "~") // Remove leading tilde
|
||||||
|
// Remove trailing slash if the root of a user dir is being tracked
|
||||||
|
if strings.Count(title, "/") <= 1 && title[len(title)-1] == '/' {
|
||||||
|
title = title[:len(title)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pe.Entries = append(pe.Entries, &PageEntry{
|
||||||
|
Prefix: parsed.Host,
|
||||||
|
Title: title,
|
||||||
|
URL: u,
|
||||||
|
Published: page.Changed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
data.RUnlock()
|
||||||
|
|
||||||
|
sort.Sort(&pe)
|
||||||
|
return &pe
|
||||||
|
}
|
109
feeds/feeds.go
109
feeds/feeds.go
@ -7,11 +7,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
urlPkg "net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -170,6 +168,8 @@ func AddFeed(url string, feed *gofeed.Feed) error {
|
|||||||
feed.DublinCoreExt = nil
|
feed.DublinCoreExt = nil
|
||||||
feed.ITunesExt = nil
|
feed.ITunesExt = nil
|
||||||
feed.Custom = nil
|
feed.Custom = nil
|
||||||
|
feed.Link = ""
|
||||||
|
feed.Links = nil
|
||||||
for _, item := range feed.Items {
|
for _, item := range feed.Items {
|
||||||
item.Description = ""
|
item.Description = ""
|
||||||
item.Content = ""
|
item.Content = ""
|
||||||
@ -180,6 +180,7 @@ func AddFeed(url string, feed *gofeed.Feed) error {
|
|||||||
item.ITunesExt = nil
|
item.ITunesExt = nil
|
||||||
item.Extensions = nil
|
item.Extensions = nil
|
||||||
item.Custom = nil
|
item.Custom = nil
|
||||||
|
item.Link = "" // Links is used instead
|
||||||
}
|
}
|
||||||
|
|
||||||
data.feedMu.Lock()
|
data.feedMu.Lock()
|
||||||
@ -361,107 +362,3 @@ func updateAll() {
|
|||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPageEntries returns the current list of PageEntries
|
|
||||||
// for use in rendering a page.
|
|
||||||
// The contents of the returned entries will never change,
|
|
||||||
// so this function needs to be called again to get updates.
|
|
||||||
// It always returns sorted entries - by post time, from newest to oldest.
|
|
||||||
func GetPageEntries() *PageEntries {
|
|
||||||
logger.Log.Println("feeds.GetPageEntries called")
|
|
||||||
|
|
||||||
var pe PageEntries
|
|
||||||
|
|
||||||
data.RLock()
|
|
||||||
|
|
||||||
for _, feed := range data.Feeds {
|
|
||||||
for _, item := range feed.Items {
|
|
||||||
|
|
||||||
var pub time.Time
|
|
||||||
|
|
||||||
// Try to use updated time first, then published
|
|
||||||
|
|
||||||
if !item.UpdatedParsed.IsZero() {
|
|
||||||
pub = *item.UpdatedParsed
|
|
||||||
} else if !item.PublishedParsed.IsZero() {
|
|
||||||
pub = *item.PublishedParsed
|
|
||||||
} else {
|
|
||||||
// No time on the post
|
|
||||||
pub = time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prefer using the feed title over anything else.
|
|
||||||
// Many feeds in Gemini only have this due to gemfeed's default settings.
|
|
||||||
prefix := feed.Title
|
|
||||||
|
|
||||||
if prefix == "" {
|
|
||||||
// feed.Title was empty
|
|
||||||
if feed.Author != nil {
|
|
||||||
// Prefer using the feed author over the item author
|
|
||||||
prefix = feed.Author.Name
|
|
||||||
} else {
|
|
||||||
if item.Author != nil {
|
|
||||||
prefix = item.Author.Name
|
|
||||||
} else {
|
|
||||||
prefix = "[author unknown]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// There's already a title, so add the author (if exists) to
|
|
||||||
// the end of the title in parentheses.
|
|
||||||
// Don't add the author if it's the same as the title.
|
|
||||||
|
|
||||||
if feed.Author != nil && feed.Author.Name != prefix {
|
|
||||||
// Prefer using the feed author over the item author
|
|
||||||
prefix += " (" + feed.Author.Name + ")"
|
|
||||||
} else {
|
|
||||||
if item.Author != nil && item.Author.Name != prefix {
|
|
||||||
prefix += " (" + item.Author.Name + ")"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pe.Entries = append(pe.Entries, &PageEntry{
|
|
||||||
Prefix: prefix,
|
|
||||||
Title: item.Title,
|
|
||||||
URL: item.Link,
|
|
||||||
Published: pub,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for url, page := range data.Pages {
|
|
||||||
parsed, _ := urlPkg.Parse(url)
|
|
||||||
|
|
||||||
// Path is title
|
|
||||||
title := parsed.Path
|
|
||||||
if strings.HasPrefix(title, "/~") {
|
|
||||||
// A user dir
|
|
||||||
title = title[2:] // Remove beginning slash and tilde
|
|
||||||
// Remove trailing slash if the root of a user dir is being tracked
|
|
||||||
if strings.Count(title, "/") <= 1 && title[len(title)-1] == '/' {
|
|
||||||
title = title[:len(title)-1]
|
|
||||||
}
|
|
||||||
} else if strings.HasPrefix(title, "/users/") {
|
|
||||||
// "/users/" is removed for aesthetics when tracking hosted users
|
|
||||||
title = strings.TrimPrefix(title, "/users/")
|
|
||||||
title = strings.TrimPrefix(title, "~") // Remove leading tilde
|
|
||||||
// Remove trailing slash if the root of a user dir is being tracked
|
|
||||||
if strings.Count(title, "/") <= 1 && title[len(title)-1] == '/' {
|
|
||||||
title = title[:len(title)-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pe.Entries = append(pe.Entries, &PageEntry{
|
|
||||||
Prefix: parsed.Host,
|
|
||||||
Title: title,
|
|
||||||
URL: url,
|
|
||||||
Published: page.Changed,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
data.RUnlock()
|
|
||||||
|
|
||||||
sort.Sort(&pe)
|
|
||||||
return &pe
|
|
||||||
}
|
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Example JSON
|
Example stored JSON.
|
||||||
|
|
||||||
{
|
{
|
||||||
"feeds": {
|
"feeds": {
|
||||||
|
2
go.mod
2
go.mod
@ -27,3 +27,5 @@ require (
|
|||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||||
gopkg.in/ini.v1 v1.57.0 // indirect
|
gopkg.in/ini.v1 v1.57.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/mmcdole/gofeed => github.com/makeworld-the-better-one/gofeed v1.1.1-0.20201123002655-c0c6354134fe
|
||||||
|
4
go.sum
4
go.sum
@ -137,6 +137,8 @@ github.com/makeworld-the-better-one/go-gemini v0.9.1 h1:/Vc6Y4Y1aOi4lZIBA1wDe+4N
|
|||||||
github.com/makeworld-the-better-one/go-gemini v0.9.1/go.mod h1:P7/FbZ+IEIbA/d+A0Y3w2GNgD8SA2AcNv7aDGJbaWG4=
|
github.com/makeworld-the-better-one/go-gemini v0.9.1/go.mod h1:P7/FbZ+IEIbA/d+A0Y3w2GNgD8SA2AcNv7aDGJbaWG4=
|
||||||
github.com/makeworld-the-better-one/go-isemoji v1.1.0 h1:wZBHOKB5zAIgaU2vaWnXFDDhatebB8TySrNVxjVV84g=
|
github.com/makeworld-the-better-one/go-isemoji v1.1.0 h1:wZBHOKB5zAIgaU2vaWnXFDDhatebB8TySrNVxjVV84g=
|
||||||
github.com/makeworld-the-better-one/go-isemoji v1.1.0/go.mod h1:FBjkPl9rr0G4vlZCc+Mr+QcnOfGCTbGWYW8/1sp06I0=
|
github.com/makeworld-the-better-one/go-isemoji v1.1.0/go.mod h1:FBjkPl9rr0G4vlZCc+Mr+QcnOfGCTbGWYW8/1sp06I0=
|
||||||
|
github.com/makeworld-the-better-one/gofeed v1.1.1-0.20201123002655-c0c6354134fe h1:i3b9Qy5z23DcXRnrsMYcM5s9Ng5VIidM1xZd+szuTsY=
|
||||||
|
github.com/makeworld-the-better-one/gofeed v1.1.1-0.20201123002655-c0c6354134fe/go.mod h1:QQO3maftbOu+hiVOGOZDRLymqGQCos4zxbA4j89gMrE=
|
||||||
github.com/makeworld-the-better-one/progressbar/v3 v3.3.5-0.20200710151429-125743e22b4f h1:YEUlTs5gb35UlBLTgqrub9axWTYB3d7/8TxrkJDZpRI=
|
github.com/makeworld-the-better-one/progressbar/v3 v3.3.5-0.20200710151429-125743e22b4f h1:YEUlTs5gb35UlBLTgqrub9axWTYB3d7/8TxrkJDZpRI=
|
||||||
github.com/makeworld-the-better-one/progressbar/v3 v3.3.5-0.20200710151429-125743e22b4f/go.mod h1:X6sxWNi9PBgQybpR4fpXPVD5fm7svLqZTQ5DJuERIoM=
|
github.com/makeworld-the-better-one/progressbar/v3 v3.3.5-0.20200710151429-125743e22b4f/go.mod h1:X6sxWNi9PBgQybpR4fpXPVD5fm7svLqZTQ5DJuERIoM=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
@ -161,8 +163,6 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F
|
|||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/mapstructure v1.3.1 h1:cCBH2gTD2K0OtLlv/Y5H01VQCqmlDxz30kS5Y5bqfLA=
|
github.com/mitchellh/mapstructure v1.3.1 h1:cCBH2gTD2K0OtLlv/Y5H01VQCqmlDxz30kS5Y5bqfLA=
|
||||||
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mmcdole/gofeed v1.1.0 h1:T2WrGLVJRV04PY2qwhEJLHCt9JiCtBhb6SmC8ZvJH08=
|
|
||||||
github.com/mmcdole/gofeed v1.1.0/go.mod h1:PPiVwgDXLlz2N83KB4TrIim2lyYM5Zn7ZWH9Pi4oHUk=
|
|
||||||
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/S/mDBM5plIU8v/Qhfz41hkDIAI=
|
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf h1:sWGE2v+hO0Nd4yFU/S/mDBM5plIU8v/Qhfz41hkDIAI=
|
||||||
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf/go.mod h1:pasqhqstspkosTneA62Nc+2p9SOBBYAPbnmRRWPQ0V8=
|
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf/go.mod h1:pasqhqstspkosTneA62Nc+2p9SOBBYAPbnmRRWPQ0V8=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
Loading…
Reference in New Issue
Block a user