use new PocketBaseClient in microblog package
This commit is contained in:
parent
2837293474
commit
506a12c06c
3 changed files with 119 additions and 115 deletions
|
|
@ -1,6 +1,8 @@
|
||||||
package microblog
|
package microblog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"gemini_site/internal/pocketbase"
|
||||||
|
|
||||||
gemini "github.com/kulak/gemini"
|
gemini "github.com/kulak/gemini"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -10,6 +12,6 @@ type Handler interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a new microblog handler
|
// NewHandler creates a new microblog handler
|
||||||
func NewHandler() Handler {
|
func NewHandler(pbClient *pocketbase.PocketBaseClient) Handler {
|
||||||
return NewMicroBlog()
|
return NewMicroBlog(pbClient)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ package microblog
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"gemini_site/internal/pocketbase"
|
||||||
"strings"
|
"log/slog"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
gemini "github.com/kulak/gemini"
|
gemini "github.com/kulak/gemini"
|
||||||
|
|
@ -48,149 +48,149 @@ type pbPost struct {
|
||||||
|
|
||||||
// MicroBlog manages blog posts
|
// MicroBlog manages blog posts
|
||||||
type MicroBlog struct {
|
type MicroBlog struct {
|
||||||
posts []Post
|
pbClient *pocketbase.PocketBaseClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMicroBlog creates a new microblog instance
|
// NewMicroBlog creates a new microblog instance
|
||||||
func NewMicroBlog() *MicroBlog {
|
func NewMicroBlog(pbClient *pocketbase.PocketBaseClient) *MicroBlog {
|
||||||
mb := &MicroBlog{
|
mb := &MicroBlog{
|
||||||
posts: make([]Post, 0),
|
pbClient: pbClient,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add some sample posts
|
|
||||||
mb.addSamplePosts()
|
|
||||||
|
|
||||||
return mb
|
return mb
|
||||||
}
|
}
|
||||||
|
|
||||||
// addSamplePosts adds some initial content
|
// // Add some sample posts
|
||||||
func (mb *MicroBlog) addSamplePosts() {
|
// mb.addSamplePosts()
|
||||||
samplePosts := []Post{
|
|
||||||
{
|
|
||||||
ID: "1",
|
|
||||||
Title: "Welcome to the Gemini Microblog",
|
|
||||||
Content: "This is the first post on our Gemini-powered microblog! It's simple, fast, and distraction-free.",
|
|
||||||
Author: "Admin",
|
|
||||||
Timestamp: time.Now().Add(-2 * time.Hour),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "2",
|
|
||||||
Title: "The Beauty of Simplicity",
|
|
||||||
Content: "Gemini protocol encourages us to focus on content over presentation. This microblog embodies that philosophy.",
|
|
||||||
Author: "Admin",
|
|
||||||
Timestamp: time.Now().Add(-1 * time.Hour),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
mb.posts = append(mb.posts, samplePosts...)
|
// return mb
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// addSamplePosts adds some initial content
|
||||||
|
// func (mb *MicroBlog) addSamplePosts() {
|
||||||
|
// samplePosts := []Post{
|
||||||
|
// {
|
||||||
|
// ID: "1",
|
||||||
|
// Title: "Welcome to the Gemini Microblog",
|
||||||
|
// Content: "This is the first post on our Gemini-powered microblog! It's simple, fast, and distraction-free.",
|
||||||
|
// Author: "Admin",
|
||||||
|
// Timestamp: time.Now().Add(-2 * time.Hour),
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// ID: "2",
|
||||||
|
// Title: "The Beauty of Simplicity",
|
||||||
|
// Content: "Gemini protocol encourages us to focus on content over presentation. This microblog embodies that philosophy.",
|
||||||
|
// Author: "Admin",
|
||||||
|
// Timestamp: time.Now().Add(-1 * time.Hour),
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mb.posts = append(mb.posts, samplePosts...)
|
||||||
|
// }
|
||||||
|
|
||||||
// AddPost adds a new post to the blog
|
// AddPost adds a new post to the blog
|
||||||
func (mb *MicroBlog) AddPost(title, content, author string) string {
|
// func (mb *MicroBlog) AddPost(title, content, author string) string {
|
||||||
id := fmt.Sprintf("%d", time.Now().Unix())
|
// id := fmt.Sprintf("%d", time.Now().Unix())
|
||||||
post := Post{
|
// post := Post{
|
||||||
ID: id,
|
// ID: id,
|
||||||
Title: title,
|
// Title: title,
|
||||||
Content: content,
|
// Content: content,
|
||||||
Author: author,
|
// Author: author,
|
||||||
Timestamp: time.Now(),
|
// Timestamp: time.Now(),
|
||||||
}
|
// }
|
||||||
|
|
||||||
mb.posts = append(mb.posts, post)
|
// mb.posts = append(mb.posts, post)
|
||||||
return id
|
// return id
|
||||||
}
|
// }
|
||||||
|
|
||||||
// GetPost retrieves a post by ID
|
// GetPost retrieves a post by ID
|
||||||
func (mb *MicroBlog) GetPost(id string) (*Post, bool) {
|
// func (mb *MicroBlog) GetPost(id string) (*Post, bool) {
|
||||||
for _, post := range mb.posts {
|
// for _, post := range mb.posts {
|
||||||
if post.ID == id {
|
// if post.ID == id {
|
||||||
return &post, true
|
// return &post, true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return nil, false
|
// return nil, false
|
||||||
}
|
// }
|
||||||
|
|
||||||
// GetRecentPosts returns the most recent posts
|
// GetRecentPosts returns the most recent posts
|
||||||
func (mb *MicroBlog) GetRecentPosts(limit int) []Post {
|
func (mb *MicroBlog) GetRecentPosts(limit int) ([]post, error) {
|
||||||
// Sort posts by timestamp (newest first)
|
res, err := mb.pbClient.GetList("micro_blog_posts", 1, limit, "-posted")
|
||||||
sortedPosts := make([]Post, len(mb.posts))
|
if err != nil {
|
||||||
copy(sortedPosts, mb.posts)
|
return nil, fmt.Errorf("failed to fetch posts from pocketbase: %w", err)
|
||||||
|
|
||||||
sort.Slice(sortedPosts, func(i, j int) bool {
|
|
||||||
return sortedPosts[i].Timestamp.After(sortedPosts[j].Timestamp)
|
|
||||||
})
|
|
||||||
|
|
||||||
if limit > 0 && len(sortedPosts) > limit {
|
|
||||||
return sortedPosts[:limit]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sortedPosts
|
var rawPosts []pbPost
|
||||||
|
if err := json.Unmarshal(res.Items, &rawPosts); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode response: %w", err)
|
||||||
|
}
|
||||||
|
slog.Info("Posts from pocketbase", "rawPosts", rawPosts)
|
||||||
|
return nil, fmt.Errorf("todo: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleBlogRequest handles Gemini requests for the microblog
|
// HandleBlogRequest handles Gemini requests for the microblog
|
||||||
func (mb *MicroBlog) HandleBlogRequest(w gemini.ResponseWriter, req *gemini.Request) {
|
func (mb *MicroBlog) HandleBlogRequest(w gemini.ResponseWriter, req *gemini.Request) {
|
||||||
path := req.URL.Path
|
// path := req.URL.Path
|
||||||
|
|
||||||
switch {
|
// switch {
|
||||||
case path == "/microblog" || path == "/microblog/":
|
// case path == "/microblog" || path == "/microblog/":
|
||||||
mb.serveBlogIndex(w, req)
|
// mb.serveBlogIndex(w, req)
|
||||||
case strings.HasPrefix(path, "/microblog/post/"):
|
// case strings.HasPrefix(path, "/microblog/post/"):
|
||||||
postID := strings.TrimPrefix(path, "/microblog/post/")
|
// postID := strings.TrimPrefix(path, "/microblog/post/")
|
||||||
mb.servePost(w, req, postID)
|
// mb.servePost(w, req, postID)
|
||||||
default:
|
// default:
|
||||||
w.WriteStatusMsg(gemini.StatusNotFound, "Blog page not found")
|
// w.WriteStatusMsg(gemini.StatusNotFound, "Blog page not found")
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// serveBlogIndex serves the main blog page with recent posts
|
// serveBlogIndex serves the main blog page with recent posts
|
||||||
func (mb *MicroBlog) serveBlogIndex(w gemini.ResponseWriter, req *gemini.Request) {
|
// func (mb *MicroBlog) serveBlogIndex(w gemini.ResponseWriter, req *gemini.Request) {
|
||||||
w.WriteStatusMsg(gemini.StatusSuccess, "text/gemini")
|
// w.WriteStatusMsg(gemini.StatusSuccess, "text/gemini")
|
||||||
|
|
||||||
var content strings.Builder
|
// var content strings.Builder
|
||||||
content.WriteString("# Gemini Microblog\n\n")
|
// content.WriteString("# Gemini Microblog\n\n")
|
||||||
|
|
||||||
posts := mb.GetRecentPosts(10)
|
// posts := mb.GetRecentPosts(10)
|
||||||
|
|
||||||
if len(posts) == 0 {
|
// if len(posts) == 0 {
|
||||||
content.WriteString("No posts yet. Be the first to write something!\n\n")
|
// content.WriteString("No posts yet. Be the first to write something!\n\n")
|
||||||
} else {
|
// } else {
|
||||||
content.WriteString("## Recent Posts\n\n")
|
// content.WriteString("## Recent Posts\n\n")
|
||||||
|
|
||||||
for _, post := range posts {
|
// for _, post := range posts {
|
||||||
content.WriteString(fmt.Sprintf("=> /blog/post/%s %s\n", post.ID, post.Title))
|
// content.WriteString(fmt.Sprintf("=> /blog/post/%s %s\n", post.ID, post.Title))
|
||||||
content.WriteString(fmt.Sprintf(" By %s on %s\n\n",
|
// content.WriteString(fmt.Sprintf(" By %s on %s\n\n",
|
||||||
post.Author,
|
// post.Author,
|
||||||
post.Timestamp.Format("2006-01-02 15:04")))
|
// post.Timestamp.Format("2006-01-02 15:04")))
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
content.WriteString("## Actions\n\n")
|
// content.WriteString("## Actions\n\n")
|
||||||
content.WriteString("=> /blog/new Write a new post\n")
|
// content.WriteString("=> /blog/new Write a new post\n")
|
||||||
content.WriteString("=> / Back to home\n")
|
// content.WriteString("=> / Back to home\n")
|
||||||
|
|
||||||
w.WriteBody([]byte(content.String()))
|
// w.WriteBody([]byte(content.String()))
|
||||||
}
|
// }
|
||||||
|
|
||||||
// servePost serves a single blog post
|
// servePost serves a single blog post
|
||||||
func (mb *MicroBlog) servePost(w gemini.ResponseWriter, req *gemini.Request, postID string) {
|
// func (mb *MicroBlog) servePost(w gemini.ResponseWriter, req *gemini.Request, postID string) {
|
||||||
post, found := mb.GetPost(postID)
|
// post, found := mb.GetPost(postID)
|
||||||
if !found {
|
// if !found {
|
||||||
w.WriteStatusMsg(gemini.StatusNotFound, "Post not found")
|
// w.WriteStatusMsg(gemini.StatusNotFound, "Post not found")
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
w.WriteStatusMsg(gemini.StatusSuccess, "text/gemini")
|
// w.WriteStatusMsg(gemini.StatusSuccess, "text/gemini")
|
||||||
|
|
||||||
var content strings.Builder
|
// var content strings.Builder
|
||||||
content.WriteString(fmt.Sprintf("# %s\n\n", post.Title))
|
// content.WriteString(fmt.Sprintf("# %s\n\n", post.Title))
|
||||||
content.WriteString(fmt.Sprintf("By %s on %s\n\n",
|
// content.WriteString(fmt.Sprintf("By %s on %s\n\n",
|
||||||
post.Author,
|
// post.Author,
|
||||||
post.Timestamp.Format("2006-01-02 15:04")))
|
// post.Timestamp.Format("2006-01-02 15:04")))
|
||||||
content.WriteString("---\n\n")
|
// content.WriteString("---\n\n")
|
||||||
content.WriteString(post.Content)
|
// content.WriteString(post.Content)
|
||||||
content.WriteString("\n\n---\n\n")
|
// content.WriteString("\n\n---\n\n")
|
||||||
content.WriteString("=> /blog Back to blog\n")
|
// content.WriteString("=> /blog Back to blog\n")
|
||||||
content.WriteString("=> / Back to home\n")
|
// content.WriteString("=> / Back to home\n")
|
||||||
|
|
||||||
w.WriteBody([]byte(content.String()))
|
// w.WriteBody([]byte(content.String()))
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,17 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"gemini_site/internal/microblog"
|
||||||
"gemini_site/internal/pocketbase"
|
"gemini_site/internal/pocketbase"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
pbClient := pocketbase.NewPocketBaseClient()
|
pbClient := pocketbase.NewPocketBaseClient()
|
||||||
res, err := pbClient.GetList("micro_blog_posts", 1, 10, "-posted")
|
mb := microblog.NewMicroBlog(pbClient)
|
||||||
|
res, err := mb.GetRecentPosts(2)
|
||||||
|
// res, err := pbClient.GetList("micro_blog_posts", 1, 10, "-posted")
|
||||||
fmt.Println("Getting page 1 of microblog posts")
|
fmt.Println("Getting page 1 of microblog posts")
|
||||||
// posts, err := client.GetPosts(1)
|
// posts, err := client.GetPosts(1)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error getting posts: %v", err)
|
log.Printf("Error getting posts: %v", err)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue