diff --git a/activitystreams.go b/activitystreams.go index 173c6f1..23c31f2 100644 --- a/activitystreams.go +++ b/activitystreams.go @@ -39,13 +39,11 @@ type asAttachment struct { URL string `json:"url"` } -// TODO: Serve index - func servePostActivityStreams(w http.ResponseWriter, r *http.Request) { // Remove ".as" from path again r.URL.Path = strings.TrimSuffix(r.URL.Path, ".as") // Fetch post from db - post, err := getPost(r.Context(), slashTrimmedPath(r)) + p, err := getPost(r.Context(), slashTrimmedPath(r)) if err == errPostNotFound { serve404(w, r) return @@ -58,26 +56,26 @@ func servePostActivityStreams(w http.ResponseWriter, r *http.Request) { Context: []string{"https://www.w3.org/ns/activitystreams"}, To: []string{"https://www.w3.org/ns/activitystreams#Public"}, MediaType: "text/html", - ID: appConfig.Server.PublicAddress + post.Path, - URL: appConfig.Server.PublicAddress + post.Path, + ID: appConfig.Server.PublicAddress + p.Path, + URL: appConfig.Server.PublicAddress + p.Path, AttributedTo: appConfig.Server.PublicAddress, } // Name and Type - if title := post.title(); title != "" { + if title := p.title(); title != "" { as.Name = title as.Type = "Article" } else { as.Type = "Note" } // Content - if rendered, err := renderMarkdown(post.Content); err == nil { + if rendered, err := renderMarkdown(p.Content); err == nil { as.Content = string(rendered) } else { http.Error(w, err.Error(), http.StatusInternalServerError) return } // Attachments - if images := post.Parameters[appConfig.Blogs[post.Blog].ActivityStreams.ImagesParameter]; len(images) > 0 { + if images := p.Parameters[appConfig.Blogs[p.Blog].ActivityStreams.ImagesParameter]; len(images) > 0 { for _, image := range images { as.Attachment = append(as.Attachment, &asAttachment{ Type: "Image", @@ -87,21 +85,45 @@ func servePostActivityStreams(w http.ResponseWriter, r *http.Request) { } // Dates dateFormat := "2006-01-02T15:04:05-07:00" - if post.Published != "" { - if t, err := dateparse.ParseIn(post.Published, time.Local); err == nil { + if p.Published != "" { + if t, err := dateparse.ParseIn(p.Published, time.Local); err == nil { as.Published = t.Format(dateFormat) } } - if post.Updated != "" { - if t, err := dateparse.ParseIn(post.Updated, time.Local); err == nil { + if p.Updated != "" { + if t, err := dateparse.ParseIn(p.Updated, time.Local); err == nil { as.Published = t.Format(dateFormat) } } // Reply - if replyLink := post.firstParameter(appConfig.Blogs[post.Blog].ActivityStreams.ReplyParameter); replyLink != "" { + if replyLink := p.firstParameter(appConfig.Blogs[p.Blog].ActivityStreams.ReplyParameter); replyLink != "" { as.InReplyTo = replyLink } // Send JSON w.Header().Add(contentType, contentTypeJSONUTF8) _ = json.NewEncoder(w).Encode(as) } + +type asPerson struct { + Context []string `json:"@context"` + ID string `json:"id"` + Type string `json:"type"` + Name string `json:"name"` + Summary string `json:"summary"` + Attachment []struct { + Type string `json:"type"` + Name string `json:"name"` + Value string `json:"value"` + } `json:"attachment"` + PreferredUsername string `json:"preferredUsername"` + Icon struct { + Type string `json:"type"` + URL string `json:"url"` + } `json:"icon"` + Inbox string `json:"inbox"` + PublicKey struct { + ID string `json:"id"` + Owner string `json:"owner"` + PublicKeyPem string `json:"publicKeyPem"` + } `json:"publicKey"` +} diff --git a/api.go b/api.go index 7b834f6..76af347 100644 --- a/api.go +++ b/api.go @@ -20,17 +20,17 @@ func apiPostCreateHugo(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusBadRequest) return } - post, aliases, err := parseHugoFile(string(bodyContent)) + p, aliases, err := parseHugoFile(string(bodyContent)) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - post.Blog = blog - post.Path = path - post.Section = section - post.Slug = slug + p.Blog = blog + p.Path = path + p.Section = section + p.Slug = slug aliases = append(aliases, alias) - err = post.replace() + err = p.replace() if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -38,13 +38,13 @@ func apiPostCreateHugo(w http.ResponseWriter, r *http.Request) { for _, alias := range aliases { // Fix relativ paths if !strings.HasPrefix(alias, "/") { - splittedPostPath := strings.Split(post.Path, "/") - alias = strings.TrimSuffix(post.Path, splittedPostPath[len(splittedPostPath)-1]) + alias + splittedPostPath := strings.Split(p.Path, "/") + alias = strings.TrimSuffix(p.Path, splittedPostPath[len(splittedPostPath)-1]) + alias } if alias != "" { - _ = createOrReplaceRedirect(alias, post.Path) + _ = createOrReplaceRedirect(alias, p.Path) } } - w.Header().Set("Location", appConfig.Server.PublicAddress+post.Path) + w.Header().Set("Location", appConfig.Server.PublicAddress+p.Path) w.WriteHeader(http.StatusCreated) } diff --git a/feeds.go b/feeds.go index 28ef134..15fc06d 100644 --- a/feeds.go +++ b/feeds.go @@ -17,7 +17,7 @@ const ( jsonFeed feedType = "json" ) -func generateFeed(blog string, f feedType, w http.ResponseWriter, r *http.Request, posts []*Post, title string, description string) { +func generateFeed(blog string, f feedType, w http.ResponseWriter, r *http.Request, posts []*post, title string, description string) { now := time.Now() if title == "" { title = appConfig.Blogs[blog].Title @@ -31,13 +31,13 @@ func generateFeed(blog string, f feedType, w http.ResponseWriter, r *http.Reques Link: &feeds.Link{Href: appConfig.Server.PublicAddress + strings.TrimSuffix(r.URL.Path, "."+string(f))}, Created: now, } - for _, postItem := range posts { - htmlContent, _ := renderMarkdown(postItem.Content) + for _, p := range posts { + htmlContent, _ := renderMarkdown(p.Content) feed.Add(&feeds.Item{ - Title: postItem.title(), - Link: &feeds.Link{Href: appConfig.Server.PublicAddress + postItem.Path}, - Description: postItem.summary(), - Id: postItem.Path, + Title: p.title(), + Link: &feeds.Link{Href: appConfig.Server.PublicAddress + p.Path}, + Description: p.summary(), + Id: p.Path, Content: string(htmlContent), }) } diff --git a/hugo.go b/hugo.go index e7fd953..ff7a01e 100644 --- a/hugo.go +++ b/hugo.go @@ -9,13 +9,13 @@ import ( "gopkg.in/yaml.v3" ) -func parseHugoFile(fileContent string) (post *Post, aliases []string, e error) { +func parseHugoFile(fileContent string) (p *post, aliases []string, e error) { frontmatterSep := "---\n" frontmatter := "" if split := strings.Split(fileContent, frontmatterSep); len(split) > 2 { frontmatter = split[1] } - post = &Post{ + p = &post{ Content: strings.TrimPrefix(fileContent, frontmatterSep+frontmatter+frontmatterSep), Parameters: map[string][]string{}, } @@ -30,8 +30,8 @@ func parseHugoFile(fileContent string) (post *Post, aliases []string, e error) { return nil, nil, err } // Read dates - post.Published = cast.ToString(flat["date"]) - post.Updated = cast.ToString(flat["lastmod"]) + p.Published = cast.ToString(flat["date"]) + p.Updated = cast.ToString(flat["lastmod"]) // Read parameters for _, fm := range appConfig.Hugo.Frontmatter { var values []string @@ -49,7 +49,7 @@ func parseHugoFile(fileContent string) (post *Post, aliases []string, e error) { } } if len(values) > 0 { - post.Parameters[fm.Parameter] = values + p.Parameters[fm.Parameter] = values } } // Parse redirects @@ -67,5 +67,5 @@ func parseHugoFile(fileContent string) (post *Post, aliases []string, e error) { } } // Return post - return post, aliases, nil + return p, aliases, nil } diff --git a/micropub.go b/micropub.go index af9a1ac..24a8df5 100644 --- a/micropub.go +++ b/micropub.go @@ -38,12 +38,12 @@ func serveMicropubQuery(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusBadRequest) return } - post, err := getPost(r.Context(), u.Path) + p, err := getPost(r.Context(), u.Path) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } - mf = post.toMfItem() + mf = p.toMfItem() } else { posts, err := getPosts(r.Context(), &postsRequestConfig{}) if err != nil { @@ -51,8 +51,8 @@ func serveMicropubQuery(w http.ResponseWriter, r *http.Request) { return } list := map[string][]*microformatItem{} - for _, post := range posts { - list["items"] = append(list["items"], post.toMfItem()) + for _, p := range posts { + list["items"] = append(list["items"], p.toMfItem()) } mf = list } @@ -64,29 +64,29 @@ func serveMicropubQuery(w http.ResponseWriter, r *http.Request) { } } -func (post *Post) toMfItem() *microformatItem { - params := post.Parameters - params["path"] = []string{post.Path} - params["section"] = []string{post.Section} - params["blog"] = []string{post.Blog} - pb, _ := yaml.Marshal(post.Parameters) - content := fmt.Sprintf("---\n%s---\n%s", string(pb), post.Content) +func (p *post) toMfItem() *microformatItem { + params := p.Parameters + params["path"] = []string{p.Path} + params["section"] = []string{p.Section} + params["blog"] = []string{p.Blog} + pb, _ := yaml.Marshal(p.Parameters) + content := fmt.Sprintf("---\n%s---\n%s", string(pb), p.Content) return µformatItem{ Type: []string{"h-entry"}, Properties: µformatProperties{ - Name: post.Parameters["title"], - Published: []string{post.Published}, - Updated: []string{post.Updated}, + Name: p.Parameters["title"], + Published: []string{p.Published}, + Updated: []string{p.Updated}, Content: []string{content}, - MpSlug: []string{post.Slug}, - Category: post.Parameters[appConfig.Micropub.CategoryParam], + MpSlug: []string{p.Slug}, + Category: p.Parameters[appConfig.Micropub.CategoryParam], }, } } func serveMicropubPost(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() - var post *Post + var p *post if ct := r.Header.Get(contentType); strings.Contains(ct, contentTypeWWWForm) || strings.Contains(ct, contentTypeMultipartForm) { var err error r.ParseForm() @@ -109,7 +109,7 @@ func serveMicropubPost(w http.ResponseWriter, r *http.Request) { http.Error(w, "Action not supported", http.StatusNotImplemented) return } - post, err = convertMPValueMapToPost(r.Form) + p, err = convertMPValueMapToPost(r.Form) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -137,7 +137,7 @@ func serveMicropubPost(w http.ResponseWriter, r *http.Request) { http.Error(w, "Action not supported", http.StatusNotImplemented) return } - post, err = convertMPMfToPost(parsedMfItem) + p, err = convertMPMfToPost(parsedMfItem) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -149,21 +149,21 @@ func serveMicropubPost(w http.ResponseWriter, r *http.Request) { if !strings.Contains(r.Context().Value("scope").(string), "create") { http.Error(w, "create scope missing", http.StatusForbidden) } - err := post.create() + err := p.create() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - w.Header().Add("Location", appConfig.Server.PublicAddress+post.Path) + w.Header().Add("Location", appConfig.Server.PublicAddress+p.Path) w.WriteHeader(http.StatusAccepted) return } -func convertMPValueMapToPost(values map[string][]string) (*Post, error) { +func convertMPValueMapToPost(values map[string][]string) (*post, error) { if h, ok := values["h"]; ok && (len(h) != 1 || h[0] != "entry") { return nil, errors.New("only entry type is supported so far") } - entry := &Post{ + entry := &post{ Parameters: map[string][]string{}, } if content, ok := values["content"]; ok { @@ -250,11 +250,11 @@ type microformatProperties struct { Audio []string `json:"audio,omitempty"` } -func convertMPMfToPost(mf *microformatItem) (*Post, error) { +func convertMPMfToPost(mf *microformatItem) (*post, error) { if len(mf.Type) != 1 || mf.Type[0] != "h-entry" { return nil, errors.New("only entry type is supported so far") } - entry := &Post{} + entry := &post{} // Content if mf.Properties != nil && len(mf.Properties.Content) == 1 && len(mf.Properties.Content[0]) > 0 { entry.Content = mf.Properties.Content[0] @@ -306,9 +306,9 @@ func convertMPMfToPost(mf *microformatItem) (*Post, error) { } -func (post *Post) computeExtraPostParameters() error { - post.Content = regexp.MustCompile("\r\n").ReplaceAllString(post.Content, "\n") - if split := strings.Split(post.Content, "---\n"); len(split) >= 3 && len(strings.TrimSpace(split[0])) == 0 { +func (p *post) computeExtraPostParameters() error { + p.Content = regexp.MustCompile("\r\n").ReplaceAllString(p.Content, "\n") + if split := strings.Split(p.Content, "---\n"); len(split) >= 3 && len(strings.TrimSpace(split[0])) == 0 { // Contains frontmatter fm := split[1] meta := map[string]interface{}{} @@ -319,55 +319,55 @@ func (post *Post) computeExtraPostParameters() error { // Find section and copy frontmatter to params for key, value := range meta { // Delete existing content - replace - post.Parameters[key] = []string{} + p.Parameters[key] = []string{} if a, ok := value.([]interface{}); ok { for _, ae := range a { - post.Parameters[key] = append(post.Parameters[key], cast.ToString(ae)) + p.Parameters[key] = append(p.Parameters[key], cast.ToString(ae)) } } else { - post.Parameters[key] = append(post.Parameters[key], cast.ToString(value)) + p.Parameters[key] = append(p.Parameters[key], cast.ToString(value)) } } // Remove frontmatter from content - post.Content = strings.Join(split[2:], "---\n") + p.Content = strings.Join(split[2:], "---\n") } // Check settings - if blog := post.Parameters["blog"]; len(blog) == 1 && blog[0] != "" { - post.Blog = blog[0] - delete(post.Parameters, "blog") + if blog := p.Parameters["blog"]; len(blog) == 1 && blog[0] != "" { + p.Blog = blog[0] + delete(p.Parameters, "blog") } else { - post.Blog = appConfig.DefaultBlog + p.Blog = appConfig.DefaultBlog } - if path := post.Parameters["path"]; len(path) == 1 && path[0] != "" { - post.Path = path[0] - delete(post.Parameters, "path") + if path := p.Parameters["path"]; len(path) == 1 && path[0] != "" { + p.Path = path[0] + delete(p.Parameters, "path") } - if section := post.Parameters["section"]; len(section) == 1 && section[0] != "" { - post.Section = section[0] - delete(post.Parameters, "section") + if section := p.Parameters["section"]; len(section) == 1 && section[0] != "" { + p.Section = section[0] + delete(p.Parameters, "section") } - if slug := post.Parameters["slug"]; len(slug) == 1 && slug[0] != "" { - post.Slug = slug[0] - delete(post.Parameters, "slug") + if slug := p.Parameters["slug"]; len(slug) == 1 && slug[0] != "" { + p.Slug = slug[0] + delete(p.Parameters, "slug") } - if post.Path == "" && post.Section == "" { + if p.Path == "" && p.Section == "" { // Has no path or section -> default section - post.Section = appConfig.Blogs[post.Blog].DefaultSection + p.Section = appConfig.Blogs[p.Blog].DefaultSection } - if post.Published == "" && post.Section != "" { + if p.Published == "" && p.Section != "" { // Has no published date, but section -> published now - post.Published = time.Now().String() + p.Published = time.Now().String() } // Add images not in content - images := post.Parameters[appConfig.Micropub.PhotoParam] - imageAlts := post.Parameters[appConfig.Micropub.PhotoDescriptionParam] + images := p.Parameters[appConfig.Micropub.PhotoParam] + imageAlts := p.Parameters[appConfig.Micropub.PhotoDescriptionParam] useAlts := len(images) == len(imageAlts) for i, image := range images { - if !strings.Contains(post.Content, image) { + if !strings.Contains(p.Content, image) { if useAlts && len(imageAlts[i]) > 0 { - post.Content += "\n\n![" + imageAlts[i] + "](" + image + " \"" + imageAlts[i] + "\")" + p.Content += "\n\n![" + imageAlts[i] + "](" + image + " \"" + imageAlts[i] + "\")" } else { - post.Content += "\n\n![](" + image + ")" + p.Content += "\n\n![](" + image + ")" } } } @@ -391,7 +391,7 @@ func micropubUpdate(w http.ResponseWriter, r *http.Request, u *url.URL, mf *micr if !strings.Contains(r.Context().Value("scope").(string), "update") { http.Error(w, "update scope missing", http.StatusForbidden) } - post, err := getPost(r.Context(), u.Path) + p, err := getPost(r.Context(), u.Path) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -400,23 +400,23 @@ func micropubUpdate(w http.ResponseWriter, r *http.Request, u *url.URL, mf *micr for key, value := range mf.Replace { switch key { case "content": - post.Content = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) + p.Content = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) case "published": - post.Published = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) + p.Published = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) case "updated": - post.Updated = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) + p.Updated = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) case "name": - post.Parameters["title"] = cast.ToStringSlice(value) + p.Parameters["title"] = cast.ToStringSlice(value) case "category": - post.Parameters[appConfig.Micropub.CategoryParam] = cast.ToStringSlice(value) + p.Parameters[appConfig.Micropub.CategoryParam] = cast.ToStringSlice(value) case "in-reply-to": - post.Parameters[appConfig.Micropub.ReplyParam] = cast.ToStringSlice(value) + p.Parameters[appConfig.Micropub.ReplyParam] = cast.ToStringSlice(value) case "like-of": - post.Parameters[appConfig.Micropub.LikeParam] = cast.ToStringSlice(value) + p.Parameters[appConfig.Micropub.LikeParam] = cast.ToStringSlice(value) case "bookmark-of": - post.Parameters[appConfig.Micropub.BookmarkParam] = cast.ToStringSlice(value) + p.Parameters[appConfig.Micropub.BookmarkParam] = cast.ToStringSlice(value) case "audio": - post.Parameters[appConfig.Micropub.AudioParam] = cast.ToStringSlice(value) + p.Parameters[appConfig.Micropub.AudioParam] = cast.ToStringSlice(value) // TODO: photo } } @@ -425,29 +425,29 @@ func micropubUpdate(w http.ResponseWriter, r *http.Request, u *url.URL, mf *micr for key, value := range mf.Add { switch key { case "content": - post.Content += strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) + p.Content += strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) case "published": - post.Published = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) + p.Published = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) case "updated": - post.Updated = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) + p.Updated = strings.TrimSpace(strings.Join(cast.ToStringSlice(value), " ")) case "category": - category := post.Parameters[appConfig.Micropub.CategoryParam] + category := p.Parameters[appConfig.Micropub.CategoryParam] if category == nil { category = []string{} } - post.Parameters[appConfig.Micropub.CategoryParam] = append(category, cast.ToStringSlice(value)...) + p.Parameters[appConfig.Micropub.CategoryParam] = append(category, cast.ToStringSlice(value)...) case "in-reply-to": - post.Parameters[appConfig.Micropub.ReplyParam] = cast.ToStringSlice(value) + p.Parameters[appConfig.Micropub.ReplyParam] = cast.ToStringSlice(value) case "like-of": - post.Parameters[appConfig.Micropub.LikeParam] = cast.ToStringSlice(value) + p.Parameters[appConfig.Micropub.LikeParam] = cast.ToStringSlice(value) case "bookmark-of": - post.Parameters[appConfig.Micropub.BookmarkParam] = cast.ToStringSlice(value) + p.Parameters[appConfig.Micropub.BookmarkParam] = cast.ToStringSlice(value) case "audio": - audio := post.Parameters[appConfig.Micropub.CategoryParam] + audio := p.Parameters[appConfig.Micropub.CategoryParam] if audio == nil { audio = []string{} } - post.Parameters[appConfig.Micropub.AudioParam] = append(audio, cast.ToStringSlice(value)...) + p.Parameters[appConfig.Micropub.AudioParam] = append(audio, cast.ToStringSlice(value)...) // TODO: photo } } @@ -459,24 +459,24 @@ func micropubUpdate(w http.ResponseWriter, r *http.Request, u *url.URL, mf *micr for _, key := range toDelete { switch key { case "content": - post.Content = "" + p.Content = "" case "published": - post.Published = "" + p.Published = "" case "updated": - post.Updated = "" + p.Updated = "" case "category": - delete(post.Parameters, appConfig.Micropub.CategoryParam) + delete(p.Parameters, appConfig.Micropub.CategoryParam) case "in-reply-to": - delete(post.Parameters, appConfig.Micropub.ReplyParam) + delete(p.Parameters, appConfig.Micropub.ReplyParam) case "like-of": - delete(post.Parameters, appConfig.Micropub.LikeParam) + delete(p.Parameters, appConfig.Micropub.LikeParam) case "bookmark-of": - delete(post.Parameters, appConfig.Micropub.BookmarkParam) + delete(p.Parameters, appConfig.Micropub.BookmarkParam) case "audio": - delete(post.Parameters, appConfig.Micropub.AudioParam) + delete(p.Parameters, appConfig.Micropub.AudioParam) case "photo": - delete(post.Parameters, appConfig.Micropub.PhotoParam) - delete(post.Parameters, appConfig.Micropub.PhotoDescriptionParam) + delete(p.Parameters, appConfig.Micropub.PhotoParam) + delete(p.Parameters, appConfig.Micropub.PhotoDescriptionParam) } } } @@ -487,17 +487,17 @@ func micropubUpdate(w http.ResponseWriter, r *http.Request, u *url.URL, mf *micr if ok { switch key { case "content": - post.Content = "" + p.Content = "" case "published": - post.Published = "" + p.Published = "" case "updated": - post.Updated = "" + p.Updated = "" case "in-reply-to": - delete(post.Parameters, appConfig.Micropub.ReplyParam) + delete(p.Parameters, appConfig.Micropub.ReplyParam) case "like-of": - delete(post.Parameters, appConfig.Micropub.LikeParam) + delete(p.Parameters, appConfig.Micropub.LikeParam) case "bookmark-of": - delete(post.Parameters, appConfig.Micropub.BookmarkParam) + delete(p.Parameters, appConfig.Micropub.BookmarkParam) // Use content to edit other parameters } } @@ -505,12 +505,12 @@ func micropubUpdate(w http.ResponseWriter, r *http.Request, u *url.URL, mf *micr } } } - err = post.computeExtraPostParameters() + err = p.computeExtraPostParameters() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } - err = post.replace() + err = p.replace() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return diff --git a/posts.go b/posts.go index 28e0a3d..254538b 100644 --- a/posts.go +++ b/posts.go @@ -16,7 +16,7 @@ import ( var errPostNotFound = errors.New("post not found") -type Post struct { +type post struct { Path string `json:"path"` Content string `json:"content"` Published string `json:"published"` @@ -34,7 +34,7 @@ func servePost(w http.ResponseWriter, r *http.Request) { return } path := slashTrimmedPath(r) - post, err := getPost(r.Context(), path) + p, err := getPost(r.Context(), path) if err == errPostNotFound { serve404(w, r) return @@ -43,8 +43,8 @@ func servePost(w http.ResponseWriter, r *http.Request) { return } render(w, templatePost, &renderData{ - blogString: post.Blog, - Data: post, + blogString: p.Blog, + Data: p, }) } @@ -52,7 +52,7 @@ type indexTemplateData struct { Blog string Title string Description string - Posts []*Post + Posts []*post HasPrev bool HasNext bool First string @@ -174,7 +174,7 @@ func serveIndex(ic *indexConfig) func(w http.ResponseWriter, r *http.Request) { onlyWithParameter: ic.onlyWithParameter, }}, appConfig.Blogs[ic.blog].Pagination) p.SetPage(pageNo) - var posts []*Post + var posts []*post err := p.Results(&posts) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) @@ -222,7 +222,7 @@ func serveIndex(ic *indexConfig) func(w http.ResponseWriter, r *http.Request) { } } -func getPost(context context.Context, path string) (*Post, error) { +func getPost(context context.Context, path string) (*post, error) { posts, err := getPosts(context, &postsRequestConfig{path: path}) if err != nil { return nil, err @@ -243,7 +243,7 @@ type postsRequestConfig struct { onlyWithParameter string } -func getPosts(context context.Context, config *postsRequestConfig) (posts []*Post, err error) { +func getPosts(context context.Context, config *postsRequestConfig) (posts []*post, err error) { paths := make(map[string]int) var rows *sql.Rows defaultSelection := "select p.path, coalesce(content, ''), coalesce(published, ''), coalesce(updated, ''), coalesce(blog, ''), coalesce(section, ''), coalesce(parameter, ''), coalesce(value, '') " @@ -286,20 +286,20 @@ func getPosts(context context.Context, config *postsRequestConfig) (posts []*Pos _ = rows.Close() }() for rows.Next() { - post := &Post{} + p := &post{} var parameterName, parameterValue string - err = rows.Scan(&post.Path, &post.Content, &post.Published, &post.Updated, &post.Blog, &post.Section, ¶meterName, ¶meterValue) + err = rows.Scan(&p.Path, &p.Content, &p.Published, &p.Updated, &p.Blog, &p.Section, ¶meterName, ¶meterValue) if err != nil { return nil, err } - if paths[post.Path] == 0 { + if paths[p.Path] == 0 { index := len(posts) - paths[post.Path] = index + 1 - post.Parameters = make(map[string][]string) - posts = append(posts, post) + paths[p.Path] = index + 1 + p.Parameters = make(map[string][]string) + posts = append(posts, p) } if parameterName != "" && posts != nil { - posts[paths[post.Path]-1].Parameters[parameterName] = append(posts[paths[post.Path]-1].Parameters[parameterName], parameterValue) + posts[paths[p.Path]-1].Parameters[parameterName] = append(posts[paths[p.Path]-1].Parameters[parameterName], parameterValue) } } return posts, nil diff --git a/postsDb.go b/postsDb.go index 83db408..a7b29e3 100644 --- a/postsDb.go +++ b/postsDb.go @@ -11,7 +11,7 @@ import ( "github.com/araddon/dateparse" ) -func (p *Post) checkPost() error { +func (p *post) checkPost() error { if p == nil { return errors.New("no post") } @@ -102,15 +102,15 @@ func (p *Post) checkPost() error { return nil } -func (p *Post) create() error { +func (p *post) create() error { return p.createOrReplace(true) } -func (p *Post) replace() error { +func (p *post) replace() error { return p.createOrReplace(false) } -func (p *Post) createOrReplace(new bool) error { +func (p *post) createOrReplace(new bool) error { err := p.checkPost() if err != nil { return err diff --git a/postsFuncs.go b/postsFuncs.go index ae41686..0462ed3 100644 --- a/postsFuncs.go +++ b/postsFuncs.go @@ -1,22 +1,23 @@ package main import ( - "github.com/PuerkitoBio/goquery" "strings" + + "github.com/PuerkitoBio/goquery" ) -func (p *Post) firstParameter(parameter string) (result string) { +func (p *post) firstParameter(parameter string) (result string) { if pp := p.Parameters[parameter]; len(pp) > 0 { result = pp[0] } return } -func (p *Post) title() string { +func (p *post) title() string { return p.firstParameter("title") } -func (p *Post) summary() (summary string) { +func (p *post) summary() (summary string) { summary = p.firstParameter("summary") if summary != "" { return diff --git a/render.go b/render.go index 8e1a843..3e90213 100644 --- a/render.go +++ b/render.go @@ -45,18 +45,18 @@ func initRendering() error { return template.HTML(htmlContent) }, // First parameter value - "p": func(post *Post, parameter string) string { - return post.firstParameter(parameter) + "p": func(p *post, parameter string) string { + return p.firstParameter(parameter) }, // All parameter values - "ps": func(post *Post, parameter string) []string { - return post.Parameters[parameter] + "ps": func(p *post, parameter string) []string { + return p.Parameters[parameter] }, - "title": func(post *Post) string { - return post.title() + "title": func(p *post) string { + return p.title() }, - "summary": func(post *Post) string { - return post.summary() + "summary": func(p *post) string { + return p.summary() }, "dateformat": func(date string, format string) string { d, err := dateparse.ParseIn(date, time.Local) diff --git a/sitemap.go b/sitemap.go index 4a5a808..178e709 100644 --- a/sitemap.go +++ b/sitemap.go @@ -1,10 +1,11 @@ package main import ( - "github.com/araddon/dateparse" - "github.com/snabb/sitemap" "net/http" "time" + + "github.com/araddon/dateparse" + "github.com/snabb/sitemap" ) func serveSitemap() func(w http.ResponseWriter, r *http.Request) { @@ -16,19 +17,19 @@ func serveSitemap() func(w http.ResponseWriter, r *http.Request) { sm := sitemap.New() sm.Minify = true for _, p := range posts { + item := &sitemap.URL{ + Loc: appConfig.Server.PublicAddress + p.Path} var lastMod time.Time if p.Updated != "" { lastMod, _ = dateparse.ParseIn(p.Updated, time.Local) - } else if p.Published != "" { + } + if p.Published != "" && lastMod.IsZero() { lastMod, _ = dateparse.ParseIn(p.Published, time.Local) } - if lastMod.IsZero() { - lastMod = time.Now() + if !lastMod.IsZero() { + item.LastMod = &lastMod } - sm.Add(&sitemap.URL{ - Loc: appConfig.Server.PublicAddress + p.Path, - LastMod: &lastMod, - }) + sm.Add(item) } _, _ = sm.WriteTo(w) }