clean up interface

This commit is contained in:
Niko Abeler 2022-12-05 21:09:23 +01:00
parent cad4897583
commit d783db98a2
10 changed files with 78 additions and 78 deletions

View File

@ -144,7 +144,7 @@ func userWebmentionHandler(repo *owl.Repository) func(http.ResponseWriter, *http
return return
} }
tryAlias := func(target string) owl.IPost { tryAlias := func(target string) owl.Post {
parsedTarget, _ := url.Parse(target) parsedTarget, _ := url.Parse(target)
aliases, _ := repo.PostAliases() aliases, _ := repo.PostAliases()
fmt.Printf("aliases %v", aliases) fmt.Printf("aliases %v", aliases)
@ -155,7 +155,7 @@ func userWebmentionHandler(repo *owl.Repository) func(http.ResponseWriter, *http
return nil return nil
} }
var aliasPost owl.IPost var aliasPost owl.Post
parts := strings.Split(target[0], "/") parts := strings.Split(target[0], "/")
if len(parts) < 2 { if len(parts) < 2 {
aliasPost = tryAlias(target[0]) aliasPost = tryAlias(target[0])

View File

@ -46,7 +46,7 @@ var webmentionCmd = &cobra.Command{
} }
} }
processPost := func(user owl.User, post owl.IPost) error { processPost := func(user owl.User, post owl.Post) error {
println("Webmentions for post: ", post.Title()) println("Webmentions for post: ", post.Title())
err := post.ScanForLinks() err := post.ScanForLinks()

80
post.go
View File

@ -17,7 +17,7 @@ import (
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
type Post struct { type GenericPost struct {
user *User user *User
id string id string
metaLoaded bool metaLoaded bool
@ -25,29 +25,33 @@ type Post struct {
wmLock sync.Mutex wmLock sync.Mutex
} }
func (post *Post) TemplateDir() string { func (post *GenericPost) TemplateDir() string {
return "article" return "article"
} }
type IPost interface { type Post interface {
TemplateDir() string TemplateDir() string
Id() string // Actual Data
User() *User User() *User
Dir() string Id() string
IncomingWebmentionsFile() string
OutgoingWebmentionsFile() string
MediaDir() string
UrlPath() string
FullUrl() string
UrlMediaPath(filename string) string
Title() string Title() string
ContentFile() string
Meta() PostMeta Meta() PostMeta
Content() []byte Content() []byte
RenderedContent() string RenderedContent() string
Aliases() []string Aliases() []string
LoadMeta() error
// Filesystem
Dir() string
MediaDir() string
ContentFile() string
// Urls
UrlPath() string
FullUrl() string
UrlMediaPath(filename string) string
// Webmentions Support
IncomingWebmentions() []WebmentionIn IncomingWebmentions() []WebmentionIn
OutgoingWebmentions() []WebmentionOut OutgoingWebmentions() []WebmentionOut
PersistIncomingWebmention(webmention WebmentionIn) error PersistIncomingWebmention(webmention WebmentionIn) error
@ -151,64 +155,64 @@ type PostWebmetions struct {
Outgoing []WebmentionOut `ymal:"outgoing"` Outgoing []WebmentionOut `ymal:"outgoing"`
} }
func (post *Post) Id() string { func (post *GenericPost) Id() string {
return post.id return post.id
} }
func (post *Post) User() *User { func (post *GenericPost) User() *User {
return post.user return post.user
} }
func (post *Post) Dir() string { func (post *GenericPost) Dir() string {
return path.Join(post.user.Dir(), "public", post.id) return path.Join(post.user.Dir(), "public", post.id)
} }
func (post *Post) IncomingWebmentionsFile() string { func (post *GenericPost) IncomingWebmentionsFile() string {
return path.Join(post.Dir(), "incoming_webmentions.yml") return path.Join(post.Dir(), "incoming_webmentions.yml")
} }
func (post *Post) OutgoingWebmentionsFile() string { func (post *GenericPost) OutgoingWebmentionsFile() string {
return path.Join(post.Dir(), "outgoing_webmentions.yml") return path.Join(post.Dir(), "outgoing_webmentions.yml")
} }
func (post *Post) MediaDir() string { func (post *GenericPost) MediaDir() string {
return path.Join(post.Dir(), "media") return path.Join(post.Dir(), "media")
} }
func (post *Post) UrlPath() string { func (post *GenericPost) UrlPath() string {
return post.user.UrlPath() + "posts/" + post.id + "/" return post.user.UrlPath() + "posts/" + post.id + "/"
} }
func (post *Post) FullUrl() string { func (post *GenericPost) FullUrl() string {
return post.user.FullUrl() + "posts/" + post.id + "/" return post.user.FullUrl() + "posts/" + post.id + "/"
} }
func (post *Post) UrlMediaPath(filename string) string { func (post *GenericPost) UrlMediaPath(filename string) string {
return post.UrlPath() + "media/" + filename return post.UrlPath() + "media/" + filename
} }
func (post *Post) Title() string { func (post *GenericPost) Title() string {
return post.Meta().Title return post.Meta().Title
} }
func (post *Post) ContentFile() string { func (post *GenericPost) ContentFile() string {
return path.Join(post.Dir(), "index.md") return path.Join(post.Dir(), "index.md")
} }
func (post *Post) Meta() PostMeta { func (post *GenericPost) Meta() PostMeta {
if !post.metaLoaded { if !post.metaLoaded {
post.LoadMeta() post.LoadMeta()
} }
return post.meta return post.meta
} }
func (post *Post) Content() []byte { func (post *GenericPost) Content() []byte {
// read file // read file
data, _ := os.ReadFile(post.ContentFile()) data, _ := os.ReadFile(post.ContentFile())
return data return data
} }
func (post *Post) RenderedContent() string { func (post *GenericPost) RenderedContent() string {
data := post.Content() data := post.Content()
// trim yaml block // trim yaml block
@ -250,11 +254,11 @@ func (post *Post) RenderedContent() string {
} }
func (post *Post) Aliases() []string { func (post *GenericPost) Aliases() []string {
return post.Meta().Aliases return post.Meta().Aliases
} }
func (post *Post) LoadMeta() error { func (post *GenericPost) LoadMeta() error {
data := post.Content() data := post.Content()
// get yaml metadata block // get yaml metadata block
@ -280,7 +284,7 @@ func (post *Post) LoadMeta() error {
return nil return nil
} }
func (post *Post) IncomingWebmentions() []WebmentionIn { func (post *GenericPost) IncomingWebmentions() []WebmentionIn {
// return parsed webmentions // return parsed webmentions
fileName := post.IncomingWebmentionsFile() fileName := post.IncomingWebmentionsFile()
if !fileExists(fileName) { if !fileExists(fileName) {
@ -293,7 +297,7 @@ func (post *Post) IncomingWebmentions() []WebmentionIn {
return webmentions return webmentions
} }
func (post *Post) OutgoingWebmentions() []WebmentionOut { func (post *GenericPost) OutgoingWebmentions() []WebmentionOut {
// return parsed webmentions // return parsed webmentions
fileName := post.OutgoingWebmentionsFile() fileName := post.OutgoingWebmentionsFile()
if !fileExists(fileName) { if !fileExists(fileName) {
@ -307,7 +311,7 @@ func (post *Post) OutgoingWebmentions() []WebmentionOut {
} }
// PersistWebmentionOutgoing persists incoming webmention // PersistWebmentionOutgoing persists incoming webmention
func (post *Post) PersistIncomingWebmention(webmention WebmentionIn) error { func (post *GenericPost) PersistIncomingWebmention(webmention WebmentionIn) error {
post.wmLock.Lock() post.wmLock.Lock()
defer post.wmLock.Unlock() defer post.wmLock.Unlock()
@ -336,7 +340,7 @@ func (post *Post) PersistIncomingWebmention(webmention WebmentionIn) error {
} }
// PersistOutgoingWebmention persists a webmention to the webmention file. // PersistOutgoingWebmention persists a webmention to the webmention file.
func (post *Post) PersistOutgoingWebmention(webmention *WebmentionOut) error { func (post *GenericPost) PersistOutgoingWebmention(webmention *WebmentionOut) error {
post.wmLock.Lock() post.wmLock.Lock()
defer post.wmLock.Unlock() defer post.wmLock.Unlock()
@ -364,7 +368,7 @@ func (post *Post) PersistOutgoingWebmention(webmention *WebmentionOut) error {
return nil return nil
} }
func (post *Post) AddIncomingWebmention(source string) error { func (post *GenericPost) AddIncomingWebmention(source string) error {
// Check if file already exists // Check if file already exists
wm := WebmentionIn{ wm := WebmentionIn{
Source: source, Source: source,
@ -376,7 +380,7 @@ func (post *Post) AddIncomingWebmention(source string) error {
return post.PersistIncomingWebmention(wm) return post.PersistIncomingWebmention(wm)
} }
func (post *Post) EnrichWebmention(webmention WebmentionIn) error { func (post *GenericPost) EnrichWebmention(webmention WebmentionIn) error {
resp, err := post.user.repo.HttpClient.Get(webmention.Source) resp, err := post.user.repo.HttpClient.Get(webmention.Source)
if err == nil { if err == nil {
entry, err := post.user.repo.Parser.ParseHEntry(resp) entry, err := post.user.repo.Parser.ParseHEntry(resp)
@ -388,7 +392,7 @@ func (post *Post) EnrichWebmention(webmention WebmentionIn) error {
return err return err
} }
func (post *Post) ApprovedIncomingWebmentions() []WebmentionIn { func (post *GenericPost) ApprovedIncomingWebmentions() []WebmentionIn {
webmentions := post.IncomingWebmentions() webmentions := post.IncomingWebmentions()
approved := []WebmentionIn{} approved := []WebmentionIn{}
for _, webmention := range webmentions { for _, webmention := range webmentions {
@ -406,7 +410,7 @@ func (post *Post) ApprovedIncomingWebmentions() []WebmentionIn {
// ScanForLinks scans the post content for links and adds them to the // ScanForLinks scans the post content for links and adds them to the
// `status.yml` file for the post. The links are not scanned by this function. // `status.yml` file for the post. The links are not scanned by this function.
func (post *Post) ScanForLinks() error { func (post *GenericPost) ScanForLinks() error {
// this could be done in markdown parsing, but I don't want to // this could be done in markdown parsing, but I don't want to
// rely on goldmark for this (yet) // rely on goldmark for this (yet)
postHtml := post.RenderedContent() postHtml := post.RenderedContent()
@ -423,7 +427,7 @@ func (post *Post) ScanForLinks() error {
return nil return nil
} }
func (post *Post) SendWebmention(webmention WebmentionOut) error { func (post *GenericPost) SendWebmention(webmention WebmentionOut) error {
defer post.PersistOutgoingWebmention(&webmention) defer post.PersistOutgoingWebmention(&webmention)
// if last scan is less than 7 days ago, don't send webmention // if last scan is less than 7 days ago, don't send webmention

View File

@ -98,7 +98,7 @@ func TestRawHTMLIfAllowedByRepo(t *testing.T) {
assertions.AssertContains(t, html, "<script>") assertions.AssertContains(t, html, "<script>")
} }
func TestLoadMeta(t *testing.T) { func TestMeta(t *testing.T) {
repo := getTestRepo(owl.RepoConfig{AllowRawHtml: true}) repo := getTestRepo(owl.RepoConfig{AllowRawHtml: true})
user, _ := repo.CreateUser("testuser") user, _ := repo.CreateUser("testuser")
post, _ := user.CreateNewPost(owl.PostMeta{Type: "article", Title: "testpost"}, "") post, _ := user.CreateNewPost(owl.PostMeta{Type: "article", Title: "testpost"}, "")
@ -114,10 +114,6 @@ func TestLoadMeta(t *testing.T) {
content += "<script>alert('foo')</script>\n" content += "<script>alert('foo')</script>\n"
os.WriteFile(post.ContentFile(), []byte(content), 0644) os.WriteFile(post.ContentFile(), []byte(content), 0644)
err := post.LoadMeta()
assertions.AssertNoError(t, err, "Error loading meta")
assertions.AssertEqual(t, post.Meta().Title, "test") assertions.AssertEqual(t, post.Meta().Title, "test")
assertions.AssertLen(t, post.Meta().Aliases, 1) assertions.AssertLen(t, post.Meta().Aliases, 1)
assertions.AssertEqual(t, post.Meta().Draft, true) assertions.AssertEqual(t, post.Meta().Draft, true)

View File

@ -1,7 +1,7 @@
package owl package owl
type Note struct { type Note struct {
Post GenericPost
} }
func (n *Note) TemplateDir() string { func (n *Note) TemplateDir() string {
@ -9,7 +9,7 @@ func (n *Note) TemplateDir() string {
} }
type Article struct { type Article struct {
Post GenericPost
} }
func (a *Article) TemplateDir() string { func (a *Article) TemplateDir() string {
@ -17,7 +17,7 @@ func (a *Article) TemplateDir() string {
} }
type Page struct { type Page struct {
Post GenericPost
} }
func (p *Page) TemplateDir() string { func (p *Page) TemplateDir() string {
@ -25,7 +25,7 @@ func (p *Page) TemplateDir() string {
} }
type Bookmark struct { type Bookmark struct {
Post GenericPost
} }
func (b *Bookmark) TemplateDir() string { func (b *Bookmark) TemplateDir() string {
@ -33,7 +33,7 @@ func (b *Bookmark) TemplateDir() string {
} }
type Reply struct { type Reply struct {
Post GenericPost
} }
func (r *Reply) TemplateDir() string { func (r *Reply) TemplateDir() string {

View File

@ -18,7 +18,7 @@ type PageContent struct {
type PostRenderData struct { type PostRenderData struct {
Title string Title string
Post IPost Post Post
Content template.HTML Content template.HTML
} }
@ -119,7 +119,7 @@ func renderIntoBaseTemplate(user User, data PageContent) (string, error) {
return html.String(), err return html.String(), err
} }
func renderPostContent(post IPost) (string, error) { func renderPostContent(post Post) (string, error) {
buf := post.RenderedContent() buf := post.RenderedContent()
postHtml, err := renderEmbedTemplate( postHtml, err := renderEmbedTemplate(
fmt.Sprintf("embed/%s/detail.html", post.TemplateDir()), fmt.Sprintf("embed/%s/detail.html", post.TemplateDir()),
@ -132,7 +132,7 @@ func renderPostContent(post IPost) (string, error) {
return postHtml, err return postHtml, err
} }
func RenderPost(post IPost) (string, error) { func RenderPost(post Post) (string, error) {
postHtml, err := renderPostContent(post) postHtml, err := renderPostContent(post)
if err != nil { if err != nil {
return "", err return "", err

View File

@ -158,12 +158,12 @@ func (repo Repository) GetUser(name string) (User, error) {
return user, nil return user, nil
} }
func (repo Repository) PostAliases() (map[string]IPost, error) { func (repo Repository) PostAliases() (map[string]Post, error) {
users, err := repo.Users() users, err := repo.Users()
if err != nil { if err != nil {
return nil, err return nil, err
} }
aliases := make(map[string]IPost) aliases := make(map[string]Post)
for _, user := range users { for _, user := range users {
user_aliases, err := user.PostAliases() user_aliases, err := user.PostAliases()
if err != nil { if err != nil {

View File

@ -213,7 +213,7 @@ func TestCanGetMapWithAllPostAliases(t *testing.T) {
posts, _ := user.PublishedPosts() posts, _ := user.PublishedPosts()
assertions.AssertLen(t, posts, 1) assertions.AssertLen(t, posts, 1)
var aliases map[string]owl.IPost var aliases map[string]owl.Post
aliases, err := repo.PostAliases() aliases, err := repo.PostAliases()
assertions.AssertNoError(t, err, "Error getting post aliases: ") assertions.AssertNoError(t, err, "Error getting post aliases: ")
assertions.AssertMapLen(t, aliases, 2) assertions.AssertMapLen(t, aliases, 2)
@ -247,7 +247,7 @@ func TestAliasesHaveCorrectPost(t *testing.T) {
posts, _ := user.PublishedPosts() posts, _ := user.PublishedPosts()
assertions.AssertLen(t, posts, 2) assertions.AssertLen(t, posts, 2)
var aliases map[string]owl.IPost var aliases map[string]owl.Post
aliases, err := repo.PostAliases() aliases, err := repo.PostAliases()
assertions.AssertNoError(t, err, "Error getting post aliases: ") assertions.AssertNoError(t, err, "Error getting post aliases: ")
assertions.AssertMapLen(t, aliases, 2) assertions.AssertMapLen(t, aliases, 2)

38
user.go
View File

@ -197,9 +197,9 @@ func (user User) FaviconUrl() string {
return "" return ""
} }
func (user User) AllPosts() ([]IPost, error) { func (user User) AllPosts() ([]Post, error) {
postFiles := listDir(path.Join(user.Dir(), "public")) postFiles := listDir(path.Join(user.Dir(), "public"))
posts := make([]IPost, 0) posts := make([]Post, 0)
for _, id := range postFiles { for _, id := range postFiles {
// if is a directory and has index.md, add to posts // if is a directory and has index.md, add to posts
if dirExists(path.Join(user.Dir(), "public", id)) { if dirExists(path.Join(user.Dir(), "public", id)) {
@ -211,7 +211,7 @@ func (user User) AllPosts() ([]IPost, error) {
} }
type PostWithDate struct { type PostWithDate struct {
post IPost post Post
date time.Time date time.Time
} }
@ -233,7 +233,7 @@ func (user User) AllPosts() ([]IPost, error) {
return posts, nil return posts, nil
} }
func (user User) PublishedPosts() ([]IPost, error) { func (user User) PublishedPosts() ([]Post, error) {
posts, _ := user.AllPosts() posts, _ := user.AllPosts()
// remove drafts // remove drafts
@ -249,7 +249,7 @@ func (user User) PublishedPosts() ([]IPost, error) {
return posts, nil return posts, nil
} }
func (user User) PrimaryFeedPosts() ([]IPost, error) { func (user User) PrimaryFeedPosts() ([]Post, error) {
config := user.Config() config := user.Config()
include := config.PrimaryListInclude include := config.PrimaryListInclude
if len(include) == 0 { if len(include) == 0 {
@ -262,7 +262,7 @@ func (user User) PrimaryFeedPosts() ([]IPost, error) {
}) })
} }
func (user User) GetPostsOfList(list PostList) ([]IPost, error) { func (user User) GetPostsOfList(list PostList) ([]Post, error) {
posts, _ := user.PublishedPosts() posts, _ := user.PublishedPosts()
// remove posts not included // remove posts not included
@ -278,29 +278,29 @@ func (user User) GetPostsOfList(list PostList) ([]IPost, error) {
return posts, nil return posts, nil
} }
func (user User) GetPost(id string) (IPost, error) { func (user User) GetPost(id string) (Post, error) {
// check if posts index.md exists // check if posts index.md exists
if !fileExists(path.Join(user.Dir(), "public", id, "index.md")) { if !fileExists(path.Join(user.Dir(), "public", id, "index.md")) {
return &Post{}, fmt.Errorf("post %s does not exist", id) return &GenericPost{}, fmt.Errorf("post %s does not exist", id)
} }
post := Post{user: &user, id: id} post := GenericPost{user: &user, id: id}
switch post.Meta().Type { switch post.Meta().Type {
case "article": case "article":
return &Article{Post: post}, nil return &Article{GenericPost: post}, nil
case "note": case "note":
return &Note{Post: post}, nil return &Note{GenericPost: post}, nil
case "reply": case "reply":
return &Reply{Post: post}, nil return &Reply{GenericPost: post}, nil
case "bookmark": case "bookmark":
return &Bookmark{Post: post}, nil return &Bookmark{GenericPost: post}, nil
case "page": case "page":
return &Page{Post: post}, nil return &Page{GenericPost: post}, nil
} }
return &post, nil return &post, nil
} }
func (user User) CreateNewPost(meta PostMeta, content string) (IPost, error) { func (user User) CreateNewPost(meta PostMeta, content string) (Post, error) {
slugHint := meta.Title slugHint := meta.Title
if slugHint == "" { if slugHint == "" {
slugHint = "note" slugHint = "note"
@ -319,7 +319,7 @@ func (user User) CreateNewPost(meta PostMeta, content string) (IPost, error) {
break break
} }
} }
post := Post{user: &user, id: folder_name} post := GenericPost{user: &user, id: folder_name}
// if date is not set, set it to now // if date is not set, set it to now
if meta.Date.IsZero() { if meta.Date.IsZero() {
@ -331,7 +331,7 @@ func (user User) CreateNewPost(meta PostMeta, content string) (IPost, error) {
// write meta // write meta
meta_bytes, err := yaml.Marshal(meta) meta_bytes, err := yaml.Marshal(meta)
if err != nil { if err != nil {
return &Post{}, err return &GenericPost{}, err
} }
initial_content += string(meta_bytes) initial_content += string(meta_bytes)
initial_content += "---\n" initial_content += "---\n"
@ -366,8 +366,8 @@ func (user User) SetConfig(new_config UserConfig) error {
return saveToYaml(user.ConfigFile(), new_config) return saveToYaml(user.ConfigFile(), new_config)
} }
func (user User) PostAliases() (map[string]IPost, error) { func (user User) PostAliases() (map[string]Post, error) {
post_aliases := make(map[string]IPost) post_aliases := make(map[string]Post)
posts, err := user.PublishedPosts() posts, err := user.PublishedPosts()
if err != nil { if err != nil {
return post_aliases, err return post_aliases, err

View File

@ -225,7 +225,7 @@ func TestPostsSortedByPublishingDateLatestFirst(t *testing.T) {
func TestPostsSortedByPublishingDateLatestFirst2(t *testing.T) { func TestPostsSortedByPublishingDateLatestFirst2(t *testing.T) {
user := getTestUser() user := getTestUser()
// Create a new post // Create a new post
posts := []owl.IPost{} posts := []owl.Post{}
for i := 59; i >= 0; i-- { for i := 59; i >= 0; i-- {
post, _ := user.CreateNewPost(owl.PostMeta{Type: "article", Title: "testpost"}, "") post, _ := user.CreateNewPost(owl.PostMeta{Type: "article", Title: "testpost"}, "")
content := "---\n" content := "---\n"