2025-11-07 01:04:10 +00:00
|
|
|
package blog
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"arimelody-web/admin/core"
|
|
|
|
|
"arimelody-web/admin/templates"
|
|
|
|
|
"arimelody-web/controller"
|
|
|
|
|
"arimelody-web/model"
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/http"
|
|
|
|
|
"os"
|
|
|
|
|
"slices"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func Handler(app *model.AppState) http.Handler {
|
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
|
|
2025-11-07 02:35:51 +00:00
|
|
|
mux.Handle("/{id}", serveBlogPost(app))
|
|
|
|
|
mux.Handle("/", serveBlogIndex(app))
|
2025-11-07 01:04:10 +00:00
|
|
|
|
|
|
|
|
mux.ServeHTTP(w, r)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type (
|
|
|
|
|
blogPost struct {
|
|
|
|
|
*model.BlogPost
|
|
|
|
|
Author *model.Account
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
blogPostGroup struct {
|
|
|
|
|
Year int
|
|
|
|
|
Posts []*blogPost
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2025-11-07 02:35:51 +00:00
|
|
|
func serveBlogIndex(app *model.AppState) http.Handler {
|
2025-11-07 01:04:10 +00:00
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2025-11-07 02:35:51 +00:00
|
|
|
session := r.Context().Value("session").(*model.Session)
|
2025-11-07 01:04:10 +00:00
|
|
|
|
|
|
|
|
posts, err := controller.GetBlogPosts(app.DB, false, -1, 0)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "WARN: Failed to fetch blog posts: %v\n", err)
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
collections := []*blogPostGroup{}
|
|
|
|
|
collectionPosts := []*blogPost{}
|
|
|
|
|
collectionYear := -1
|
|
|
|
|
for i, post := range posts {
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if collectionYear == -1 {
|
|
|
|
|
collectionYear = post.CreatedAt.Year()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
authoredPost := blogPost{
|
|
|
|
|
BlogPost: post,
|
|
|
|
|
Author: author,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if post.CreatedAt.Year() != collectionYear || i == len(posts) - 1 {
|
|
|
|
|
if i == len(posts) - 1 {
|
|
|
|
|
collectionPosts = append(collectionPosts, &authoredPost)
|
|
|
|
|
}
|
|
|
|
|
collections = append(collections, &blogPostGroup{
|
|
|
|
|
Year: collectionYear,
|
|
|
|
|
Posts: slices.Clone(collectionPosts),
|
|
|
|
|
})
|
|
|
|
|
collectionPosts = []*blogPost{}
|
|
|
|
|
collectionYear = post.CreatedAt.Year()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
collectionPosts = append(collectionPosts, &authoredPost)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type blogsData struct {
|
|
|
|
|
core.AdminPageData
|
|
|
|
|
TotalPosts int
|
|
|
|
|
Collections []*blogPostGroup
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = templates.BlogsTemplate.Execute(w, blogsData{
|
|
|
|
|
AdminPageData: core.AdminPageData{
|
|
|
|
|
Session: session,
|
|
|
|
|
},
|
|
|
|
|
TotalPosts: len(posts),
|
|
|
|
|
Collections: collections,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "WARN: Error rendering admin blog index: %v\n", err)
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2025-11-07 02:35:51 +00:00
|
|
|
|
|
|
|
|
func serveBlogPost(app *model.AppState) http.Handler {
|
|
|
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
session := r.Context().Value("session").(*model.Session)
|
|
|
|
|
|
|
|
|
|
blogID := r.PathValue("id")
|
|
|
|
|
|
|
|
|
|
post, err := controller.GetBlogPost(app.DB, blogID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf("can't find blog with ID %s\n", blogID)
|
|
|
|
|
http.NotFound(w, r)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type blogPostData struct {
|
|
|
|
|
core.AdminPageData
|
|
|
|
|
Post *model.BlogPost
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = templates.EditBlogTemplate.Execute(w, blogPostData{
|
|
|
|
|
AdminPageData: core.AdminPageData{
|
|
|
|
|
Session: session,
|
|
|
|
|
},
|
|
|
|
|
Post: post,
|
|
|
|
|
})
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Fprintf(os.Stderr, "WARN: Error rendering admin edit page for blog %s: %v\n", blogID, err)
|
|
|
|
|
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|