Skip to content

Commit 222fd16

Browse files
nervebandclaude
andcommitted
Add self-upgrade, ASCII banner, and demo video
Features: - Add 'upgrade' command for self-updating from GitHub releases - Add 'version' command showing build info - Add ASCII art banner on startup - Add Remotion demo video with Beeper branding - Add demo GIF to README Fixes: - Fix search response parsing for {items: [...]} format - Fix search default limit (100 → 20 to match API max) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 4936a1d commit 222fd16

20 files changed

Lines changed: 1085 additions & 16 deletions

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Beeper API CLI
22

3+
<p align="center">
4+
<img src="assets/demo.gif" alt="Beeper API CLI Demo" width="800">
5+
</p>
6+
37
A cross-platform command-line interface for the Beeper Desktop API. Built for programmatic access to Beeper conversations with LLM-friendly output formats.
48

59
🚀 **[Quick Start Guide](QUICKSTART.md)** | 📚 **[API Documentation](API.md)** | 🔧 **[Examples](examples/)**
@@ -14,6 +18,7 @@ While existing tools read the Beeper SQLite database directly, this CLI interfac
1418
- **LLM-Friendly Output**: JSON, plain text, and markdown formats optimized for AI agent consumption
1519
- **Auto-Discovery**: Automatically detect Beeper Desktop API endpoint when available
1620
- **Cross-Platform**: Single binary for Linux, macOS, and Windows
21+
- **Self-Upgrade**: Built-in upgrade command to update to the latest version
1722
- **Pipeable**: Unix-friendly design for scripting and tool composition
1823

1924
## Installation
@@ -82,6 +87,10 @@ output_format: json # json, text, markdown
8287
- `delete` - Delete message
8388
- `read` - Mark messages as read
8489

90+
### Utility Commands
91+
- `version` - Display version and build information
92+
- `upgrade` - Self-upgrade to the latest release from GitHub
93+
8594
## Output Formats
8695

8796
All commands support multiple output formats via `--output` flag:

assets/demo.gif

8.7 MB
Loading

cmd/banner.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
// Banner displays the ASCII art banner for beeper-api-cli
8+
const banner = `
9+
____ ______ ______ ____ ______ ____
10+
/ __ )/ ____// ____// __ \/ ____// __ \
11+
/ __ / __/ / __/ / /_/ / __/ / /_/ /
12+
/ /_/ / /___ / /___ / ____/ /___ / _, _/
13+
/_____/_____//_____//_/ /_____//_/ |_|
14+
15+
█████╗ ██████╗ ██╗ ██████╗██╗ ██╗
16+
██╔══██╗██╔══██╗██║ ██╔════╝██║ ██║
17+
███████║██████╔╝██║█████╗██║ ██║ ██║
18+
██╔══██║██╔═══╝ ██║╚════╝██║ ██║ ██║
19+
██║ ██║██║ ██║ ╚██████╗███████╗██║
20+
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚══════╝╚═╝
21+
`
22+
23+
// BannerWithVersion returns the banner with version info
24+
func BannerWithVersion() string {
25+
return fmt.Sprintf("%s\n Command-line interface for Beeper Desktop API\n Version: %s\n", banner, Version)
26+
}
27+
28+
// PrintBanner prints the ASCII art banner
29+
func PrintBanner() {
30+
fmt.Print(BannerWithVersion())
31+
}

cmd/root.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ import (
1313
var (
1414
cfg *config.Config
1515
outputFormat string
16+
// Version is set at build time via ldflags
17+
Version = "dev"
1618
)
1719

1820
var rootCmd = &cobra.Command{
1921
Use: "beeper",
2022
Short: "Beeper API CLI - Command-line interface for Beeper Desktop API",
21-
Long: `A cross-platform CLI for the Beeper Desktop API.
22-
Provides LLM-friendly interfaces for reading and sending messages
23-
across all Beeper-supported chat networks.`,
23+
Long: BannerWithVersion() + "\nA cross-platform CLI for the Beeper Desktop API.\nProvides LLM-friendly interfaces for reading and sending messages\nacross all Beeper-supported chat networks.",
2424
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
2525
var err error
2626
cfg, err = config.Load()

cmd/search.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@ var searchCmd = &cobra.Command{
3636

3737
func init() {
3838
searchCmd.Flags().String("query", "", "Search query text")
39-
searchCmd.Flags().IntVar(&searchLimit, "limit", 100, "Maximum number of results")
39+
searchCmd.Flags().IntVar(&searchLimit, "limit", 20, "Maximum number of results (max: 20)")
4040
rootCmd.AddCommand(searchCmd)
4141
}

cmd/upgrade.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"runtime"
7+
8+
"github.com/creativeprojects/go-selfupdate"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
// Configure these for your repo
13+
const repoOwner = "nerveband"
14+
const repoName = "beeper-api-cli"
15+
16+
var upgradeCmd = &cobra.Command{
17+
Use: "upgrade",
18+
Short: "Upgrade to the latest version",
19+
Long: "Check for and install the latest version from GitHub releases",
20+
RunE: func(cmd *cobra.Command, args []string) error {
21+
return runUpgrade()
22+
},
23+
}
24+
25+
func init() {
26+
rootCmd.AddCommand(upgradeCmd)
27+
}
28+
29+
func runUpgrade() error {
30+
fmt.Printf("Current version: %s\n", Version)
31+
fmt.Println("Checking for updates...")
32+
33+
// Create GitHub source (no auth needed for public repos)
34+
source, err := selfupdate.NewGitHubSource(selfupdate.GitHubConfig{})
35+
if err != nil {
36+
return fmt.Errorf("failed to create update source: %w", err)
37+
}
38+
39+
// Create updater (checksum validation optional - only if checksums.txt exists)
40+
updater, err := selfupdate.NewUpdater(selfupdate.Config{
41+
Source: source,
42+
})
43+
if err != nil {
44+
return fmt.Errorf("failed to create updater: %w", err)
45+
}
46+
47+
// Check for latest release
48+
latest, found, err := updater.DetectLatest(
49+
context.Background(),
50+
selfupdate.NewRepositorySlug(repoOwner, repoName),
51+
)
52+
if err != nil {
53+
return fmt.Errorf("failed to check for updates: %w", err)
54+
}
55+
56+
if !found {
57+
fmt.Println("No releases found")
58+
return nil
59+
}
60+
61+
// Compare versions (skip comparison for dev builds - always offer upgrade)
62+
if Version != "dev" {
63+
if latest.LessOrEqual(Version) {
64+
fmt.Printf("Already up to date (latest: %s)\n", latest.Version())
65+
return nil
66+
}
67+
} else {
68+
fmt.Println("Running development build")
69+
}
70+
71+
// Download and install
72+
fmt.Printf("New version available: %s\n", latest.Version())
73+
fmt.Printf("Downloading for %s/%s...\n", runtime.GOOS, runtime.GOARCH)
74+
75+
exe, err := selfupdate.ExecutablePath()
76+
if err != nil {
77+
return fmt.Errorf("failed to get executable path: %w", err)
78+
}
79+
80+
if err := updater.UpdateTo(context.Background(), latest, exe); err != nil {
81+
return fmt.Errorf("failed to update: %w", err)
82+
}
83+
84+
fmt.Printf("Successfully upgraded to %s\n", latest.Version())
85+
return nil
86+
}

cmd/version.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"runtime"
6+
7+
"github.com/spf13/cobra"
8+
)
9+
10+
var versionCmd = &cobra.Command{
11+
Use: "version",
12+
Short: "Print version information",
13+
Long: "Display the current version, build information, and platform details",
14+
Run: func(cmd *cobra.Command, args []string) {
15+
fmt.Printf("beeper-api-cli version %s\n", Version)
16+
fmt.Printf(" Go version: %s\n", runtime.Version())
17+
fmt.Printf(" OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH)
18+
},
19+
}
20+
21+
func init() {
22+
rootCmd.AddCommand(versionCmd)
23+
}

go.mod

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,42 @@ module github.com/nerveband/beeper-api-cli
33
go 1.25.6
44

55
require (
6+
github.com/creativeprojects/go-selfupdate v1.5.2
7+
github.com/spf13/cobra v1.10.2
8+
github.com/spf13/viper v1.21.0
9+
github.com/stretchr/testify v1.11.1
10+
)
11+
12+
require (
13+
code.gitea.io/sdk/gitea v0.22.1 // indirect
14+
github.com/42wim/httpsig v1.2.3 // indirect
15+
github.com/Masterminds/semver/v3 v3.4.0 // indirect
616
github.com/davecgh/go-spew v1.1.1 // indirect
17+
github.com/davidmz/go-pageant v1.0.2 // indirect
718
github.com/fsnotify/fsnotify v1.9.0 // indirect
19+
github.com/go-fed/httpsig v1.1.0 // indirect
820
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
21+
github.com/google/go-github/v74 v74.0.0 // indirect
22+
github.com/google/go-querystring v1.1.0 // indirect
23+
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
24+
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
25+
github.com/hashicorp/go-version v1.8.0 // indirect
926
github.com/inconshreveable/mousetrap v1.1.0 // indirect
1027
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
1128
github.com/pmezard/go-difflib v1.0.0 // indirect
1229
github.com/sagikazarmark/locafero v0.11.0 // indirect
1330
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
1431
github.com/spf13/afero v1.15.0 // indirect
1532
github.com/spf13/cast v1.10.0 // indirect
16-
github.com/spf13/cobra v1.10.2 // indirect
1733
github.com/spf13/pflag v1.0.10 // indirect
18-
github.com/spf13/viper v1.21.0 // indirect
19-
github.com/stretchr/testify v1.11.1 // indirect
2034
github.com/subosito/gotenv v1.6.0 // indirect
35+
github.com/ulikunitz/xz v0.5.15 // indirect
36+
gitlab.com/gitlab-org/api/client-go v1.9.1 // indirect
2137
go.yaml.in/yaml/v3 v3.0.4 // indirect
22-
golang.org/x/sys v0.29.0 // indirect
23-
golang.org/x/text v0.28.0 // indirect
38+
golang.org/x/crypto v0.46.0 // indirect
39+
golang.org/x/oauth2 v0.34.0 // indirect
40+
golang.org/x/sys v0.39.0 // indirect
41+
golang.org/x/text v0.32.0 // indirect
42+
golang.org/x/time v0.14.0 // indirect
2443
gopkg.in/yaml.v3 v3.0.1 // indirect
2544
)

go.sum

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,57 @@
1+
code.gitea.io/sdk/gitea v0.22.1 h1:7K05KjRORyTcTYULQ/AwvlVS6pawLcWyXZcTr7gHFyA=
2+
code.gitea.io/sdk/gitea v0.22.1/go.mod h1:yyF5+GhljqvA30sRDreoyHILruNiy4ASufugzYg0VHM=
3+
github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs=
4+
github.com/42wim/httpsig v1.2.3/go.mod h1:nZq9OlYKDrUBhptd77IHx4/sZZD+IxTBADvAPI9G/EM=
5+
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
6+
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
17
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
8+
github.com/creativeprojects/go-selfupdate v1.5.2 h1:3KR3JLrq70oplb9yZzbmJ89qRP78D1AN/9u+l3k0LJ4=
9+
github.com/creativeprojects/go-selfupdate v1.5.2/go.mod h1:BCOuwIl1dRRCmPNRPH0amULeZqayhKyY2mH/h4va7Dk=
210
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
311
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12+
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
13+
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
14+
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
15+
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
16+
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
17+
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
418
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
519
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
20+
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
21+
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
622
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
723
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
24+
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
25+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
26+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
27+
github.com/google/go-github/v74 v74.0.0 h1:yZcddTUn8DPbj11GxnMrNiAnXH14gNs559AsUpNpPgM=
28+
github.com/google/go-github/v74 v74.0.0/go.mod h1:ubn/YdyftV80VPSI26nSJvaEsTOnsjrxG3o9kJhcyak=
29+
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
30+
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
31+
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
32+
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
33+
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
34+
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
35+
github.com/hashicorp/go-retryablehttp v0.7.8 h1:ylXZWnqa7Lhqpk0L1P1LzDtGcCR0rPVUrx/c8Unxc48=
36+
github.com/hashicorp/go-retryablehttp v0.7.8/go.mod h1:rjiScheydd+CxvumBsIrFKlx3iS0jrZ7LvzFGFmuKbw=
37+
github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4=
38+
github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
839
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
940
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
41+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
42+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
43+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
44+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
45+
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
46+
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
47+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
48+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
1049
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
1150
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
1251
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1352
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
53+
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
54+
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
1455
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
1556
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
1657
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
@@ -31,12 +72,39 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
3172
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
3273
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
3374
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
75+
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
76+
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
77+
gitlab.com/gitlab-org/api/client-go v1.9.1 h1:tZm+URa36sVy8UCEHQyGGJ8COngV4YqMHpM6k9O5tK8=
78+
gitlab.com/gitlab-org/api/client-go v1.9.1/go.mod h1:71yTJk1lnHCWcZLvM5kPAXzeJ2fn5GjaoV8gTOPd4ME=
3479
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
3580
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
36-
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
37-
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
38-
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
39-
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
81+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
82+
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
83+
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
84+
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
85+
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
86+
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
87+
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
88+
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
89+
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
90+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
91+
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
92+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
93+
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
94+
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
95+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
96+
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
97+
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
98+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
99+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
100+
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
101+
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
102+
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
103+
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
104+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
105+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
40106
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
107+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
108+
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
41109
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
42110
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/api/client.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ func (c *Client) SendMessage(chatID, message string) (string, error) {
167167
return resp.ID, nil
168168
}
169169

170+
// SearchResponse represents the API response for searching messages
171+
type SearchResponse struct {
172+
Items []Message `json:"items"`
173+
}
174+
170175
// SearchMessages searches for messages across all chats
171176
func (c *Client) SearchMessages(query string, limit int) ([]Message, error) {
172177
path := fmt.Sprintf("/v1/messages/search?q=%s&limit=%d", query, limit)
@@ -175,12 +180,12 @@ func (c *Client) SearchMessages(query string, limit int) ([]Message, error) {
175180
return nil, err
176181
}
177182

178-
var messages []Message
179-
if err := json.Unmarshal(data, &messages); err != nil {
183+
var resp SearchResponse
184+
if err := json.Unmarshal(data, &resp); err != nil {
180185
return nil, fmt.Errorf("failed to unmarshal messages: %w", err)
181186
}
182187

183-
return messages, nil
188+
return resp.Items, nil
184189
}
185190

186191
// DiscoverAPI attempts to auto-discover the Beeper Desktop API URL

0 commit comments

Comments
 (0)