From 73ec606b951915cadc8b7ee594b0af40c919c216 Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Thu, 1 Sep 2022 21:34:33 +0200 Subject: [PATCH] refactoring webmention persistence --- post.go | 106 ++++++++++++++++++++++++++++++++++++++++---------- post_test.go | 35 ++++++++++++++--- webmention.go | 6 +++ 3 files changed, 121 insertions(+), 26 deletions(-) diff --git a/post.go b/post.go index 5bf4d9f..b42fdcc 100644 --- a/post.go +++ b/post.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/sha256" "encoding/base64" + "fmt" "io/ioutil" "os" "path" @@ -147,32 +148,97 @@ func (post *Post) LoadMeta() error { return nil } -func (post *Post) AddWebmention(source string) error { - // ensure dir exists - os.MkdirAll(post.WebmentionDir(), 0755) +func (post *Post) WebmentionFile(source string) string { hash := sha256.Sum256([]byte(source)) hashStr := base64.URLEncoding.EncodeToString(hash[:]) - // Check if file already exists - fileName := path.Join(post.WebmentionDir(), hashStr+".yml") - if fileExists(fileName) { - return nil - } - data := "source: " + source + "\n" - html, err := post.user.repo.Retriever.Get(source) - if err == nil { - entry, err := post.user.repo.Parser.ParseHEntry(html) - if err == nil { - data += "title: " + entry.Title + "\n" - } - } - - return os.WriteFile(fileName, []byte(data), 0644) + return path.Join(post.WebmentionDir(), hashStr+".yml") } -func (post *Post) Webmentions() []string { +func (post *Post) PersistWebmention(webmention Webmention) error { // ensure dir exists os.MkdirAll(post.WebmentionDir(), 0755) - return listDir(post.WebmentionDir()) + // write to file + fileName := post.WebmentionFile(webmention.Source) + data, err := yaml.Marshal(webmention) + if err != nil { + return err + } + return os.WriteFile(fileName, data, 0644) +} + +func (post *Post) Webmention(source string) (Webmention, error) { + // ensure dir exists + os.MkdirAll(post.WebmentionDir(), 0755) + + // Check if file exists + fileName := post.WebmentionFile(source) + if !fileExists(fileName) { + // return error if file doesn't exist + return Webmention{}, fmt.Errorf("Webmention file not found: %s", source) + } + + data, err := os.ReadFile(fileName) + if err != nil { + return Webmention{}, err + } + + mention := Webmention{} + err = yaml.Unmarshal(data, &mention) + if err != nil { + return Webmention{}, err + } + + return mention, nil +} + +func (post *Post) AddWebmention(source string) error { + // Check if file already exists + _, err := post.Webmention(source) + if err != nil { + webmention := Webmention{ + Source: source, + } + defer post.EnrichWebmention(source) + return post.PersistWebmention(webmention) + } + return nil +} + +func (post *Post) EnrichWebmention(source string) error { + html, err := post.user.repo.Retriever.Get(source) + if err == nil { + webmention, err := post.Webmention(source) + if err != nil { + return err + } + entry, err := post.user.repo.Parser.ParseHEntry(html) + if err == nil { + webmention.Title = entry.Title + return post.PersistWebmention(webmention) + } + } + return err +} + +func (post *Post) Webmentions() []Webmention { + // ensure dir exists + os.MkdirAll(post.WebmentionDir(), 0755) + files := listDir(post.WebmentionDir()) + webmentions := []Webmention{} + for _, file := range files { + data, err := os.ReadFile(path.Join(post.WebmentionDir(), file)) + if err != nil { + continue + } + mention := Webmention{} + err = yaml.Unmarshal(data, &mention) + if err != nil { + continue + } + webmentions = append(webmentions, mention) + } + + return webmentions } diff --git a/post_test.go b/post_test.go index 26b5a32..62e0f86 100644 --- a/post_test.go +++ b/post_test.go @@ -1,6 +1,7 @@ package owl_test import ( + "h4kor/owl-blogs" "os" "path" "strings" @@ -167,6 +168,27 @@ func TestLoadMeta(t *testing.T) { /// Webmention /// +func TestPersistWebmention(t *testing.T) { + repo := getTestRepo() + user, _ := repo.CreateUser("testuser") + post, _ := user.CreateNewPost("testpost") + webmention := owl.Webmention{ + Source: "http://example.com/source", + } + err := post.PersistWebmention(webmention) + if err != nil { + t.Errorf("Got error: %v", err) + } + mentions := post.Webmentions() + if len(mentions) != 1 { + t.Errorf("Expected 1 webmention, got %d", len(mentions)) + } + + if mentions[0].Source != webmention.Source { + t.Errorf("Expected source: %s, got %s", webmention.Source, mentions[0].Source) + } +} + func TestAddWebmentionCreatesFile(t *testing.T) { repo := getTestRepo() repo.Retriever = &MockHttpRetriever{} @@ -174,13 +196,14 @@ func TestAddWebmentionCreatesFile(t *testing.T) { user, _ := repo.CreateUser("testuser") post, _ := user.CreateNewPost("testpost") - post.AddWebmention("https://example.com") - dir, _ := os.Open(post.WebmentionDir()) - defer dir.Close() - files, _ := dir.Readdirnames(-1) + err := post.AddWebmention("https://example.com") + if err != nil { + t.Errorf("Got Error: %v", err) + } - if len(files) != 1 { - t.Error("No file created for webmention") + mentions := post.Webmentions() + if len(mentions) != 1 { + t.Errorf("Expected 1 webmention, got %d", len(mentions)) } } diff --git a/webmention.go b/webmention.go index 780fa20..ba9ff82 100644 --- a/webmention.go +++ b/webmention.go @@ -9,6 +9,12 @@ import ( "golang.org/x/net/html" ) +type Webmention struct { + Source string `yaml:"source"` + Title string `yaml:"title"` + Approved bool `yaml:"approved"` +} + type HttpRetriever interface { Get(url string) ([]byte, error) }