summaryrefslogtreecommitdiffstats
path: root/tools/notes/notes.go
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-09-30 21:50:36 -0700
committerRose Hogenson <rosehogenson@posteo.net>2025-09-30 21:50:36 -0700
commitc2ca26a918b7054199234e8459d84ee2fd260759 (patch)
treea44f8dad1ca70eb25d4dc12bf17e136fd0711e04 /tools/notes/notes.go
parented285a247a3a967e02f428fa2b6e69d629e2bd14 (diff)
downloadroseh.moe-c2ca26a918b7054199234e8459d84ee2fd260759.tar.zst
Allow appending to notes
Right now it's n^2 which is a big problem (to be fixed later)
Diffstat (limited to 'tools/notes/notes.go')
-rw-r--r--tools/notes/notes.go108
1 files changed, 59 insertions, 49 deletions
diff --git a/tools/notes/notes.go b/tools/notes/notes.go
index adc7e6a..2b03694 100644
--- a/tools/notes/notes.go
+++ b/tools/notes/notes.go
@@ -35,7 +35,7 @@ func readGobResp[Response any](req *http.Request) (*Response, error) {
return nil, fmt.Errorf("read gob response: decode response: %s", err)
}
if apiResp.Status != api.Ok {
- return nil, fmt.Errorf("read gob response: api error: %s", apiResp.Err)
+ return nil, fmt.Errorf("read gob response: api error: %s: %s", apiResp.Status, apiResp.Err)
}
resp, ok := apiResp.Ok.(*Response)
if !ok {
@@ -44,23 +44,19 @@ func readGobResp[Response any](req *http.Request) (*Response, error) {
return resp, nil
}
-func login(ctx context.Context) (string, error) {
+func login(ctx context.Context) (*api.LoginResponse, error) {
fmt.Print("Enter password:")
password, err := term.ReadPassword(int(os.Stdin.Fd()))
fmt.Println()
if err != nil {
- return "", err
+ return nil, err
}
req, err := http.NewRequestWithContext(ctx, "POST", *serverURL+"/api/login", nil)
if err != nil {
- return "", err
+ return nil, err
}
req.Header.Set("Roseh-Password", string(password))
- resp, err := readGobResp[api.LoginResponse](req)
- if err != nil {
- return "", err
- }
- return resp.Token, nil
+ return readGobResp[api.LoginResponse](req)
}
func loadToken(ctx context.Context) (string, error) {
@@ -71,8 +67,8 @@ func loadToken(ctx context.Context) (string, error) {
if err != nil {
return "", err
}
- os.WriteFile(tokenCache, []byte(token), 0600)
- return token, nil
+ os.WriteFile(tokenCache, []byte(token.Token), 0600)
+ return token.Token, nil
}
return "", err
}
@@ -96,6 +92,39 @@ func gobReq(ctx context.Context, method, url string, req any) (*http.Request, er
return httpReq, nil
}
+func gobReqResp[Response any](ctx context.Context, method, url string, req any) (*Response, error) {
+ httpReq, err := gobReq(ctx, method, url, req)
+ if err != nil {
+ return nil, err
+ }
+ return readGobResp[Response](httpReq)
+}
+
+func listNotes(ctx context.Context, req *api.ListNotesRequest) (*api.ListNotesResponse, error) {
+ return gobReqResp[api.ListNotesResponse](ctx, "GET", *serverURL+"/api/list-notes", req)
+}
+
+func createNote(ctx context.Context, req *api.CreateNoteRequest) (*api.CreateNoteResponse, error) {
+ return gobReqResp[api.CreateNoteResponse](ctx, "POST", *serverURL+"/api/create-note", req)
+}
+
+func readNote(ctx context.Context, req *api.ReadNoteRequest) (*gob.Decoder, func() error, error) {
+ httpReq, err := gobReq(ctx, "GET", *serverURL+"/api/read-note", req)
+ if err != nil {
+ return nil, nil, err
+ }
+ resp, err := http.DefaultClient.Do(httpReq)
+ if err != nil {
+ return nil, nil, err
+ }
+ if resp.StatusCode != http.StatusOK {
+ body, _ := io.ReadAll(resp.Body)
+ resp.Body.Close()
+ return nil, nil, fmt.Errorf("error status: %s\n%s", resp.Status, body)
+ }
+ return gob.NewDecoder(resp.Body), resp.Body.Close, nil
+}
+
type loginCommand struct{}
func (*loginCommand) Name() string {
@@ -117,7 +146,7 @@ func (*loginCommand) login(ctx context.Context) error {
if err != nil {
return err
}
- return os.WriteFile(tokenCache, []byte(token), 0600)
+ return os.WriteFile(tokenCache, []byte(token.Token), 0600)
}
func (c *loginCommand) Execute(ctx context.Context, _ *flag.FlagSet, _ ...any) subcommands.ExitStatus {
@@ -145,11 +174,7 @@ func (*listCommand) Usage() string {
func (*listCommand) SetFlags(*flag.FlagSet) {}
func (*listCommand) list(ctx context.Context) error {
- req, err := gobReq(ctx, "GET", *serverURL+"/api/list-notes", &api.ListNotesRequest{})
- if err != nil {
- return err
- }
- resp, err := readGobResp[api.ListNotesResponse](req)
+ resp, err := listNotes(ctx, &api.ListNotesRequest{})
if err != nil {
return err
}
@@ -184,13 +209,21 @@ func (*newCommand) Usage() string {
func (*newCommand) SetFlags(*flag.FlagSet) {}
type createNoteRequestStreamWriter struct {
- w *gob.Encoder
+ ctx context.Context
+ continuationToken []byte
+ name string
}
func (w *createNoteRequestStreamWriter) Write(buf []byte) (int, error) {
- if err := w.w.Encode(&api.CreateNoteRequestStream{Chunk: buf}); err != nil {
+ resp, err := createNote(w.ctx, &api.CreateNoteRequest{
+ ContinuationToken: w.continuationToken,
+ Chunk: buf,
+ })
+ if err != nil {
return 0, err
}
+ w.continuationToken = resp.ContinuationToken
+ w.name = resp.Name
return len(buf), nil
}
@@ -200,25 +233,11 @@ func (*newCommand) new(ctx context.Context, fileName string) error {
return err
}
defer f.Close()
- r, w := io.Pipe()
- req, err := http.NewRequestWithContext(ctx, "POST", *serverURL+"/api/create-note", r)
- if err != nil {
- return fmt.Errorf("request: %s", err)
- }
- token, err := loadToken(ctx)
- if err != nil {
- return fmt.Errorf("token: %s", err)
- }
- req.Header.Set("Roseh-Token", token)
- go func() {
- io.Copy(&createNoteRequestStreamWriter{gob.NewEncoder(w)}, f)
- w.Close()
- }()
- resp, err := readGobResp[api.CreateNoteResponse](req)
- if err != nil {
- return fmt.Errorf("req: %s", err)
+ streamWriter := &createNoteRequestStreamWriter{ctx: ctx}
+ if _, err := io.Copy(streamWriter, f); err != nil {
+ return err
}
- fmt.Println(resp.Name)
+ fmt.Println(streamWriter.name)
return nil
}
@@ -252,20 +271,11 @@ func (*readCommand) Usage() string {
func (*readCommand) SetFlags(*flag.FlagSet) {}
func (*readCommand) read(ctx context.Context, key string) error {
- req, err := gobReq(ctx, "GET", *serverURL+"/api/read-note", &api.ReadNoteRequest{Note: key})
+ decoder, close, err := readNote(ctx, &api.ReadNoteRequest{Note: key})
if err != nil {
return err
}
- resp, err := http.DefaultClient.Do(req)
- if err != nil {
- return fmt.Errorf("http: %s", err)
- }
- defer resp.Body.Close()
- if resp.StatusCode != http.StatusOK {
- body, _ := io.ReadAll(resp.Body)
- return fmt.Errorf("error status: %s\n%s", resp.Status, body)
- }
- decoder := gob.NewDecoder(resp.Body)
+ defer close()
for {
apiResp := new(api.Response)
if err := decoder.Decode(apiResp); err != nil {
@@ -275,7 +285,7 @@ func (*readCommand) read(ctx context.Context, key string) error {
return err
}
if apiResp.Status != api.Ok {
- return fmt.Errorf("api error: %s", apiResp.Err)
+ return fmt.Errorf("%s: %s", apiResp.Status, apiResp.Err)
}
resp, ok := apiResp.Ok.(*api.ReadNoteResponseStream)
if !ok {