diff --git a/.env b/.env deleted file mode 100644 index e48c393..0000000 --- a/.env +++ /dev/null @@ -1,3 +0,0 @@ -export POCKET_BASE_PW=ifk2HEbM -export POCKET_BASE_HOST=http://aemos:5000 -export POCKET_BASE_USER=micro_blog_fetchers diff --git a/.gitignore b/.gitignore index 1ab3e6a..3739dcd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ keys/ gemini-server gemini_site + +.env diff --git a/go.mod b/go.mod index a5895a6..8850484 100644 --- a/go.mod +++ b/go.mod @@ -3,5 +3,6 @@ module gemini_site go 1.25.0 require ( + git.travisshears.com/travisshears/gemlog-cli v1.0.1 github.com/kulak/gemini v1.2.2 ) diff --git a/go.sum b/go.sum index 88ba58c..a1a1b63 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +git.travisshears.com/travisshears/gemlog-cli v1.0.1 h1:0AcFwrnukwcWHuePEROG3WDSGbcE8WoFvJTQxrTaszc= +git.travisshears.com/travisshears/gemlog-cli v1.0.1/go.mod h1:N6l94N174EhDOIHU0/RlJ0PWrxB0BMa0W6LcpgAtvCE= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/kulak/gemini v1.2.2 h1:wPFOAFFdOf9ZaHcpMwTq1xYUWxmyV3h0uQl0OXCGa+A= @@ -8,5 +10,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/gemlog/gemlog.go b/internal/gemlog/gemlog.go new file mode 100644 index 0000000..876fdf3 --- /dev/null +++ b/internal/gemlog/gemlog.go @@ -0,0 +1,102 @@ +package gemlog + +import ( + "fmt" + "log/slog" + "os" + "strconv" + "strings" + + gemlog "git.travisshears.com/travisshears/gemlog-cli/gemlog" + gemini "github.com/kulak/gemini" +) + +type Gemlog struct { + config *gemlog.Config +} + +func NewGemlog() *Gemlog { + port, err := strconv.Atoi(os.Getenv("COUCH_DB_PORT")) + if err != nil { + slog.Error("Failed to parse COUCH_DB_PORT", "error", err) + os.Exit(1) + } + + config := gemlog.Config{ + CouchDB: gemlog.CouchDBConfig{ + Host: os.Getenv("COUCHDB_HOST"), + Port: port, + User: os.Getenv("COUCHDB_USER"), + Password: os.Getenv("COUCHDB_PASSWORD"), + }, + } + + g := &Gemlog{ + config: &config, + } + return g +} + +func (g *Gemlog) HandleRequest(w gemini.ResponseWriter, req *gemini.Request) { + path := req.URL.Path + + switch { + case path == "/gemlog" || path == "/gemlog/": + g.serveIndex(w, req) + case strings.HasPrefix(path, "/gemlog/post/"): + slug := strings.TrimPrefix(path, "/gemlog/post/") + g.servePost(w, req, slug) + default: + w.WriteStatusMsg(gemini.StatusNotFound, "Page not found") + } +} + +func (g *Gemlog) serveIndex(w gemini.ResponseWriter, req *gemini.Request) { + w.WriteStatusMsg(gemini.StatusSuccess, "text/gemini") + + var content strings.Builder + page, err := os.ReadFile("./pages/gemlog.gmi") + if err != nil { + slog.Error("Problem reading gemlog page", "error", err) + return + } + content.Write(page) + content.WriteString("\n") + + posts, err := gemlog.ListGemLogs(g.config) + if err != nil { + content.WriteString("Error fetching posts: " + err.Error() + "\n\n") + } + + if len(posts) == 0 { + content.WriteString("No posts found.\n\n") + } else { + content.WriteString("## Posts\n\n") + + for _, post := range posts { + content.WriteString(fmt.Sprintf("=> /gemlog/post/%s %s - %s\n", post.Slug, post.Date.Format("2006-01-02"), post.Title)) + } + } + + content.WriteString("## Nav\n\n") + // content.WriteString(fmt.Sprintf("=> /microblog/page/%d Next page\n", pageNum+1)) + content.WriteString("=> / Back to home\n") + w.WriteBody([]byte(content.String())) +} + +func (g *Gemlog) servePost(w gemini.ResponseWriter, req *gemini.Request, slug string) { + var content strings.Builder + w.WriteStatusMsg(gemini.StatusSuccess, "text/gemini") + post, err := gemlog.ReadGemlogEntryBySlug(g.config, slug) + if err != nil { + content.WriteString("Error fetching gemlog post: " + err.Error() + "\n\n") + } + + content.WriteString(fmt.Sprintf("# %s\n", post.Title)) + content.WriteString(fmt.Sprintf("posted: %s\n", post.Date.Format("2006-01-02"))) + content.WriteString(post.Gemtxt) + content.WriteString("## Nav\n\n") + content.WriteString("=> /gemlog Back to gemlog list\n") + content.WriteString("=> / Back to home\n") + w.WriteBody([]byte(content.String())) +} diff --git a/internal/gemlog/handler.go b/internal/gemlog/handler.go new file mode 100644 index 0000000..2a57e3a --- /dev/null +++ b/internal/gemlog/handler.go @@ -0,0 +1,15 @@ +package gemlog + +import ( + gemini "github.com/kulak/gemini" +) + +// Handler interface for microblog functionality +type Handler interface { + HandleRequest(w gemini.ResponseWriter, req *gemini.Request) +} + +// NewHandler creates a new microblog handler +func NewHandler() Handler { + return NewGemlog() +} diff --git a/main.go b/main.go index 4a93954..8aec1cb 100644 --- a/main.go +++ b/main.go @@ -10,14 +10,16 @@ import ( "strings" "time" - "gemini_site/internal/microblog" + gemlog "gemini_site/internal/gemlog" + microblog "gemini_site/internal/microblog" "gemini_site/internal/pocketbase" gemini "github.com/kulak/gemini" ) type MainHandler struct { - blog microblog.Handler + blog microblog.Handler + gemlog gemlog.Handler } func (h MainHandler) ServeGemini(w gemini.ResponseWriter, req *gemini.Request) { @@ -31,6 +33,11 @@ func (h MainHandler) ServeGemini(w gemini.ResponseWriter, req *gemini.Request) { return } + if strings.HasPrefix(req.URL.Path, "/gemlog") { + h.gemlog.HandleRequest(w, req) + return + } + switch req.URL.Path { case "/": gemini.ServeFileName("pages/home.gmi", "text/gemini")(w, req) @@ -105,7 +112,8 @@ func main() { pbClient := pocketbase.NewPocketBaseClient() handler := MainHandler{ - blog: microblog.NewHandler(pbClient), + blog: microblog.NewHandler(pbClient), + gemlog: gemlog.NewHandler(), } err := gemini.ListenAndServe(host, cert, key, gemini.TrapPanic(handler.ServeGemini)) diff --git a/pages/gemlog.gmi b/pages/gemlog.gmi new file mode 100644 index 0000000..9003364 --- /dev/null +++ b/pages/gemlog.gmi @@ -0,0 +1,9 @@ +# Gemlog + +Welcome to my gemlog! + +I'm still figureing out exactly what I'll be posting here as I already maintain a tech blog on my personal site. For now it will mostly be about my experience with the gemini protocal. Maybe some tutorials on how to self-host a capsule. + +Abandoned capsules are a commmon sight here in gemspace. While this gemlog might go stale, the content on the micro-blog page is dynamic and as long as I'm posting to social media will have fresh content. Remember to check that page out as well. + +=> /microblog Microblog diff --git a/pages/home.gmi b/pages/home.gmi index c46207d..4c8d5a2 100644 --- a/pages/home.gmi +++ b/pages/home.gmi @@ -20,6 +20,7 @@ So far I've joined the following communities here in gemspace: ## Capsule Features +=> /gemlog Gemlog - Gemini exclusive blog => /microblog Microblog - Aggregation of all my microblog posts ## Site updates diff --git a/test_pocketbase.go b/test_pocketbase.go deleted file mode 100644 index 5edddf0..0000000 --- a/test_pocketbase.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "fmt" - "log/slog" - - "gemini_site/internal/microblog" - "gemini_site/internal/pocketbase" -) - -func main() { - pbClient := pocketbase.NewPocketBaseClient() - mb := microblog.NewMicroBlog(pbClient) - res, err := mb.GetRecentPosts(10) - // res, err := pbClient.GetList("micro_blog_posts", 1, 10, "-posted") - fmt.Println("Getting page 1 of microblog posts, 10 posts") - // posts, err := client.GetPosts(1) - if err != nil { - slog.Error("Error getting posts", "error", err) - } else { - slog.Info("Got microblog posts", "posts", res) - } -}