diff --git a/bruno/Gemlog/List Gemlogs for CLI.bru b/bruno/Gemlog/List Gemlogs for CLI.bru new file mode 100644 index 0000000..eda7653 --- /dev/null +++ b/bruno/Gemlog/List Gemlogs for CLI.bru @@ -0,0 +1,20 @@ +meta { + name: List Gemlogs for CLI + type: http + seq: 3 +} + +get { + url: http://eisenhorn:5023/gemlog/_design/gemlog-cli/_view/list + body: json + auth: basic +} + +auth:basic { + username: gemlog-cli + password: {{pw}} +} + +settings { + encodeUrl: true +} diff --git a/gemlog/core.go b/gemlog/core.go index b4efb6e..4501a97 100644 --- a/gemlog/core.go +++ b/gemlog/core.go @@ -16,6 +16,13 @@ type GemlogEntry struct { Gemtxt string `json:"gemtxt"` } +type GemlogListEntry struct { + Title string `json:"title"` + Slug string `json:"slug"` + Date time.Time `json:"date"` + ID string `json:"id"` +} + // NewUUID generates a new UUID v4 using crypto/rand func NewUUID() (string, error) { uuid := make([]byte, 16) diff --git a/gemlog/db.go b/gemlog/db.go index ecdb93f..13f0c2b 100644 --- a/gemlog/db.go +++ b/gemlog/db.go @@ -9,6 +9,62 @@ import ( "net/http" ) +func genBasicAuthHeader(user, password string) string { + auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", user, password))) + return fmt.Sprintf("Basic %s", auth) +} + +func ListGemLogs(config *Config) ([]GemlogListEntry, error) { + url := fmt.Sprintf("%s:%d/gemlog/_design/gemlog-cli/_view/list", 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) + } + + req.Header.Add("authorization", genBasicAuthHeader(config.CouchDB.User, config.CouchDB.Password)) + + res, err := http.DefaultClient.Do(req) + if err != nil { + return nil, fmt.Errorf("failed to send request: %w", err) + } + defer res.Body.Close() + + body, err := io.ReadAll(res.Body) + if err != nil { + return nil, fmt.Errorf("failed to read response body: %w", err) + } + + if res.StatusCode < 200 || res.StatusCode >= 300 { + return nil, fmt.Errorf("unexpected status code %d: %s", res.StatusCode, string(body)) + } + + // Parse CouchDB response + var couchResponse struct { + TotalRows int `json:"total_rows"` + Offset int `json:"offset"` + Rows []struct { + ID string `json:"id"` + Key string `json:"key"` + Value struct { + Rev string `json:"rev"` + } `json:"value"` + Doc GemlogListEntry `json:"doc"` + } `json:"rows"` + } + + if err := json.Unmarshal(body, &couchResponse); err != nil { + return nil, fmt.Errorf("failed to parse response: %w", err) + } + + // Extract entries from response + entries := make([]GemlogListEntry, 0, len(couchResponse.Rows)) + for _, row := range couchResponse.Rows { + entries = append(entries, row.Doc) + } + + return entries, nil +} + func SaveGemlogEntry(config *Config, entry *GemlogEntry) error { url := fmt.Sprintf("%s:%d/gemlog/", config.CouchDB.Host, config.CouchDB.Port) @@ -23,9 +79,7 @@ func SaveGemlogEntry(config *Config, entry *GemlogEntry) error { return fmt.Errorf("failed to create request: %w", err) } - // Encode username:password for Basic Auth - auth := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", config.CouchDB.User, config.CouchDB.Password))) - req.Header.Add("authorization", fmt.Sprintf("Basic %s", auth)) + req.Header.Add("authorization", genBasicAuthHeader(config.CouchDB.User, config.CouchDB.Password)) req.Header.Add("content-type", "application/json") res, err := http.DefaultClient.Do(req) diff --git a/gemlog/read.go b/gemlog/read.go new file mode 100644 index 0000000..e69de29 diff --git a/main.go b/main.go index edf1c94..032d8fc 100644 --- a/main.go +++ b/main.go @@ -120,6 +120,7 @@ func main() { os.Exit(1) } + // TODO: check if we can reach db before starting program p := tea.NewProgram(initialModel(config)) if _, err := p.Run(); err != nil { fmt.Printf("Alas, there's been an error: %v", err)