From e1f67f6da1ceb85bf16be5d4b309253c35835832 Mon Sep 17 00:00:00 2001 From: Virgil Date: Wed, 1 Apr 2026 23:07:59 +0000 Subject: [PATCH] feat(user): add avatar endpoints --- users.go | 10 ++++++++++ users_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/users.go b/users.go index 9cb36f3..9410985 100644 --- a/users.go +++ b/users.go @@ -58,6 +58,16 @@ func (s *UserService) DeleteEmails(ctx context.Context, emails ...string) error return s.client.DeleteWithBody(ctx, "/api/v1/user/emails", types.DeleteEmailOption{Emails: emails}) } +// UpdateAvatar updates the authenticated user's avatar. +func (s *UserService) UpdateAvatar(ctx context.Context, opts *types.UpdateUserAvatarOption) error { + return s.client.Post(ctx, "/api/v1/user/avatar", opts, nil) +} + +// DeleteAvatar deletes the authenticated user's avatar. +func (s *UserService) DeleteAvatar(ctx context.Context) error { + return s.client.Delete(ctx, "/api/v1/user/avatar") +} + // ListStopwatches returns all existing stopwatches for the authenticated user. func (s *UserService) ListStopwatches(ctx context.Context) ([]types.StopWatch, error) { return ListAll[types.StopWatch](ctx, s.client, "/api/v1/user/stopwatches", nil) diff --git a/users_test.go b/users_test.go index 29dc4de..3ad2e90 100644 --- a/users_test.go +++ b/users_test.go @@ -263,6 +263,49 @@ func TestUserService_DeleteEmails_Good(t *testing.T) { } } +func TestUserService_UpdateAvatar_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + t.Errorf("expected POST, got %s", r.Method) + } + if r.URL.Path != "/api/v1/user/avatar" { + t.Errorf("wrong path: %s", r.URL.Path) + } + var body types.UpdateUserAvatarOption + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + t.Fatal(err) + } + if body.Image != "aGVsbG8=" { + t.Fatalf("unexpected body: %+v", body) + } + w.WriteHeader(http.StatusNoContent) + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + if err := f.Users.UpdateAvatar(context.Background(), &types.UpdateUserAvatarOption{Image: "aGVsbG8="}); err != nil { + t.Fatal(err) + } +} + +func TestUserService_DeleteAvatar_Good(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodDelete { + t.Errorf("expected DELETE, got %s", r.Method) + } + if r.URL.Path != "/api/v1/user/avatar" { + t.Errorf("wrong path: %s", r.URL.Path) + } + w.WriteHeader(http.StatusNoContent) + })) + defer srv.Close() + + f := NewForge(srv.URL, "tok") + if err := f.Users.DeleteAvatar(context.Background()); err != nil { + t.Fatal(err) + } +} + func TestUserService_ListFollowers_Good(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet {