forked from wgroeneveld/go-jamming
refactored package design to avoid circular deps
This commit is contained in:
parent
e717f6312b
commit
ddd465ce92
|
@ -0,0 +1,28 @@
|
||||||
|
package mf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"fmt"
|
||||||
|
"github.com/wgroeneveld/go-jamming/common"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Mention struct {
|
||||||
|
Source string
|
||||||
|
Target string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *Mention) String() string {
|
||||||
|
return fmt.Sprintf("source: %s, target: %s", wm.Source, wm.Target)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *Mention) AsPath(conf *common.Config) string {
|
||||||
|
filename := fmt.Sprintf("%x", md5.Sum([]byte("source=" + wm.Source+ ",target=" + wm.Target)))
|
||||||
|
domain, _ := conf.FetchDomain(wm.Target)
|
||||||
|
return conf.DataPath + "/" + domain + "/" + filename + ".json"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wm *Mention) SourceUrl() *url.URL {
|
||||||
|
url, _ := url.Parse(wm.Source)
|
||||||
|
return url
|
||||||
|
}
|
|
@ -1,22 +1,23 @@
|
||||||
package webmention
|
package mf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"willnorris.com/go/microformats"
|
"willnorris.com/go/microformats"
|
||||||
|
"github.com/wgroeneveld/go-jamming/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DateFormat = "2006-01-02T15:04:05"
|
DateFormat = "2006-01-02T15:04:05"
|
||||||
)
|
)
|
||||||
|
|
||||||
type indiewebAuthor struct {
|
type IndiewebAuthor struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Picture string `json:"picture"`
|
Picture string `json:"picture"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type indiewebData struct {
|
type IndiewebData struct {
|
||||||
Author indiewebAuthor `json:"author"`
|
Author IndiewebAuthor `json:"author"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
Published string `json:"published"`
|
Published string `json:"published"`
|
||||||
|
@ -26,9 +27,8 @@ type indiewebData struct {
|
||||||
Target string `json:"target"`
|
Target string `json:"target"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var now = time.Now
|
func PublishedNow(utcOffset int) string {
|
||||||
func publishedNow(utcOffset int) string {
|
return common.Now().UTC().Add(time.Duration(utcOffset) * time.Minute).Format("2006-01-02T15:04:05")
|
||||||
return now().UTC().Add(time.Duration(utcOffset) * time.Minute).Format("2006-01-02T15:04:05")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func shorten(txt string) string {
|
func shorten(txt string) string {
|
||||||
|
@ -41,7 +41,7 @@ func shorten(txt string) string {
|
||||||
// Go stuff: entry.Properties["name"][0].(string),
|
// Go stuff: entry.Properties["name"][0].(string),
|
||||||
// JS stuff: hEntry.properties?.name?.[0]
|
// JS stuff: hEntry.properties?.name?.[0]
|
||||||
// The problem: convoluted syntax and no optional chaining!
|
// The problem: convoluted syntax and no optional chaining!
|
||||||
func mfStr(mf *microformats.Microformat, key string) string {
|
func Str(mf *microformats.Microformat, key string) string {
|
||||||
val := mf.Properties[key]
|
val := mf.Properties[key]
|
||||||
if len(val) == 0 {
|
if len(val) == 0 {
|
||||||
return ""
|
return ""
|
||||||
|
@ -60,7 +60,7 @@ func mfStr(mf *microformats.Microformat, key string) string {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
func mfMap(mf *microformats.Microformat, key string) map[string]string {
|
func Map(mf *microformats.Microformat, key string) map[string]string {
|
||||||
val := mf.Properties[key]
|
val := mf.Properties[key]
|
||||||
if len(val) == 0 {
|
if len(val) == 0 {
|
||||||
return map[string]string{}
|
return map[string]string{}
|
||||||
|
@ -72,7 +72,7 @@ func mfMap(mf *microformats.Microformat, key string) map[string]string {
|
||||||
return mapVal
|
return mapVal
|
||||||
}
|
}
|
||||||
|
|
||||||
func mfProp(mf *microformats.Microformat, key string) *microformats.Microformat {
|
func Prop(mf *microformats.Microformat, key string) *microformats.Microformat {
|
||||||
val := mf.Properties[key]
|
val := mf.Properties[key]
|
||||||
if len(val) == 0 {
|
if len(val) == 0 {
|
||||||
return µformats.Microformat{
|
return µformats.Microformat{
|
||||||
|
@ -82,28 +82,28 @@ func mfProp(mf *microformats.Microformat, key string) *microformats.Microformat
|
||||||
return val[0].(*microformats.Microformat)
|
return val[0].(*microformats.Microformat)
|
||||||
}
|
}
|
||||||
|
|
||||||
func determinePublishedDate(hEntry *microformats.Microformat, utcOffset int) string {
|
func DeterminePublishedDate(hEntry *microformats.Microformat, utcOffset int) string {
|
||||||
publishedDate := mfStr(hEntry, "published")
|
publishedDate := Str(hEntry, "published")
|
||||||
if publishedDate == "" {
|
if publishedDate == "" {
|
||||||
return publishedNow(utcOffset)
|
return PublishedNow(utcOffset)
|
||||||
}
|
}
|
||||||
return publishedDate
|
return publishedDate
|
||||||
}
|
}
|
||||||
|
|
||||||
func determineAuthorName(hEntry *microformats.Microformat) string {
|
func DetermineAuthorName(hEntry *microformats.Microformat) string {
|
||||||
authorName := mfStr(mfProp(hEntry, "author"), "name")
|
authorName := Str(Prop(hEntry, "author"), "name")
|
||||||
if authorName == "" {
|
if authorName == "" {
|
||||||
return mfProp(hEntry, "author").Value
|
return Prop(hEntry, "author").Value
|
||||||
}
|
}
|
||||||
return authorName
|
return authorName
|
||||||
}
|
}
|
||||||
|
|
||||||
func determineMfType(hEntry *microformats.Microformat) string {
|
func DetermineType(hEntry *microformats.Microformat) string {
|
||||||
likeOf := mfStr(hEntry, "like-of")
|
likeOf := Str(hEntry, "like-of")
|
||||||
if likeOf != "" {
|
if likeOf != "" {
|
||||||
return "like"
|
return "like"
|
||||||
}
|
}
|
||||||
bookmarkOf := mfStr(hEntry, "bookmark-of")
|
bookmarkOf := Str(hEntry, "bookmark-of")
|
||||||
if bookmarkOf != "" {
|
if bookmarkOf != "" {
|
||||||
return "bookmark"
|
return "bookmark"
|
||||||
}
|
}
|
||||||
|
@ -111,27 +111,27 @@ func determineMfType(hEntry *microformats.Microformat) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mastodon uids start with "tag:server", but we do want indieweb uids from other sources
|
// Mastodon uids start with "tag:server", but we do want indieweb uids from other sources
|
||||||
func determineUrl(hEntry *microformats.Microformat, source string) string {
|
func DetermineUrl(hEntry *microformats.Microformat, source string) string {
|
||||||
uid := mfStr(hEntry, "uid")
|
uid := Str(hEntry, "uid")
|
||||||
if uid != "" && strings.HasPrefix(uid, "http") {
|
if uid != "" && strings.HasPrefix(uid, "http") {
|
||||||
return uid
|
return uid
|
||||||
}
|
}
|
||||||
url := mfStr(hEntry, "url")
|
url := Str(hEntry, "url")
|
||||||
if url != "" {
|
if url != "" {
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
return source
|
return source
|
||||||
}
|
}
|
||||||
|
|
||||||
func determineContent(hEntry *microformats.Microformat) string {
|
func DetermineContent(hEntry *microformats.Microformat) string {
|
||||||
bridgyTwitterContent := mfStr(hEntry, "bridgy-twitter-content")
|
bridgyTwitterContent := Str(hEntry, "bridgy-twitter-content")
|
||||||
if bridgyTwitterContent != "" {
|
if bridgyTwitterContent != "" {
|
||||||
return shorten(bridgyTwitterContent)
|
return shorten(bridgyTwitterContent)
|
||||||
}
|
}
|
||||||
summary := mfStr(hEntry, "summary")
|
summary := Str(hEntry, "summary")
|
||||||
if summary != "" {
|
if summary != "" {
|
||||||
return shorten(summary)
|
return shorten(summary)
|
||||||
}
|
}
|
||||||
contentEntry := mfMap(hEntry, "content")["value"]
|
contentEntry := Map(hEntry, "content")["value"]
|
||||||
return shorten(contentEntry)
|
return shorten(contentEntry)
|
||||||
}
|
}
|
|
@ -4,7 +4,8 @@ package pingback
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/wgroeneveld/go-jamming/app/webmention"
|
"github.com/wgroeneveld/go-jamming/app/mf"
|
||||||
|
"github.com/wgroeneveld/go-jamming/app/webmention/receive"
|
||||||
"github.com/wgroeneveld/go-jamming/rest"
|
"github.com/wgroeneveld/go-jamming/rest"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -30,11 +31,11 @@ func HandlePost(conf *common.Config) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
wm := webmention.Mention{
|
wm := mf.Mention{
|
||||||
Source: rpc.Source(),
|
Source: rpc.Source(),
|
||||||
Target: rpc.Target(),
|
Target: rpc.Target(),
|
||||||
}
|
}
|
||||||
receiver := webmention.Receiver{
|
receiver := receive.Receiver{
|
||||||
RestClient: &rest.HttpClient{},
|
RestClient: &rest.HttpClient{},
|
||||||
Conf: conf,
|
Conf: conf,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package send
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/wgroeneveld/go-jamming/app/mf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SendPingbackToEndpoint(endpoint string, mention mf.Mention) {
|
||||||
|
// do stuff
|
||||||
|
}
|
|
@ -2,6 +2,8 @@
|
||||||
package webmention
|
package webmention
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/wgroeneveld/go-jamming/app/mf"
|
||||||
|
"github.com/wgroeneveld/go-jamming/app/webmention/receive"
|
||||||
"net/http"
|
"net/http"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
@ -37,11 +39,11 @@ func HandlePost(conf *common.Config) http.HandlerFunc {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
wm := Mention{
|
wm := mf.Mention{
|
||||||
Source: r.FormValue("source"),
|
Source: r.FormValue("source"),
|
||||||
Target: target,
|
Target: target,
|
||||||
}
|
}
|
||||||
recv := &Receiver{
|
recv := &receive.Receiver{
|
||||||
RestClient: httpClient,
|
RestClient: httpClient,
|
||||||
Conf: conf,
|
Conf: conf,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
|
|
||||||
package webmention
|
package receive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"github.com/wgroeneveld/go-jamming/app/mf"
|
||||||
"github.com/wgroeneveld/go-jamming/common"
|
"github.com/wgroeneveld/go-jamming/common"
|
||||||
"github.com/wgroeneveld/go-jamming/rest"
|
"github.com/wgroeneveld/go-jamming/rest"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -18,25 +16,6 @@ import (
|
||||||
"willnorris.com/go/microformats"
|
"willnorris.com/go/microformats"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Mention struct {
|
|
||||||
Source string
|
|
||||||
Target string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *Mention) String() string {
|
|
||||||
return fmt.Sprintf("source: %s, target: %s", wm.Source, wm.Target)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *Mention) asPath(conf *common.Config) string {
|
|
||||||
filename := fmt.Sprintf("%x", md5.Sum([]byte("source=" + wm.Source+ ",target=" + wm.Target)))
|
|
||||||
domain, _ := conf.FetchDomain(wm.Target)
|
|
||||||
return conf.DataPath + "/" + domain + "/" + filename + ".json"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wm *Mention) sourceUrl() *url.URL {
|
|
||||||
url, _ := url.Parse(wm.Source)
|
|
||||||
return url
|
|
||||||
}
|
|
||||||
|
|
||||||
// used as a "class" to iject dependencies, just to be able to test. Do NOT like htis.
|
// used as a "class" to iject dependencies, just to be able to test. Do NOT like htis.
|
||||||
// Is there a better way? e.g. in validate, I just pass rest.Client as an arg. Not great either.
|
// Is there a better way? e.g. in validate, I just pass rest.Client as an arg. Not great either.
|
||||||
|
@ -45,7 +24,7 @@ type Receiver struct {
|
||||||
Conf *common.Config
|
Conf *common.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (recv *Receiver) Receive(wm Mention) {
|
func (recv *Receiver) Receive(wm mf.Mention) {
|
||||||
log.Info().Str("Webmention", wm.String()).Msg("OK: looks valid")
|
log.Info().Str("Webmention", wm.String()).Msg("OK: looks valid")
|
||||||
body, geterr := recv.RestClient.GetBody(wm.Source)
|
body, geterr := recv.RestClient.GetBody(wm.Source)
|
||||||
|
|
||||||
|
@ -58,8 +37,8 @@ func (recv *Receiver) Receive(wm Mention) {
|
||||||
recv.processSourceBody(body, wm)
|
recv.processSourceBody(body, wm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (recv *Receiver) deletePossibleOlderWebmention(wm Mention) {
|
func (recv *Receiver) deletePossibleOlderWebmention(wm mf.Mention) {
|
||||||
os.Remove(wm.asPath(recv.Conf))
|
os.Remove(wm.AsPath(recv.Conf))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHEntry(data *microformats.Data) *microformats.Microformat {
|
func getHEntry(data *microformats.Data) *microformats.Microformat {
|
||||||
|
@ -72,32 +51,32 @@ func getHEntry(data *microformats.Data) *microformats.Microformat {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (recv *Receiver) processSourceBody(body string, wm Mention) {
|
func (recv *Receiver) processSourceBody(body string, wm mf.Mention) {
|
||||||
if !strings.Contains(body, wm.Target) {
|
if !strings.Contains(body, wm.Target) {
|
||||||
log.Warn().Str("target", wm.Target).Msg("ABORT: no mention of target found in html src of source!")
|
log.Warn().Str("target", wm.Target).Msg("ABORT: no mention of target found in html src of source!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data := microformats.Parse(strings.NewReader(body), wm.sourceUrl())
|
data := microformats.Parse(strings.NewReader(body), wm.SourceUrl())
|
||||||
indieweb := recv.convertBodyToIndiewebData(body, wm, getHEntry(data))
|
indieweb := recv.convertBodyToIndiewebData(body, wm, getHEntry(data))
|
||||||
|
|
||||||
recv.saveWebmentionToDisk(wm, indieweb)
|
recv.saveWebmentionToDisk(wm, indieweb)
|
||||||
log.Info().Str("file", wm.asPath(recv.Conf)).Msg("OK: Webmention processed.")
|
log.Info().Str("file", wm.AsPath(recv.Conf)).Msg("OK: Webmention processed.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (recv *Receiver) convertBodyToIndiewebData(body string, wm Mention, hEntry *microformats.Microformat) *indiewebData {
|
func (recv *Receiver) convertBodyToIndiewebData(body string, wm mf.Mention, hEntry *microformats.Microformat) *mf.IndiewebData {
|
||||||
if hEntry == nil {
|
if hEntry == nil {
|
||||||
return recv.parseBodyAsNonIndiewebSite(body, wm)
|
return recv.parseBodyAsNonIndiewebSite(body, wm)
|
||||||
}
|
}
|
||||||
return recv.parseBodyAsIndiewebSite(hEntry, wm)
|
return recv.parseBodyAsIndiewebSite(hEntry, wm)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (recv *Receiver) saveWebmentionToDisk(wm Mention, indieweb *indiewebData) {
|
func (recv *Receiver) saveWebmentionToDisk(wm mf.Mention, indieweb *mf.IndiewebData) {
|
||||||
jsonData, jsonErr := json.Marshal(indieweb)
|
jsonData, jsonErr := json.Marshal(indieweb)
|
||||||
if jsonErr != nil {
|
if jsonErr != nil {
|
||||||
log.Err(jsonErr).Msg("Unable to serialize Webmention into JSON")
|
log.Err(jsonErr).Msg("Unable to serialize Webmention into JSON")
|
||||||
}
|
}
|
||||||
err := ioutil.WriteFile(wm.asPath(recv.Conf), jsonData, fs.ModePerm)
|
err := ioutil.WriteFile(wm.AsPath(recv.Conf), jsonData, fs.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Err(err).Msg("Unable to save Webmention to disk")
|
log.Err(err).Msg("Unable to save Webmention to disk")
|
||||||
}
|
}
|
||||||
|
@ -105,40 +84,40 @@ func (recv *Receiver) saveWebmentionToDisk(wm Mention, indieweb *indiewebData) {
|
||||||
|
|
||||||
// TODO I'm smelling very unstable code, apply https://golang.org/doc/effective_go#recover here?
|
// TODO I'm smelling very unstable code, apply https://golang.org/doc/effective_go#recover here?
|
||||||
// see https://github.com/willnorris/microformats/blob/main/microformats.go
|
// see https://github.com/willnorris/microformats/blob/main/microformats.go
|
||||||
func (recv *Receiver) parseBodyAsIndiewebSite(hEntry *microformats.Microformat, wm Mention) *indiewebData {
|
func (recv *Receiver) parseBodyAsIndiewebSite(hEntry *microformats.Microformat, wm mf.Mention) *mf.IndiewebData {
|
||||||
name := mfStr(hEntry, "name")
|
name := mf.Str(hEntry, "name")
|
||||||
pic := mfStr(mfProp(hEntry, "author"), "photo")
|
pic := mf.Str(mf.Prop(hEntry, "author"), "photo")
|
||||||
mfType := determineMfType(hEntry)
|
mfType := mf.DetermineType(hEntry)
|
||||||
|
|
||||||
return &indiewebData{
|
return &mf.IndiewebData{
|
||||||
Name: name,
|
Name: name,
|
||||||
Author: indiewebAuthor{
|
Author: mf.IndiewebAuthor{
|
||||||
Name: determineAuthorName(hEntry),
|
Name: mf.DetermineAuthorName(hEntry),
|
||||||
Picture: pic,
|
Picture: pic,
|
||||||
},
|
},
|
||||||
Content: determineContent(hEntry),
|
Content: mf.DetermineContent(hEntry),
|
||||||
Url: determineUrl(hEntry, wm.Source),
|
Url: mf.DetermineUrl(hEntry, wm.Source),
|
||||||
Published: determinePublishedDate(hEntry, recv.Conf.UtcOffset),
|
Published: mf.DeterminePublishedDate(hEntry, recv.Conf.UtcOffset),
|
||||||
Source: wm.Source,
|
Source: wm.Source,
|
||||||
Target: wm.Target,
|
Target: wm.Target,
|
||||||
IndiewebType: mfType,
|
IndiewebType: mfType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (recv *Receiver) parseBodyAsNonIndiewebSite(body string, wm Mention) *indiewebData {
|
func (recv *Receiver) parseBodyAsNonIndiewebSite(body string, wm mf.Mention) *mf.IndiewebData {
|
||||||
r := regexp.MustCompile(`<title>(.*?)<\/title>`)
|
r := regexp.MustCompile(`<title>(.*?)<\/title>`)
|
||||||
titleMatch := r.FindStringSubmatch(body)
|
titleMatch := r.FindStringSubmatch(body)
|
||||||
title := wm.Source
|
title := wm.Source
|
||||||
if titleMatch != nil {
|
if titleMatch != nil {
|
||||||
title = titleMatch[1]
|
title = titleMatch[1]
|
||||||
}
|
}
|
||||||
return &indiewebData{
|
return &mf.IndiewebData{
|
||||||
Author: indiewebAuthor{
|
Author: mf.IndiewebAuthor{
|
||||||
Name: wm.Source,
|
Name: wm.Source,
|
||||||
},
|
},
|
||||||
Name: title,
|
Name: title,
|
||||||
Content: title,
|
Content: title,
|
||||||
Published: publishedNow(recv.Conf.UtcOffset),
|
Published: mf.PublishedNow(recv.Conf.UtcOffset),
|
||||||
Url: wm.Source,
|
Url: wm.Source,
|
||||||
IndiewebType: "mention",
|
IndiewebType: "mention",
|
||||||
Source: wm.Source,
|
Source: wm.Source,
|
|
@ -1,9 +1,10 @@
|
||||||
|
|
||||||
package webmention
|
package receive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/wgroeneveld/go-jamming/app/mf"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -22,12 +23,12 @@ var conf = &common.Config{
|
||||||
|
|
||||||
|
|
||||||
func TestConvertWebmentionToPath(t *testing.T) {
|
func TestConvertWebmentionToPath(t *testing.T) {
|
||||||
wm := Mention{
|
wm := mf.Mention{
|
||||||
Source: "https://brainbaking.com",
|
Source: "https://brainbaking.com",
|
||||||
Target: "https://jefklakscodex.com/articles",
|
Target: "https://jefklakscodex.com/articles",
|
||||||
}
|
}
|
||||||
|
|
||||||
result := wm.asPath(conf)
|
result := wm.AsPath(conf)
|
||||||
if result != "testdata/jefklakscodex.com/99be66594fdfcf482545fead8e7e4948.json" {
|
if result != "testdata/jefklakscodex.com/99be66594fdfcf482545fead8e7e4948.json" {
|
||||||
t.Fatalf("md5 hash check failed, got " + result)
|
t.Fatalf("md5 hash check failed, got " + result)
|
||||||
}
|
}
|
||||||
|
@ -42,12 +43,12 @@ func writeSomethingTo(filename string) {
|
||||||
func TestReceive(t *testing.T) {
|
func TestReceive(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
label string
|
label string
|
||||||
wm Mention
|
wm mf.Mention
|
||||||
json string
|
json string
|
||||||
} {
|
} {
|
||||||
{
|
{
|
||||||
label: "receive a Webmention bookmark via twitter",
|
label: "receive a Webmention bookmark via twitter",
|
||||||
wm: Mention{
|
wm: mf.Mention{
|
||||||
Source: "https://brainbaking.com/valid-bridgy-twitter-source.html",
|
Source: "https://brainbaking.com/valid-bridgy-twitter-source.html",
|
||||||
Target: "https://brainbaking.com/post/2021/03/the-indieweb-mixed-bag",
|
Target: "https://brainbaking.com/post/2021/03/the-indieweb-mixed-bag",
|
||||||
},
|
},
|
||||||
|
@ -55,7 +56,7 @@ func TestReceive(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "receive a brid.gy Webmention like",
|
label: "receive a brid.gy Webmention like",
|
||||||
wm: Mention{
|
wm: mf.Mention{
|
||||||
Source: "https://brainbaking.com/valid-bridgy-like.html",
|
Source: "https://brainbaking.com/valid-bridgy-like.html",
|
||||||
// wrapped in a a class="u-like-of" tag
|
// wrapped in a a class="u-like-of" tag
|
||||||
Target: "https://brainbaking.com/valid-indieweb-target.html",
|
Target: "https://brainbaking.com/valid-indieweb-target.html",
|
||||||
|
@ -65,7 +66,7 @@ func TestReceive(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "receive a brid.gy Webmention that has a url and photo without value",
|
label: "receive a brid.gy Webmention that has a url and photo without value",
|
||||||
wm: Mention{
|
wm: mf.Mention{
|
||||||
Source: "https://brainbaking.com/valid-bridgy-source.html",
|
Source: "https://brainbaking.com/valid-bridgy-source.html",
|
||||||
Target: "https://brainbaking.com/valid-indieweb-target.html",
|
Target: "https://brainbaking.com/valid-indieweb-target.html",
|
||||||
},
|
},
|
||||||
|
@ -73,7 +74,7 @@ func TestReceive(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "receive saves a JSON file of indieweb-metadata if all is valid",
|
label: "receive saves a JSON file of indieweb-metadata if all is valid",
|
||||||
wm: Mention{
|
wm: mf.Mention{
|
||||||
Source: "https://brainbaking.com/valid-indieweb-source.html",
|
Source: "https://brainbaking.com/valid-indieweb-source.html",
|
||||||
Target: "https://jefklakscodex.com/articles",
|
Target: "https://jefklakscodex.com/articles",
|
||||||
},
|
},
|
||||||
|
@ -81,7 +82,7 @@ func TestReceive(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "receive saves a JSON file of indieweb-metadata with summary as content if present",
|
label: "receive saves a JSON file of indieweb-metadata with summary as content if present",
|
||||||
wm: Mention{
|
wm: mf.Mention{
|
||||||
Source: "https://brainbaking.com/valid-indieweb-source-with-summary.html",
|
Source: "https://brainbaking.com/valid-indieweb-source-with-summary.html",
|
||||||
Target: "https://brainbaking.com/valid-indieweb-target.html",
|
Target: "https://brainbaking.com/valid-indieweb-target.html",
|
||||||
},
|
},
|
||||||
|
@ -89,7 +90,7 @@ func TestReceive(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "receive saves a JSON file of non-indieweb-data such as title if all is valid",
|
label: "receive saves a JSON file of non-indieweb-data such as title if all is valid",
|
||||||
wm: Mention{
|
wm: mf.Mention{
|
||||||
Source: "https://brainbaking.com/valid-nonindieweb-source.html",
|
Source: "https://brainbaking.com/valid-nonindieweb-source.html",
|
||||||
Target: "https://brainbaking.com/valid-indieweb-target.html",
|
Target: "https://brainbaking.com/valid-indieweb-target.html",
|
||||||
},
|
},
|
||||||
|
@ -102,20 +103,20 @@ func TestReceive(t *testing.T) {
|
||||||
os.MkdirAll("testdata/brainbaking.com", os.ModePerm)
|
os.MkdirAll("testdata/brainbaking.com", os.ModePerm)
|
||||||
os.MkdirAll("testdata/jefklakscodex.com", os.ModePerm)
|
os.MkdirAll("testdata/jefklakscodex.com", os.ModePerm)
|
||||||
defer os.RemoveAll("testdata")
|
defer os.RemoveAll("testdata")
|
||||||
now = func() time.Time {
|
common.Now = func() time.Time {
|
||||||
return time.Date(2020, time.January, 1, 12, 30, 0, 0, time.UTC)
|
return time.Date(2020, time.January, 1, 12, 30, 0, 0, time.UTC)
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver := &Receiver{
|
receiver := &Receiver{
|
||||||
Conf: conf,
|
Conf: conf,
|
||||||
RestClient: &mocks.RestClientMock{
|
RestClient: &mocks.RestClientMock{
|
||||||
GetBodyFunc: mocks.RelPathGetBodyFunc(t),
|
GetBodyFunc: mocks.RelPathGetBodyFunc(t, "../../../mocks/"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver.Receive(tc.wm)
|
receiver.Receive(tc.wm)
|
||||||
|
|
||||||
actualJson, _ := ioutil.ReadFile(tc.wm.asPath(conf))
|
actualJson, _ := ioutil.ReadFile(tc.wm.AsPath(conf))
|
||||||
assert.JSONEq(t, tc.json, string(actualJson))
|
assert.JSONEq(t, tc.json, string(actualJson))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -125,11 +126,11 @@ func TestReceiveTargetDoesNotExistAnymoreDeletesPossiblyOlderWebmention(t *testi
|
||||||
os.MkdirAll("testdata/jefklakscodex.com", os.ModePerm)
|
os.MkdirAll("testdata/jefklakscodex.com", os.ModePerm)
|
||||||
defer os.RemoveAll("testdata")
|
defer os.RemoveAll("testdata")
|
||||||
|
|
||||||
wm := Mention{
|
wm := mf.Mention{
|
||||||
Source: "https://brainbaking.com",
|
Source: "https://brainbaking.com",
|
||||||
Target: "https://jefklakscodex.com/articles",
|
Target: "https://jefklakscodex.com/articles",
|
||||||
}
|
}
|
||||||
filename := wm.asPath(conf)
|
filename := wm.AsPath(conf)
|
||||||
writeSomethingTo(filename)
|
writeSomethingTo(filename)
|
||||||
|
|
||||||
client := &mocks.RestClientMock{
|
client := &mocks.RestClientMock{
|
||||||
|
@ -147,17 +148,17 @@ func TestReceiveTargetDoesNotExistAnymoreDeletesPossiblyOlderWebmention(t *testi
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReceiveTargetThatDoesNotPointToTheSourceDoesNothing(t *testing.T) {
|
func TestReceiveTargetThatDoesNotPointToTheSourceDoesNothing(t *testing.T) {
|
||||||
wm := Mention{
|
wm := mf.Mention{
|
||||||
Source: "https://brainbaking.com/valid-indieweb-source.html",
|
Source: "https://brainbaking.com/valid-indieweb-source.html",
|
||||||
Target: "https://brainbaking.com/valid-indieweb-source.html",
|
Target: "https://brainbaking.com/valid-indieweb-source.html",
|
||||||
}
|
}
|
||||||
filename := wm.asPath(conf)
|
filename := wm.AsPath(conf)
|
||||||
writeSomethingTo(filename)
|
writeSomethingTo(filename)
|
||||||
|
|
||||||
receiver := &Receiver{
|
receiver := &Receiver{
|
||||||
Conf: conf,
|
Conf: conf,
|
||||||
RestClient: &mocks.RestClientMock{
|
RestClient: &mocks.RestClientMock{
|
||||||
GetBodyFunc: mocks.RelPathGetBodyFunc(t),
|
GetBodyFunc: mocks.RelPathGetBodyFunc(t, "../../../mocks/"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +170,7 @@ func TestProcessSourceBodyAbortsIfNoMentionOfTargetFoundInSourceHtml(t *testing.
|
||||||
os.MkdirAll("testdata/jefklakscodex.com", os.ModePerm)
|
os.MkdirAll("testdata/jefklakscodex.com", os.ModePerm)
|
||||||
defer os.RemoveAll("testdata")
|
defer os.RemoveAll("testdata")
|
||||||
|
|
||||||
wm := Mention{
|
wm := mf.Mention{
|
||||||
Source: "https://brainbaking.com",
|
Source: "https://brainbaking.com",
|
||||||
Target: "https://jefklakscodex.com/articles",
|
Target: "https://jefklakscodex.com/articles",
|
||||||
}
|
}
|
||||||
|
@ -178,6 +179,6 @@ func TestProcessSourceBodyAbortsIfNoMentionOfTargetFoundInSourceHtml(t *testing.
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver.processSourceBody("<html>my nice body</html>", wm)
|
receiver.processSourceBody("<html>my nice body</html>", wm)
|
||||||
assert.NoFileExists(t, wm.asPath(conf))
|
assert.NoFileExists(t, wm.AsPath(conf))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package send
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/wgroeneveld/go-jamming/app/mf"
|
||||||
|
"github.com/wgroeneveld/go-jamming/app/pingback/send"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mention() {
|
||||||
|
send.SendPingbackToEndpoint("endpoint", mf.Mention{})
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// I know it's public. Not sure how to handle this in tests, package-independent
|
||||||
|
var Now = time.Now
|
|
@ -22,11 +22,11 @@ func (m *RestClientMock) GetBody(url string) (string, error) {
|
||||||
return m.GetBodyFunc(url)
|
return m.GetBodyFunc(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RelPathGetBodyFunc(t *testing.T) func(string) (string, error) {
|
func RelPathGetBodyFunc(t *testing.T, relPath string) func(string) (string, error) {
|
||||||
return func(url string) (string, error) {
|
return func(url string) (string, error) {
|
||||||
// url: https://brainbaking.com/something-something.html
|
// url: https://brainbaking.com/something-something.html
|
||||||
// want: ../../mocks/something-something.html
|
// want: ../../mocks/something-something.html
|
||||||
mockfile := "../../mocks/" + strings.ReplaceAll(url, "https://brainbaking.com/", "")
|
mockfile := relPath + strings.ReplaceAll(url, "https://brainbaking.com/", "")
|
||||||
html, err := ioutil.ReadFile(mockfile)
|
html, err := ioutil.ReadFile(mockfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
|
Loading…
Reference in New Issue