From 3bd168de0024873e4ab06aa3ae2e49700b67541e Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Sat, 27 Aug 2022 23:01:14 +0200 Subject: [PATCH] missing files --- webmention.go | 83 ++++++++++++++++++++++++++++++++++++++++++++++ webmention_test.go | 36 ++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 webmention.go create mode 100644 webmention_test.go diff --git a/webmention.go b/webmention.go new file mode 100644 index 0000000..53dee9a --- /dev/null +++ b/webmention.go @@ -0,0 +1,83 @@ +package owl + +import ( + "bytes" + "errors" + "net/http" + "strings" + + "golang.org/x/net/html" +) + +type HttpRetriever interface { + Get(url string) ([]byte, error) +} + +type OwlHttpRetriever struct{} + +type ParsedHEntry struct { + Title string +} + +func (ret *OwlHttpRetriever) Get(url string) ([]byte, error) { + resp, err := http.Get(url) + if err != nil { + return []byte{}, err + } + var data []byte + _, err = resp.Body.Read(data) + // TODO: encoding + return data, err +} + +func collectText(n *html.Node, buf *bytes.Buffer) { + if n.Type == html.TextNode { + buf.WriteString(n.Data) + } + for c := n.FirstChild; c != nil; c = c.NextSibling { + collectText(c, buf) + } +} + +func ParseHEntry(data []byte) (ParsedHEntry, error) { + doc, err := html.Parse(strings.NewReader(string(data))) + if err != nil { + return ParsedHEntry{}, err + } + + var interpretHFeed func(*html.Node, *ParsedHEntry, bool) (ParsedHEntry, error) + interpretHFeed = func(n *html.Node, curr *ParsedHEntry, parent bool) (ParsedHEntry, error) { + attrs := n.Attr + for _, attr := range attrs { + if attr.Key == "class" && strings.Contains(attr.Val, "p-name") { + buf := &bytes.Buffer{} + collectText(n, buf) + curr.Title = buf.String() + return *curr, nil + } + } + + for c := n.FirstChild; c != nil; c = c.NextSibling { + interpretHFeed(c, curr, false) + } + return *curr, nil + } + + var findHFeed func(*html.Node) (ParsedHEntry, error) + findHFeed = func(n *html.Node) (ParsedHEntry, error) { + attrs := n.Attr + for _, attr := range attrs { + if attr.Key == "class" && strings.Contains(attr.Val, "h-entry") { + return interpretHFeed(n, &ParsedHEntry{}, true) + } + } + for c := n.FirstChild; c != nil; c = c.NextSibling { + entry, err := findHFeed(c) + if err == nil { + return entry, nil + } + } + return ParsedHEntry{}, errors.New("no h-entry found") + } + return findHFeed(doc) +} diff --git a/webmention_test.go b/webmention_test.go new file mode 100644 index 0000000..c9abf6c --- /dev/null +++ b/webmention_test.go @@ -0,0 +1,36 @@ +package owl_test + +import ( + "h4kor/owl-blogs" + "testing" +) + +// +// https://www.w3.org/TR/webmention/#h-webmention-verification +// + +func TestParseValidHEntry(t *testing.T) { + html := []byte("
Foo
") + + entry, err := owl.ParseHEntry(html) + + if err != nil { + t.Errorf("Unable to parse feed: %v", err) + } + if entry.Title != "Foo" { + t.Errorf("Wrong Title. Expected %v, got %v", "Foo", entry.Title) + } +} + +func TestParseValidHEntryWithoutTitle(t *testing.T) { + html := []byte("
Foo
") + + entry, err := owl.ParseHEntry(html) + + if err != nil { + t.Errorf("Unable to parse feed: %v", err) + } + if entry.Title != "" { + t.Errorf("Wrong Title. Expected %v, got %v", "Foo", entry.Title) + } +}