try to parse source of webmention as HEntry

This commit is contained in:
Niko Abeler 2022-08-31 20:01:58 +02:00
parent 3bd168de00
commit 01593c0a36
9 changed files with 89 additions and 36 deletions

View File

@ -6,6 +6,18 @@ import (
"time" "time"
) )
type MockMicroformatParser struct{}
func (*MockMicroformatParser) ParseHEntry(data []byte) (owl.ParsedHEntry, error) {
return owl.ParsedHEntry{Title: "Mock Title"}, nil
}
type MockHttpRetriever struct{}
func (*MockHttpRetriever) Get(url string) ([]byte, error) {
return []byte(""), nil
}
func randomName() string { func randomName() string {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
var letters = []rune("abcdefghijklmnopqrstuvwxyz") var letters = []rune("abcdefghijklmnopqrstuvwxyz")

10
post.go
View File

@ -150,12 +150,20 @@ func (post *Post) LoadMeta() error {
func (post *Post) AddWebmention(source string) error { func (post *Post) AddWebmention(source string) error {
hash := sha256.Sum256([]byte(source)) hash := sha256.Sum256([]byte(source))
hashStr := base64.URLEncoding.EncodeToString(hash[:]) hashStr := base64.URLEncoding.EncodeToString(hash[:])
data := "source: " + source
// Check if file already exists // Check if file already exists
fileName := path.Join(post.WebmentionDir(), hashStr+".yml") fileName := path.Join(post.WebmentionDir(), hashStr+".yml")
if fileExists(fileName) { if fileExists(fileName) {
return nil 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 os.WriteFile(fileName, []byte(data), 0644)
} }

View File

@ -169,7 +169,8 @@ func TestLoadMeta(t *testing.T) {
func TestAddWebmentionCreatesFile(t *testing.T) { func TestAddWebmentionCreatesFile(t *testing.T) {
repo := getTestRepo() repo := getTestRepo()
repo.SetAllowRawHtml(true) repo.Retriever = &MockHttpRetriever{}
repo.Parser = &MockMicroformatParser{}
user, _ := repo.CreateUser("testuser") user, _ := repo.CreateUser("testuser")
post, _ := user.CreateNewPost("testpost") post, _ := user.CreateNewPost("testpost")
@ -185,7 +186,8 @@ func TestAddWebmentionCreatesFile(t *testing.T) {
func TestAddWebmentionNotOverwritingFile(t *testing.T) { func TestAddWebmentionNotOverwritingFile(t *testing.T) {
repo := getTestRepo() repo := getTestRepo()
repo.SetAllowRawHtml(true) repo.Retriever = &MockHttpRetriever{}
repo.Parser = &MockMicroformatParser{}
user, _ := repo.CreateUser("testuser") user, _ := repo.CreateUser("testuser")
post, _ := user.CreateNewPost("testpost") post, _ := user.CreateNewPost("testpost")
@ -211,3 +213,26 @@ func TestAddWebmentionNotOverwritingFile(t *testing.T) {
t.Errorf("Expected: %v", content) t.Errorf("Expected: %v", content)
} }
} }
func TestAddWebmentionAddsParsedTitle(t *testing.T) {
repo := getTestRepo()
repo.Retriever = &MockHttpRetriever{}
repo.Parser = &MockMicroformatParser{}
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)
if len(files) != 1 {
t.Error("No file created for webmention")
}
fileContent, _ := os.ReadFile(path.Join(post.WebmentionDir(), files[0]))
if !strings.Contains(string(fileContent), "Mock Title") {
t.Error("File not containing the title.")
t.Errorf("Got: %v", string(fileContent))
}
}

View File

@ -1,2 +1,2 @@
docker build . -t git.libove.org/h4kor/owl-blogs docker build . -t git.libove.org/h4kor/owl-blogs:$1
docker push git.libove.org/h4kor/owl-blogs docker push git.libove.org/h4kor/owl-blogs

View File

@ -20,6 +20,8 @@ type Repository struct {
single_user_mode bool single_user_mode bool
active_user string active_user string
allow_raw_html bool allow_raw_html bool
Retriever HttpRetriever
Parser MicroformatParser
} }
type RepoConfig struct { type RepoConfig struct {
@ -27,7 +29,7 @@ type RepoConfig struct {
} }
func CreateRepository(name string) (Repository, error) { func CreateRepository(name string) (Repository, error) {
newRepo := Repository{name: name} newRepo := Repository{name: name, Parser: OwlMicroformatParser{}, Retriever: OwlHttpRetriever{}}
// check if repository already exists // check if repository already exists
if dirExists(newRepo.Dir()) { if dirExists(newRepo.Dir()) {
return Repository{}, fmt.Errorf("Repository already exists") return Repository{}, fmt.Errorf("Repository already exists")
@ -61,7 +63,7 @@ func CreateRepository(name string) (Repository, error) {
func OpenRepository(name string) (Repository, error) { func OpenRepository(name string) (Repository, error) {
repo := Repository{name: name} repo := Repository{name: name, Parser: OwlMicroformatParser{}, Retriever: OwlHttpRetriever{}}
if !dirExists(repo.Dir()) { if !dirExists(repo.Dir()) {
return Repository{}, fmt.Errorf("Repository does not exist: " + repo.Dir()) return Repository{}, fmt.Errorf("Repository does not exist: " + repo.Dir())
} }

View File

@ -27,7 +27,7 @@ func TestCannotCreateExistingRepository(t *testing.T) {
func TestCanCreateANewUser(t *testing.T) { func TestCanCreateANewUser(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
if _, err := os.Stat(path.Join(user.Dir(), "")); err != nil { if _, err := os.Stat(path.Join(user.Dir(), "")); err != nil {
t.Error("User directory not created") t.Error("User directory not created")
@ -36,7 +36,7 @@ func TestCanCreateANewUser(t *testing.T) {
func TestCannotRecreateExisitingUser(t *testing.T) { func TestCannotRecreateExisitingUser(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
userName := randomUserName() userName := randomUserName()
repo.CreateUser(userName) repo.CreateUser(userName)
_, err := repo.CreateUser(userName) _, err := repo.CreateUser(userName)
@ -47,7 +47,7 @@ func TestCannotRecreateExisitingUser(t *testing.T) {
func TestCreateUserAddsVersionFile(t *testing.T) { func TestCreateUserAddsVersionFile(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
if _, err := os.Stat(path.Join(user.Dir(), "/meta/VERSION")); err != nil { if _, err := os.Stat(path.Join(user.Dir(), "/meta/VERSION")); err != nil {
t.Error("Version file not created") t.Error("Version file not created")
@ -56,7 +56,7 @@ func TestCreateUserAddsVersionFile(t *testing.T) {
func TestCreateUserAddsBaseHtmlFile(t *testing.T) { func TestCreateUserAddsBaseHtmlFile(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
if _, err := os.Stat(path.Join(user.Dir(), "/meta/base.html")); err != nil { if _, err := os.Stat(path.Join(user.Dir(), "/meta/base.html")); err != nil {
t.Error("Base html file not created") t.Error("Base html file not created")
@ -65,7 +65,7 @@ func TestCreateUserAddsBaseHtmlFile(t *testing.T) {
func TestCreateUserAddConfigYml(t *testing.T) { func TestCreateUserAddConfigYml(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
if _, err := os.Stat(path.Join(user.Dir(), "/meta/config.yml")); err != nil { if _, err := os.Stat(path.Join(user.Dir(), "/meta/config.yml")); err != nil {
t.Error("Config file not created") t.Error("Config file not created")
@ -74,7 +74,7 @@ func TestCreateUserAddConfigYml(t *testing.T) {
func TestCreateUserAddsPublicFolder(t *testing.T) { func TestCreateUserAddsPublicFolder(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
if _, err := os.Stat(path.Join(user.Dir(), "/public")); err != nil { if _, err := os.Stat(path.Join(user.Dir(), "/public")); err != nil {
t.Error("Public folder not created") t.Error("Public folder not created")
@ -83,7 +83,7 @@ func TestCreateUserAddsPublicFolder(t *testing.T) {
func TestCanListRepoUsers(t *testing.T) { func TestCanListRepoUsers(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user1, _ := repo.CreateUser(randomUserName()) user1, _ := repo.CreateUser(randomUserName())
user2, _ := repo.CreateUser(randomUserName()) user2, _ := repo.CreateUser(randomUserName())
// Create a new post // Create a new post
@ -121,7 +121,7 @@ func TestCannotOpenNonExisitingRepo(t *testing.T) {
func TestGetUser(t *testing.T) { func TestGetUser(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
// Get the user // Get the user
user2, err := repo.GetUser(user.Name()) user2, err := repo.GetUser(user.Name())
@ -135,7 +135,7 @@ func TestGetUser(t *testing.T) {
func TestCannotGetNonexistingUser(t *testing.T) { func TestCannotGetNonexistingUser(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
_, err := repo.GetUser(randomUserName()) _, err := repo.GetUser(randomUserName())
if err == nil { if err == nil {
t.Error("No error returned when getting non-existing user") t.Error("No error returned when getting non-existing user")
@ -144,7 +144,7 @@ func TestCannotGetNonexistingUser(t *testing.T) {
func TestGetStaticDirOfRepo(t *testing.T) { func TestGetStaticDirOfRepo(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
// Get the user // Get the user
staticDir := repo.StaticDir() staticDir := repo.StaticDir()
if staticDir == "" { if staticDir == "" {
@ -154,7 +154,7 @@ func TestGetStaticDirOfRepo(t *testing.T) {
func TestNewRepoGetsStaticFiles(t *testing.T) { func TestNewRepoGetsStaticFiles(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
if _, err := os.Stat(repo.StaticDir()); err != nil { if _, err := os.Stat(repo.StaticDir()); err != nil {
t.Error("Static directory not found") t.Error("Static directory not found")
} }
@ -169,7 +169,7 @@ func TestNewRepoGetsStaticFiles(t *testing.T) {
func TestNewRepoGetsStaticFilesPicoCSSWithContent(t *testing.T) { func TestNewRepoGetsStaticFilesPicoCSSWithContent(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
file, err := os.Open(path.Join(repo.StaticDir(), "pico.min.css")) file, err := os.Open(path.Join(repo.StaticDir(), "pico.min.css"))
if err != nil { if err != nil {
t.Error("Error opening pico.min.css") t.Error("Error opening pico.min.css")
@ -183,7 +183,7 @@ func TestNewRepoGetsStaticFilesPicoCSSWithContent(t *testing.T) {
func TestNewRepoGetsBaseHtml(t *testing.T) { func TestNewRepoGetsBaseHtml(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
if _, err := os.Stat(path.Join(repo.Dir(), "/base.html")); err != nil { if _, err := os.Stat(path.Join(repo.Dir(), "/base.html")); err != nil {
t.Error("Base html file not found") t.Error("Base html file not found")
} }
@ -191,7 +191,7 @@ func TestNewRepoGetsBaseHtml(t *testing.T) {
func TestCanGetRepoTemplate(t *testing.T) { func TestCanGetRepoTemplate(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
// Get the user // Get the user
template, err := repo.Template() template, err := repo.Template()
if err != nil { if err != nil {
@ -239,7 +239,7 @@ func TestSingleUserRepoUserUrlPathIsSimple(t *testing.T) {
} }
func TestCanGetMapWithAllPostAliases(t *testing.T) { func TestCanGetMapWithAllPostAliases(t *testing.T) {
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
post, _ := user.CreateNewPost("test-1") post, _ := user.CreateNewPost("test-1")
@ -276,7 +276,7 @@ func TestCanGetMapWithAllPostAliases(t *testing.T) {
} }
func TestAliasesHaveCorrectPost(t *testing.T) { func TestAliasesHaveCorrectPost(t *testing.T) {
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
post1, _ := user.CreateNewPost("test-1") post1, _ := user.CreateNewPost("test-1")
post2, _ := user.CreateNewPost("test-2") post2, _ := user.CreateNewPost("test-2")

View File

@ -11,7 +11,7 @@ import (
func TestCreateNewPostCreatesEntryInPublic(t *testing.T) { func TestCreateNewPostCreatesEntryInPublic(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
// Create a new post // Create a new post
user.CreateNewPost("testpost") user.CreateNewPost("testpost")
@ -26,7 +26,7 @@ func TestCreateNewPostCreatesEntryInPublic(t *testing.T) {
func TestCreateNewPostCreatesMediaDir(t *testing.T) { func TestCreateNewPostCreatesMediaDir(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
// Create a new post // Create a new post
post, _ := user.CreateNewPost("testpost") post, _ := user.CreateNewPost("testpost")
@ -49,7 +49,7 @@ func TestCreateNewPostAddsDateToMetaBlock(t *testing.T) {
func TestCreateNewPostMultipleCalls(t *testing.T) { func TestCreateNewPostMultipleCalls(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
// Create a new post // Create a new post
user.CreateNewPost("testpost") user.CreateNewPost("testpost")
@ -66,7 +66,7 @@ func TestCreateNewPostMultipleCalls(t *testing.T) {
func TestCanListUserPosts(t *testing.T) { func TestCanListUserPosts(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
// Create a new post // Create a new post
user.CreateNewPost("testpost") user.CreateNewPost("testpost")
@ -83,7 +83,7 @@ func TestCanListUserPosts(t *testing.T) {
func TestCannotListUserPostsInSubdirectories(t *testing.T) { func TestCannotListUserPostsInSubdirectories(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
// Create a new post // Create a new post
user.CreateNewPost("testpost") user.CreateNewPost("testpost")
@ -120,7 +120,7 @@ func TestCannotListUserPostsInSubdirectories(t *testing.T) {
func TestCannotListUserPostsWithoutIndexMd(t *testing.T) { func TestCannotListUserPostsWithoutIndexMd(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
// Create a new post // Create a new post
user.CreateNewPost("testpost") user.CreateNewPost("testpost")
@ -149,7 +149,7 @@ func TestCannotListUserPostsWithoutIndexMd(t *testing.T) {
func TestListUserPostsDoesNotIncludeDrafts(t *testing.T) { func TestListUserPostsDoesNotIncludeDrafts(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
// Create a new post // Create a new post
post, _ := user.CreateNewPost("testpost") post, _ := user.CreateNewPost("testpost")
@ -170,7 +170,7 @@ func TestListUserPostsDoesNotIncludeDrafts(t *testing.T) {
func TestListUsersDraftsExcludedRealWorld(t *testing.T) { func TestListUsersDraftsExcludedRealWorld(t *testing.T) {
// Create a new user // Create a new user
repo, _ := owl.CreateRepository(testRepoName()) repo := getTestRepo()
user, _ := repo.CreateUser(randomUserName()) user, _ := repo.CreateUser(randomUserName())
// Create a new post // Create a new post
post, _ := user.CreateNewPost("testpost") post, _ := user.CreateNewPost("testpost")

View File

@ -13,13 +13,19 @@ type HttpRetriever interface {
Get(url string) ([]byte, error) Get(url string) ([]byte, error)
} }
type MicroformatParser interface {
ParseHEntry(data []byte) (ParsedHEntry, error)
}
type OwlHttpRetriever struct{} type OwlHttpRetriever struct{}
type OwlMicroformatParser struct{}
type ParsedHEntry struct { type ParsedHEntry struct {
Title string Title string
} }
func (ret *OwlHttpRetriever) Get(url string) ([]byte, error) { func (OwlHttpRetriever) Get(url string) ([]byte, error) {
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
return []byte{}, err return []byte{}, err
@ -39,7 +45,7 @@ func collectText(n *html.Node, buf *bytes.Buffer) {
} }
} }
func ParseHEntry(data []byte) (ParsedHEntry, error) { func (OwlMicroformatParser) ParseHEntry(data []byte) (ParsedHEntry, error) {
doc, err := html.Parse(strings.NewReader(string(data))) doc, err := html.Parse(strings.NewReader(string(data)))
if err != nil { if err != nil {
return ParsedHEntry{}, err return ParsedHEntry{}, err

View File

@ -11,8 +11,8 @@ import (
func TestParseValidHEntry(t *testing.T) { func TestParseValidHEntry(t *testing.T) {
html := []byte("<div class=\"h-entry\"><div class=\"p-name\">Foo</div></div>") html := []byte("<div class=\"h-entry\"><div class=\"p-name\">Foo</div></div>")
parser := &owl.OwlMicroformatParser{}
entry, err := owl.ParseHEntry(html) entry, err := parser.ParseHEntry(html)
if err != nil { if err != nil {
t.Errorf("Unable to parse feed: %v", err) t.Errorf("Unable to parse feed: %v", err)
@ -24,8 +24,8 @@ func TestParseValidHEntry(t *testing.T) {
func TestParseValidHEntryWithoutTitle(t *testing.T) { func TestParseValidHEntryWithoutTitle(t *testing.T) {
html := []byte("<div class=\"h-entry\"></div><div class=\"p-name\">Foo</div>") html := []byte("<div class=\"h-entry\"></div><div class=\"p-name\">Foo</div>")
parser := &owl.OwlMicroformatParser{}
entry, err := owl.ParseHEntry(html) entry, err := parser.ParseHEntry(html)
if err != nil { if err != nil {
t.Errorf("Unable to parse feed: %v", err) t.Errorf("Unable to parse feed: %v", err)