From 00226ebfddfe0018c75e3c619099804dfa707e79 Mon Sep 17 00:00:00 2001 From: Travis Shears Date: Mon, 6 Oct 2025 09:49:34 +0200 Subject: [PATCH 1/6] add ReadGemlogEntryBySlug --- bruno/Gemlog/Get Gemlog By Slug.bru | 24 +++++++++++ gemlog/db.go | 63 +++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 bruno/Gemlog/Get Gemlog By Slug.bru diff --git a/bruno/Gemlog/Get Gemlog By Slug.bru b/bruno/Gemlog/Get Gemlog By Slug.bru new file mode 100644 index 0000000..f02e8a2 --- /dev/null +++ b/bruno/Gemlog/Get Gemlog By Slug.bru @@ -0,0 +1,24 @@ +meta { + name: Get Gemlog By Slug + type: http + seq: 6 +} + +get { + url: http://eisenhorn:5023/gemlog/_design/capsule/_view/post_by_slug?key="hello-from-gemlog-cli" + body: json + auth: basic +} + +params:query { + key: "hello-from-gemlog-cli" +} + +auth:basic { + username: gemlog-cli + password: {{pw}} +} + +settings { + encodeUrl: true +} diff --git a/gemlog/db.go b/gemlog/db.go index e3b0efa..bae5533 100644 --- a/gemlog/db.go +++ b/gemlog/db.go @@ -123,6 +123,69 @@ func ReadGemlogEntry(config *Config, id string) (GemlogEntry, error) { }, nil } +func ReadGemlogEntryBySlug(config *Config, slug string) (GemlogEntry, error) { + url := fmt.Sprintf("%s:%d/gemlog/_design/capsule/_view/post_by_slug?key=\"%s\"", config.CouchDB.Host, config.CouchDB.Port, slug) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return GemlogEntry{}, fmt.Errorf("failed to create request: %w", err) + } + + req.Header.Add("authorization", genBasicAuthHeader(config.CouchDB.User, config.CouchDB.Password)) + req.Header.Add("content-type", "application/json") + + res, err := http.DefaultClient.Do(req) + if err != nil { + return GemlogEntry{}, fmt.Errorf("failed to send request: %w", err) + } + defer res.Body.Close() + + body, err := io.ReadAll(res.Body) + if err != nil { + return GemlogEntry{}, fmt.Errorf("failed to read response body: %w", err) + } + + if res.StatusCode < 200 || res.StatusCode >= 300 { + return GemlogEntry{}, fmt.Errorf("unexpected status code %d: %s", res.StatusCode, string(body)) + } + + // Decode CouchDB view response + var viewResponse struct { + TotalRows int `json:"total_rows"` + Offset int `json:"offset"` + Rows []struct { + ID string `json:"id"` + Key string `json:"key"` + Value struct { + ID string `json:"_id"` + Rev string `json:"_rev"` + Title string `json:"title"` + Slug string `json:"slug"` + Date time.Time `json:"date"` + Gemtxt string `json:"gemtxt"` + } `json:"value"` + } `json:"rows"` + } + + if err := json.Unmarshal(body, &viewResponse); err != nil { + return GemlogEntry{}, fmt.Errorf("failed to parse response: %w", err) + } + + // Check if we got any results + if len(viewResponse.Rows) == 0 { + return GemlogEntry{}, fmt.Errorf("no document found with slug: %s", slug) + } + + // Extract the first (and should be only) result + doc := viewResponse.Rows[0].Value + + return GemlogEntry{ + Title: doc.Title, + Slug: doc.Slug, + Date: doc.Date, + Gemtxt: doc.Gemtxt, + }, nil +} + func DeleteGemlogEntry(config *Config, id string, rev string) error { url := fmt.Sprintf("%s:%d/gemlog/%s?rev=%s", config.CouchDB.Host, config.CouchDB.Port, id, rev) req, err := http.NewRequest("DELETE", url, nil) From ea2233cb2b0231ab7f43c324c5caf360a62f37bb Mon Sep 17 00:00:00 2001 From: Travis Shears Date: Mon, 6 Oct 2025 09:52:23 +0200 Subject: [PATCH 2/6] add config setup instructions --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 060133d..b029ccb 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,20 @@ Quick tool to write gemtext posts for my gemlog. => gemini://travisshears.com/gemlog +## Config setup + +This app relys on a config file at `~/.config/gemlog-cli/config.yml` + +With the following format: + +```yaml +couchdb: + host: http://myhost + port: 1234 + user: gemlog-cli + password: xxxxxxxxxxxxxxxxxxxxxxxxxxx +``` + ## Dev To run command locally: From df6679edf5d1ad0d323de78ca83b49d373b7446c Mon Sep 17 00:00:00 2001 From: Travis Shears Date: Mon, 6 Oct 2025 10:08:27 +0200 Subject: [PATCH 3/6] add install instructions --- .gitignore | 1 + README.md | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/.gitignore b/.gitignore index b14c548..bf5e268 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ debug.log +/bin diff --git a/README.md b/README.md index b029ccb..80352bb 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,15 @@ Quick tool to write gemtext posts for my gemlog. => gemini://travisshears.com/gemlog +## Install + +Build and link. Remember to setup config file as well. + +```shell +$ go build -o bin/gemlog +$ ln -s /Users/xxxxxxxx/_projects/gemlog-cli/bin/gemlog-cli ~/bin/gemlog +``` + ## Config setup This app relys on a config file at `~/.config/gemlog-cli/config.yml` From 7cb2ac3e8f55803506be083bb6af842417d7732c Mon Sep 17 00:00:00 2001 From: Travis Shears Date: Mon, 6 Oct 2025 10:42:09 +0200 Subject: [PATCH 4/6] disable logging --- internal/{ui => }/config/config.go | 0 internal/ui/app.go | 2 +- main.go | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename internal/{ui => }/config/config.go (100%) diff --git a/internal/ui/config/config.go b/internal/config/config.go similarity index 100% rename from internal/ui/config/config.go rename to internal/config/config.go diff --git a/internal/ui/app.go b/internal/ui/app.go index f3fce1c..a52c1a8 100644 --- a/internal/ui/app.go +++ b/internal/ui/app.go @@ -118,7 +118,7 @@ func (m model) View() string { return s } -var enableLogs bool = true +var enableLogs bool = false func Run(config *gemlog.Config) { if enableLogs { diff --git a/main.go b/main.go index 3c1c08a..7de4196 100644 --- a/main.go +++ b/main.go @@ -4,8 +4,8 @@ import ( "fmt" "os" + config "git.travisshears.com/travisshears/gemlog-cli/internal/config" ui "git.travisshears.com/travisshears/gemlog-cli/internal/ui" - config "git.travisshears.com/travisshears/gemlog-cli/internal/ui/config" ) func main() { From e689d210e7364b7643ef2254003ad0ac8d3f51e0 Mon Sep 17 00:00:00 2001 From: Travis Shears Date: Tue, 7 Oct 2025 09:56:39 +0200 Subject: [PATCH 5/6] change sorting to show latest posts first --- gemlog/db.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gemlog/db.go b/gemlog/db.go index bae5533..3d7ed0f 100644 --- a/gemlog/db.go +++ b/gemlog/db.go @@ -17,7 +17,7 @@ func genBasicAuthHeader(user, password string) string { } func ListGemLogs(config *Config) ([]GemlogListEntry, error) { - url := fmt.Sprintf("%s:%d/gemlog/_design/gemlog-cli/_view/list", config.CouchDB.Host, config.CouchDB.Port) + url := fmt.Sprintf("%s:%d/gemlog/_design/gemlog-cli/_view/list?descending=true", config.CouchDB.Host, config.CouchDB.Port) req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, fmt.Errorf("failed to create request: %w", err) From 0233572fd1ed914a0ff9de3dea730d9e69a985b7 Mon Sep 17 00:00:00 2001 From: Travis Shears Date: Wed, 8 Oct 2025 21:19:12 +0200 Subject: [PATCH 6/6] fix scroll and add bulid script --- build.sh | 5 +++++ internal/ui/entryList.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100755 build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5ad72f6 --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +go build -o ./bin/gemlog-cli diff --git a/internal/ui/entryList.go b/internal/ui/entryList.go index 5be6dfc..0331cab 100644 --- a/internal/ui/entryList.go +++ b/internal/ui/entryList.go @@ -39,7 +39,7 @@ func (m EntryListPageModel) Update(msg tea.Msg, active bool, ctx *context) (Entr m.cursor-- } case "down", "j": - if m.cursor < len(actions)-1 { + if m.cursor < len(m.entries)-1 { m.cursor++ } case "left", "h":