refactoring webmention interface

This commit is contained in:
Niko Abeler 2022-09-10 14:04:13 +02:00
parent 4b9a5adf5c
commit 881940cd88
3 changed files with 43 additions and 45 deletions

58
post.go
View File

@ -2,7 +2,6 @@ package owl
import ( import (
"bytes" "bytes"
"errors"
"io/ioutil" "io/ioutil"
"net/url" "net/url"
"os" "os"
@ -201,14 +200,18 @@ func (post *Post) persistWebmentions(webmentions PostWebmetions) error {
return nil return nil
} }
// PersistWebmentionOutgoing persists incoming webmention
func (post *Post) PersistIncomingWebmention(webmention WebmentionIn) error { func (post *Post) PersistIncomingWebmention(webmention WebmentionIn) error {
post.wmLock.Lock()
defer post.wmLock.Unlock()
wms := post.Webmentions() wms := post.Webmentions()
// if target is not in status, add it // if target is not in status, add it
replaced := false replaced := false
for i, t := range wms.Incoming { for i, t := range wms.Incoming {
if t.Source == webmention.Source { if t.Source == webmention.Source {
wms.Incoming[i] = webmention wms.Incoming[i].UpdateWith(webmention)
replaced = true replaced = true
break break
} }
@ -222,8 +225,7 @@ func (post *Post) PersistIncomingWebmention(webmention WebmentionIn) error {
} }
// PersistOutgoingWebmention persists a webmention to the webmention file. // PersistOutgoingWebmention persists a webmention to the webmention file.
// If `newLink` is true, the webmention is only persisted if it is not already in the webmention file. func (post *Post) PersistOutgoingWebmention(webmention *WebmentionOut) error {
func (post *Post) PersistOutgoingWebmention(webmention *WebmentionOut, newLink bool) error {
post.wmLock.Lock() post.wmLock.Lock()
defer post.wmLock.Unlock() defer post.wmLock.Unlock()
@ -233,11 +235,7 @@ func (post *Post) PersistOutgoingWebmention(webmention *WebmentionOut, newLink b
replaced := false replaced := false
for i, t := range wms.Outgoing { for i, t := range wms.Outgoing {
if t.Target == webmention.Target { if t.Target == webmention.Target {
// if newLink is true, only replace if the link is new wms.Outgoing[i].UpdateWith(*webmention)
if newLink {
return nil
}
wms.Outgoing[i] = *webmention
replaced = true replaced = true
break break
} }
@ -250,45 +248,21 @@ func (post *Post) PersistOutgoingWebmention(webmention *WebmentionOut, newLink b
return post.persistWebmentions(wms) return post.persistWebmentions(wms)
} }
func (post *Post) getIncomingWebmentionBySource(source string) (WebmentionIn, error) {
wms := post.Webmentions()
for _, wm := range wms.Incoming {
if wm.Source == source {
return wm, nil
}
}
return WebmentionIn{}, errors.New("not found")
}
func (post *Post) AddIncomingWebmention(source string) error { func (post *Post) AddIncomingWebmention(source string) error {
post.wmLock.Lock()
defer post.wmLock.Unlock()
// Check if file already exists // Check if file already exists
_, err := post.getIncomingWebmentionBySource(source) wm := WebmentionIn{
if err != nil {
wms := post.Webmentions()
wms.Incoming = append(wms.Incoming, WebmentionIn{
Source: source, Source: source,
}) }
defer func() { defer func() {
go post.EnrichWebmention(source) go post.EnrichWebmention(wm)
}() }()
return post.persistWebmentions(wms) return post.PersistIncomingWebmention(wm)
}
return nil
} }
func (post *Post) EnrichWebmention(source string) error { func (post *Post) EnrichWebmention(webmention WebmentionIn) error {
post.wmLock.Lock() resp, err := post.user.repo.HttpClient.Get(webmention.Source)
defer post.wmLock.Unlock()
resp, err := post.user.repo.HttpClient.Get(source)
if err == nil { if err == nil {
webmention, err := post.getIncomingWebmentionBySource(source)
if err != nil {
return err
}
entry, err := post.user.repo.Parser.ParseHEntry(resp) entry, err := post.user.repo.Parser.ParseHEntry(resp)
if err == nil { if err == nil {
webmention.Title = entry.Title webmention.Title = entry.Title
@ -324,13 +298,13 @@ func (post *Post) ScanForLinks() error {
for _, link := range links { for _, link := range links {
post.PersistOutgoingWebmention(&WebmentionOut{ post.PersistOutgoingWebmention(&WebmentionOut{
Target: link, Target: link,
}, true) })
} }
return nil return nil
} }
func (post *Post) SendWebmention(webmention WebmentionOut) error { func (post *Post) SendWebmention(webmention WebmentionOut) error {
defer post.PersistOutgoingWebmention(&webmention, false) defer post.PersistOutgoingWebmention(&webmention)
webmention.ScannedAt = time.Now() webmention.ScannedAt = time.Now()
resp, err := post.user.repo.HttpClient.Get(webmention.Target) resp, err := post.user.repo.HttpClient.Get(webmention.Target)

View File

@ -240,7 +240,7 @@ func TestEnrichAddsTitle(t *testing.T) {
post, _ := user.CreateNewPost("testpost") post, _ := user.CreateNewPost("testpost")
post.AddIncomingWebmention("https://example.com") post.AddIncomingWebmention("https://example.com")
post.EnrichWebmention("https://example.com") post.EnrichWebmention(owl.WebmentionIn{Source: "https://example.com"})
mentions := post.IncomingWebmentions() mentions := post.IncomingWebmentions()
if len(mentions) != 1 { if len(mentions) != 1 {

View File

@ -19,6 +19,18 @@ type WebmentionIn struct {
RetrievedAt time.Time `yaml:"retrieved_at"` RetrievedAt time.Time `yaml:"retrieved_at"`
} }
func (webmention *WebmentionIn) UpdateWith(update WebmentionIn) {
if update.Title != "" {
webmention.Title = update.Title
}
if update.ApprovalStatus != "" {
webmention.ApprovalStatus = update.ApprovalStatus
}
if !update.RetrievedAt.IsZero() {
webmention.RetrievedAt = update.RetrievedAt
}
}
type WebmentionOut struct { type WebmentionOut struct {
Target string `yaml:"target"` Target string `yaml:"target"`
Supported bool `yaml:"supported"` Supported bool `yaml:"supported"`
@ -26,6 +38,18 @@ type WebmentionOut struct {
LastSentAt time.Time `yaml:"last_sent_at"` LastSentAt time.Time `yaml:"last_sent_at"`
} }
func (webmention *WebmentionOut) UpdateWith(update WebmentionOut) {
if update.Supported {
webmention.Supported = update.Supported
}
if !update.ScannedAt.IsZero() {
webmention.ScannedAt = update.ScannedAt
}
if !update.LastSentAt.IsZero() {
webmention.LastSentAt = update.LastSentAt
}
}
type HttpClient interface { type HttpClient interface {
Get(url string) (resp *http.Response, err error) Get(url string) (resp *http.Response, err error)
Post(url, contentType string, body io.Reader) (resp *http.Response, err error) Post(url, contentType string, body io.Reader) (resp *http.Response, err error)