blog visitor frontend (pretty much) done!
This commit is contained in:
parent
3d64333b4f
commit
faf6095d16
16 changed files with 903 additions and 463 deletions
187
view/blog.go
187
view/blog.go
|
@ -5,7 +5,9 @@ import (
|
|||
"html/template"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"arimelody-web/controller"
|
||||
"arimelody-web/model"
|
||||
|
@ -16,14 +18,26 @@ import (
|
|||
"github.com/gomarkdown/markdown/parser"
|
||||
)
|
||||
|
||||
type BlogView struct {
|
||||
*model.Blog
|
||||
Comments []*model.ThreadViewPost
|
||||
Likes int
|
||||
Reposts int
|
||||
BlueskyURL string
|
||||
MastodonURL string
|
||||
}
|
||||
type (
|
||||
BlogView struct {
|
||||
Collections []*BlogViewPostCollection
|
||||
}
|
||||
|
||||
BlogViewPostCollection struct {
|
||||
Name string
|
||||
Posts []*BlogPostView
|
||||
}
|
||||
|
||||
BlogPostView struct {
|
||||
*model.BlogPost
|
||||
Author *model.Account
|
||||
Comments []*model.ThreadViewPost
|
||||
Likes int
|
||||
Boosts int
|
||||
BlueskyURL string
|
||||
MastodonURL string
|
||||
}
|
||||
)
|
||||
|
||||
var mdRenderer = html.NewRenderer(html.RendererOptions{
|
||||
Flags: html.CommonFlags | html.HrefTargetBlank,
|
||||
|
@ -31,41 +45,105 @@ var mdRenderer = html.NewRenderer(html.RendererOptions{
|
|||
|
||||
func BlogHandler(app *model.AppState) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
blog := model.Blog{
|
||||
Title: "hello world!",
|
||||
Description: "lorem ipsum yadda yadda something boobies babababababababa",
|
||||
Visible: true,
|
||||
Date: time.Now(),
|
||||
AuthorID: "ari",
|
||||
Markdown:
|
||||
`
|
||||
**i'm ari!** (she/her) 🏳️⚧️🏳️🌈💫🦆🇮🇪
|
||||
if strings.Count(r.URL.Path, "/") > 1 {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
welcome to my blog!
|
||||
if len(r.URL.Path) > 1 {
|
||||
ServeBlogPost(app, r.URL.Path[1:]).ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
i'm a musician, developer, streamer, youtuber, and probably a bunch of other things i forgot to mention!
|
||||
dbPosts, err := controller.GetBlogPosts(app.DB, true, -1, 0)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no rows") {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog posts: %v\n", err)
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
collections := []*BlogViewPostCollection{}
|
||||
posts := []*BlogPostView{}
|
||||
collectionYear := 0
|
||||
for i, post := range dbPosts {
|
||||
author, err := controller.GetAccountByID(app.DB, post.AuthorID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "WARN: Failed to retrieve author of blog %s: %v\n", post.ID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
## code block test
|
||||
if i == 0 {
|
||||
collectionYear = post.CreatedAt.Year()
|
||||
}
|
||||
|
||||
~~~ c
|
||||
#include <stdio.h>
|
||||
if post.CreatedAt.Year() != collectionYear || i == len(dbPosts) - 1 {
|
||||
if i == len(dbPosts) - 1 {
|
||||
posts = append(posts, &BlogPostView{
|
||||
BlogPost: post,
|
||||
Author: author,
|
||||
})
|
||||
}
|
||||
postsCopy := slices.Clone(posts)
|
||||
collections = append(collections, &BlogViewPostCollection{
|
||||
Name: strconv.Itoa(collectionYear),
|
||||
Posts: postsCopy,
|
||||
})
|
||||
posts = []*BlogPostView{}
|
||||
collectionYear = post.CreatedAt.Year()
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("hello world!~\n");
|
||||
return 0;
|
||||
}
|
||||
~~~
|
||||
posts = append(posts, &BlogPostView{
|
||||
BlogPost: post,
|
||||
Author: author,
|
||||
})
|
||||
}
|
||||
|
||||
## aridoodle
|
||||
|
||||
this is `+"`"+`aridoodle`+"`"+`. please take care of her.
|
||||
|
||||

|
||||
`,
|
||||
BlueskyActorID: "did:plc:yct6cvgfipngizry5umzkxr3",
|
||||
BlueskyPostID: "3llsudsx7pc2u",
|
||||
err = templates.BlogTemplate.Execute(w, BlogView{
|
||||
Collections: collections,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "WARN: Error rendering blog post: %v\n", err)
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func ServeBlogPost(app *model.AppState, blogPostID string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
blog, err := controller.GetBlogPost(app.DB, blogPostID)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "no rows") {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog post Bluesky thread: %v\n", err)
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if !blog.Visible {
|
||||
session, err := controller.GetSessionFromRequest(app, r)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "WARN: Failed to retrieve session: %v\n", err)
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if session == nil || session.Account == nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
author, err := controller.GetAccountByID(app.DB, blog.AuthorID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "WARN: Failed to retrieve author of blog %s: %v\n", blog.ID, err)
|
||||
}
|
||||
|
||||
// blog.Markdown += " <i class=\"end-mark\"></i>"
|
||||
|
||||
|
@ -74,23 +152,32 @@ this is `+"`"+`aridoodle`+"`"+`. please take care of her.
|
|||
blog.HTML = template.HTML(markdown.Render(md, mdRenderer))
|
||||
|
||||
comments := []*model.ThreadViewPost{}
|
||||
blueskyPost, err := controller.FetchThreadViewPost(blog.BlueskyActorID, blog.BlueskyPostID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog post Bluesky thread: %v\n", err)
|
||||
} else {
|
||||
comments = append(comments, blueskyPost.Replies...)
|
||||
}
|
||||
likeCount := 0
|
||||
boostCount := 0
|
||||
var blueskyURL string
|
||||
var blueskyPost *model.ThreadViewPost
|
||||
if blog.BlueskyActorID != nil && blog.BlueskyPostID != nil {
|
||||
blueskyPost, err = controller.FetchThreadViewPost(*blog.BlueskyActorID, *blog.BlueskyPostID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog post Bluesky thread: %v\n", err)
|
||||
} else {
|
||||
comments = append(comments, blueskyPost.Replies...)
|
||||
likeCount += blueskyPost.Post.LikeCount
|
||||
boostCount += blueskyPost.Post.RepostCount
|
||||
blueskyURL = fmt.Sprintf("https://bsky.app/profile/%s/post/%s", blueskyPost.Post.Author.Handle, *blog.BlueskyPostID)
|
||||
}
|
||||
}
|
||||
|
||||
err = templates.BlogTemplate.Execute(w, BlogView{
|
||||
Blog: &blog,
|
||||
Comments: blueskyPost.Replies,
|
||||
Likes: blueskyPost.Post.LikeCount,
|
||||
Reposts: blueskyPost.Post.RepostCount,
|
||||
BlueskyURL: fmt.Sprintf("https://bsky.app/profile/%s/post/%s", blog.BlueskyActorID, blog.BlueskyPostID),
|
||||
MastodonURL: "#",
|
||||
err = templates.BlogPostTemplate.Execute(w, BlogPostView{
|
||||
BlogPost: blog,
|
||||
Author: author,
|
||||
Comments: comments,
|
||||
Likes: likeCount,
|
||||
Boosts: boostCount,
|
||||
BlueskyURL: blueskyURL,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error rendering blog post: %v\n", err)
|
||||
fmt.Fprintf(os.Stderr, "WARN: Error rendering blog post: %v\n", err)
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue