diff --git a/internal/microblog/microblog.go b/internal/microblog/microblog.go index ff36dc3..7229613 100644 --- a/internal/microblog/microblog.go +++ b/internal/microblog/microblog.go @@ -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,15 +167,36 @@ 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 "=> " + 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/") + // postID := strings.TrimPrefix(path, "/microblog/post/") // mb.servePost(w, req, postID) default: w.WriteStatusMsg(gemini.StatusNotFound, "Page not found") @@ -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,22 +217,24 @@ 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 - page, err := os.ReadFile("./pages/microblog.gmi") - if err != nil { - slog.Error("Problem reading microblog page", "error", err) - return + if pageNum == 1 { + page, err := os.ReadFile("./pages/microblog.gmi") + if err != nil { + slog.Error("Problem reading microblog page", "error", err) + return + } + content.Write(page) + content.WriteString("\n") } - 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()))