refactoring webmention persistence

This commit is contained in:
Niko Abeler 2022-09-01 21:34:33 +02:00
parent a5250eb01c
commit 73ec606b95
3 changed files with 121 additions and 26 deletions

106
post.go
View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"encoding/base64" "encoding/base64"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
@ -147,32 +148,97 @@ func (post *Post) LoadMeta() error {
return nil return nil
} }
func (post *Post) AddWebmention(source string) error { func (post *Post) WebmentionFile(source string) string {
// ensure dir exists
os.MkdirAll(post.WebmentionDir(), 0755)
hash := sha256.Sum256([]byte(source)) hash := sha256.Sum256([]byte(source))
hashStr := base64.URLEncoding.EncodeToString(hash[:]) hashStr := base64.URLEncoding.EncodeToString(hash[:])
// Check if file already exists return path.Join(post.WebmentionDir(), hashStr+".yml")
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)
} }
func (post *Post) Webmentions() []string { func (post *Post) PersistWebmention(webmention Webmention) error {
// ensure dir exists // ensure dir exists
os.MkdirAll(post.WebmentionDir(), 0755) 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
} }

View File

@ -1,6 +1,7 @@
package owl_test package owl_test
import ( import (
"h4kor/owl-blogs"
"os" "os"
"path" "path"
"strings" "strings"
@ -167,6 +168,27 @@ func TestLoadMeta(t *testing.T) {
/// Webmention /// 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) { func TestAddWebmentionCreatesFile(t *testing.T) {
repo := getTestRepo() repo := getTestRepo()
repo.Retriever = &MockHttpRetriever{} repo.Retriever = &MockHttpRetriever{}
@ -174,13 +196,14 @@ func TestAddWebmentionCreatesFile(t *testing.T) {
user, _ := repo.CreateUser("testuser") user, _ := repo.CreateUser("testuser")
post, _ := user.CreateNewPost("testpost") post, _ := user.CreateNewPost("testpost")
post.AddWebmention("https://example.com") err := post.AddWebmention("https://example.com")
dir, _ := os.Open(post.WebmentionDir()) if err != nil {
defer dir.Close() t.Errorf("Got Error: %v", err)
files, _ := dir.Readdirnames(-1) }
if len(files) != 1 { mentions := post.Webmentions()
t.Error("No file created for webmention") if len(mentions) != 1 {
t.Errorf("Expected 1 webmention, got %d", len(mentions))
} }
} }

View File

@ -9,6 +9,12 @@ import (
"golang.org/x/net/html" "golang.org/x/net/html"
) )
type Webmention struct {
Source string `yaml:"source"`
Title string `yaml:"title"`
Approved bool `yaml:"approved"`
}
type HttpRetriever interface { type HttpRetriever interface {
Get(url string) ([]byte, error) Get(url string) ([]byte, error)
} }