Improve ActivityPub and Webmention verification

This commit is contained in:
Jan-Lukas Else 2021-06-15 22:20:54 +02:00
parent 32339e5c41
commit 1ef5b11310
3 changed files with 38 additions and 22 deletions

View File

@ -17,6 +17,7 @@ import (
"github.com/go-chi/chi/v5"
"github.com/go-fed/httpsig"
"github.com/spf13/cast"
)
func (a *goBlog) initActivityPub() error {
@ -167,17 +168,22 @@ func (a *goBlog) apHandleInbox(w http.ResponseWriter, r *http.Request) {
case "Create":
{
if object, ok := activity["object"].(map[string]interface{}); ok {
inReplyTo, hasReplyToString := object["inReplyTo"].(string)
id, hasID := object["id"].(string)
if hasReplyToString && hasID && len(inReplyTo) > 0 && len(id) > 0 && strings.Contains(inReplyTo, blogIri) {
inReplyTo := cast.ToString(object["inReplyTo"])
objectId := cast.ToString(object["id"])
objectUrl := cast.ToString(object["url"])
baseUrl := objectId
if objectUrl != "" {
baseUrl = objectUrl
}
if inReplyTo != "" && objectId != "" && strings.Contains(inReplyTo, blogIri) {
// It's an ActivityPub reply; save reply as webmention
_ = a.createWebmention(id, inReplyTo)
} else if content, hasContent := object["content"].(string); hasContent && hasID && len(id) > 0 {
_ = a.createWebmention(baseUrl, inReplyTo)
} else if content, hasContent := object["content"].(string); hasContent && objectId != "" {
// May be a mention; find links to blog and save them as webmentions
if links, err := allLinksFromHTMLString(content, id); err == nil {
if links, err := allLinksFromHTMLString(content, baseUrl); err == nil {
for _, link := range links {
if strings.Contains(link, blogIri) {
_ = a.createWebmention(id, link)
_ = a.createWebmention(baseUrl, link)
}
}
}

View File

@ -614,17 +614,22 @@ func noIndexHeader(next http.Handler) http.Handler {
}
type dynamicHandler struct {
router *chi.Mux
mutex sync.RWMutex
router *chi.Mux
mutex sync.RWMutex
initialized bool
}
func (d *dynamicHandler) swapHandler(h *chi.Mux) {
d.mutex.Lock()
d.router = h
d.initialized = true
d.mutex.Unlock()
}
func (d *dynamicHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for !d.initialized {
time.Sleep(1 * time.Second)
}
// Fix to use Path routing instead of RawPath routing in Chi
r.URL.RawPath = ""
// Serve request

View File

@ -72,7 +72,7 @@ func (a *goBlog) verifyMention(m *mention) error {
rec := httptest.NewRecorder()
for a.d == nil {
// Server not yet started
time.Sleep(10 * time.Second)
time.Sleep(1 * time.Second)
}
a.d.ServeHTTP(rec, req.WithContext(context.WithValue(req.Context(), loggedInKey, true)))
resp = rec.Result()
@ -89,11 +89,11 @@ func (a *goBlog) verifyMention(m *mention) error {
_, err := a.db.exec("delete from webmentions where source = @source and target = @target", sql.Named("source", m.Source), sql.Named("target", m.Target))
return err
}
if len(m.Content) > 500 {
m.Content = m.Content[0:497] + "…"
if cr := []rune(m.Content); len(cr) > 500 {
m.Content = string(cr[0:497]) + "…"
}
if len(m.Title) > 60 {
m.Title = m.Title[0:57] + "…"
if tr := []rune(m.Title); len(tr) > 60 {
m.Title = string(tr[0:57]) + "…"
}
newStatus := webmentionStatusVerified
if a.db.webmentionExists(m.Source, m.Target) {
@ -122,20 +122,25 @@ func (m *mention) verifyReader(body io.Reader) error {
}); !hasLink {
return errors.New("target not found in source")
}
// Set title
doc, err := goquery.NewDocumentFromReader(&gqBuffer)
if err != nil {
return err
}
if title := doc.Find("title"); title != nil {
m.Title = title.Text()
}
// Fill mention attributes
sourceURL, err := url.Parse(m.Source)
if err != nil {
return err
}
m.Title = ""
m.Content = ""
m.Author = ""
m.fillFromData(microformats.Parse(&mfBuffer, sourceURL))
// Set title when content is empty as well
if m.Title == "" && m.Content == "" {
doc, err := goquery.NewDocumentFromReader(&gqBuffer)
if err != nil {
return err
}
if title := doc.Find("title"); title != nil {
m.Title = title.Text()
}
}
return nil
}