add pagination to microblog

This commit is contained in:
Travis Shears 2025-09-29 10:25:16 +02:00
parent ee4dfdad18
commit 444d143a0b

View file

@ -6,6 +6,8 @@ import (
"gemini_site/internal/pocketbase"
"log/slog"
"os"
"regexp"
"strconv"
"strings"
"time"
@ -131,8 +133,8 @@ func transformNostrPost(p pbPost) post {
}
// GetRecentPosts returns the most recent posts
func (mb *MicroBlog) GetRecentPosts(limit int) ([]post, error) {
res, err := mb.pbClient.GetList("micro_blog_posts", 1, limit, "-posted")
func (mb *MicroBlog) GetRecentPosts(limit int, page int) ([]post, error) {
res, err := mb.pbClient.GetList("micro_blog_posts", page, limit, "-posted")
if err != nil {
return nil, fmt.Errorf("failed to fetch posts from pocketbase: %w", err)
}
@ -165,13 +167,34 @@ func (mb *MicroBlog) GetRecentPosts(limit int) ([]post, error) {
return filteredPosts, nil
}
func replaceLinks(content string) string {
// Regex: ^(https?://\S+)
// ^ : start of line
// https? : http or https
// :// : literal
// \S+ : one or more non-whitespace characters
re := regexp.MustCompile(`(?m)^(https?://\S+)`)
// Replace each match with "=> <url>"
return re.ReplaceAllStringFunc(content, func(match string) string {
return "=> " + match
})
}
// HandleBlogRequest handles Gemini requests for the microblog
func (mb *MicroBlog) HandleBlogRequest(w gemini.ResponseWriter, req *gemini.Request) {
path := req.URL.Path
switch {
case path == "/microblog" || path == "/microblog/":
mb.serveIndex(w, req)
mb.serveIndex(w, req, 1)
case strings.HasPrefix(path, "/microblog/page/"):
pageNum := strings.TrimPrefix(path, "/microblog/page/")
num, err := strconv.Atoi(pageNum)
if err != nil {
w.WriteStatusMsg(gemini.StatusBadRequest, "Invalid page number")
return
}
mb.serveIndex(w, req, num)
// case strings.HasPrefix(path, "/microblog/post/"):
// postID := strings.TrimPrefix(path, "/microblog/post/")
// mb.servePost(w, req, postID)
@ -182,7 +205,8 @@ func (mb *MicroBlog) HandleBlogRequest(w gemini.ResponseWriter, req *gemini.Requ
func drawPost(builder *strings.Builder, p post) {
builder.WriteString("+------------------------------------------+\n")
builder.WriteString(p.Content)
content := replaceLinks(p.Content)
builder.WriteString(content)
builder.WriteString("\n")
builder.WriteString(fmt.Sprintf("source: %s, id: %s...\n", p.Source, p.RemoteID[:10]))
builder.WriteString("+------------------------------------------+\n\n\n")
@ -193,13 +217,14 @@ func drawPost(builder *strings.Builder, p post) {
}
// serveBlogIndex serves the main blog page with recent posts
func (mb *MicroBlog) serveIndex(w gemini.ResponseWriter, req *gemini.Request) {
func (mb *MicroBlog) serveIndex(w gemini.ResponseWriter, req *gemini.Request, pageNum int) {
w.WriteStatusMsg(gemini.StatusSuccess, "text/gemini")
var content strings.Builder
// content.WriteString("# Gemini Microblog\n\n")
// content.WriteString("Here are my microblog posts from various plantforms\n")
// Read and include the contents of ../../pages/microblog.gmi
if pageNum == 1 {
page, err := os.ReadFile("./pages/microblog.gmi")
if err != nil {
slog.Error("Problem reading microblog page", "error", err)
@ -207,8 +232,9 @@ func (mb *MicroBlog) serveIndex(w gemini.ResponseWriter, req *gemini.Request) {
}
content.Write(page)
content.WriteString("\n")
}
posts, err := mb.GetRecentPosts(20)
posts, err := mb.GetRecentPosts(20, pageNum)
if err != nil {
content.WriteString("Error fetching posts: " + err.Error() + "\n\n")
}
@ -216,7 +242,7 @@ func (mb *MicroBlog) serveIndex(w gemini.ResponseWriter, req *gemini.Request) {
if len(posts) == 0 {
content.WriteString("No posts found.\n\n")
} else {
content.WriteString("## Recent Posts\n\n")
content.WriteString("## Posts\n\n")
for _, post := range posts {
drawPost(&content, post)
@ -225,6 +251,8 @@ func (mb *MicroBlog) serveIndex(w gemini.ResponseWriter, req *gemini.Request) {
content.WriteString("## Nav\n\n")
// content.WriteString("=> /blog/new Write a new post\n")
content.WriteString(fmt.Sprintf("=> /microblog/page/%d Next page\n", pageNum+1))
content.WriteString("=> / Back to home\n")
w.WriteBody([]byte(content.String()))