Skip to content

Commit d4f9e0c

Browse files
author
Peter Steinberger
committed
fix(chat): normalize threads
1 parent 405d6cb commit d4f9e0c

5 files changed

Lines changed: 57 additions & 8 deletions

File tree

internal/cmd/chat_dm.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ func (c *ChatDMSendCmd) Run(ctx context.Context, flags *RootFlags) error {
5656
message := &chat.Message{Text: text}
5757
thread := strings.TrimSpace(c.Thread)
5858
if thread != "" {
59-
message.Thread = &chat.Thread{Name: thread}
59+
threadName, err := normalizeThread(space.Name, thread)
60+
if err != nil {
61+
return usage(fmt.Sprintf("invalid thread: %v", err))
62+
}
63+
message.Thread = &chat.Thread{Name: threadName}
6064
}
6165

6266
call := svc.Spaces.Messages.Create(space.Name, message)

internal/cmd/chat_helpers.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,30 @@ func normalizeUser(resource string) string {
3333
return "users/" + user
3434
}
3535

36+
func normalizeThread(space, resource string) (string, error) {
37+
thread := strings.TrimSpace(resource)
38+
if thread == "" {
39+
return "", fmt.Errorf("empty thread")
40+
}
41+
if strings.HasPrefix(thread, "spaces/") {
42+
if !strings.Contains(thread, "/threads/") {
43+
return "", fmt.Errorf("invalid thread resource %q", thread)
44+
}
45+
return thread, nil
46+
}
47+
if strings.HasPrefix(thread, "threads/") {
48+
thread = strings.TrimPrefix(thread, "threads/")
49+
}
50+
if strings.Contains(thread, "/") {
51+
return "", fmt.Errorf("invalid thread id %q", thread)
52+
}
53+
space, err := normalizeSpace(space)
54+
if err != nil {
55+
return "", err
56+
}
57+
return fmt.Sprintf("%s/threads/%s", space, thread), nil
58+
}
59+
3660
func parseCommaArgs(values []string) []string {
3761
out := make([]string, 0, len(values))
3862
for _, raw := range values {

internal/cmd/chat_messages.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ func (c *ChatMessagesListCmd) Run(ctx context.Context, flags *RootFlags) error {
4646
filters := make([]string, 0, 2)
4747
thread := strings.TrimSpace(c.Thread)
4848
if thread != "" {
49-
filters = append(filters, fmt.Sprintf("thread.name = \"%s\"", thread))
49+
threadName, err := normalizeThread(space, thread)
50+
if err != nil {
51+
return usage(fmt.Sprintf("invalid thread: %v", err))
52+
}
53+
filters = append(filters, fmt.Sprintf("thread.name = \"%s\"", threadName))
5054
}
5155
if c.Unread {
5256
readState, readErr := svc.Users.Spaces.GetSpaceReadState(fmt.Sprintf("users/me/spaces/%s/spaceReadState", spaceID(space))).Do()
@@ -155,7 +159,11 @@ func (c *ChatMessagesSendCmd) Run(ctx context.Context, flags *RootFlags) error {
155159
message := &chat.Message{Text: text}
156160
thread := strings.TrimSpace(c.Thread)
157161
if thread != "" {
158-
message.Thread = &chat.Thread{Name: thread}
162+
threadName, err := normalizeThread(space, thread)
163+
if err != nil {
164+
return usage(fmt.Sprintf("invalid thread: %v", err))
165+
}
166+
message.Thread = &chat.Thread{Name: threadName}
159167
}
160168

161169
call := svc.Spaces.Messages.Create(space, message)

internal/cmd/chat_spaces.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,16 @@ func (c *ChatSpacesCreateCmd) Run(ctx context.Context, flags *RootFlags) error {
219219
})
220220
}
221221

222-
resp, err := svc.Spaces.Setup(&chat.SetUpSpaceRequest{
222+
req := &chat.SetUpSpaceRequest{
223223
Space: &chat.Space{
224224
SpaceType: "SPACE",
225225
DisplayName: displayName,
226226
},
227-
Memberships: memberships,
228-
}).Do()
227+
}
228+
if len(memberships) > 0 {
229+
req.Memberships = memberships
230+
}
231+
resp, err := svc.Spaces.Setup(req).Do()
229232
if err != nil {
230233
return err
231234
}

internal/cmd/execute_chat_test.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ func TestExecute_ChatMessagesList_Text_Unread(t *testing.T) {
232232

233233
out := captureStdout(t, func() {
234234
errOut := captureStderr(t, func() {
235-
if err := Execute([]string{"--account", "a@b.com", "chat", "messages", "list", "spaces/aaa", "--unread"}); err != nil {
235+
if err := Execute([]string{"--account", "a@b.com", "chat", "messages", "list", "spaces/aaa", "--unread", "--thread", "t1"}); err != nil {
236236
t.Fatalf("Execute: %v", err)
237237
}
238238
})
@@ -246,13 +246,17 @@ func TestExecute_ChatMessagesList_Text_Unread(t *testing.T) {
246246
if !strings.Contains(gotFilter, "createTime > \"2025-01-01T00:00:00Z\"") {
247247
t.Fatalf("unexpected filter: %q", gotFilter)
248248
}
249+
if !strings.Contains(gotFilter, "thread.name = \"spaces/aaa/threads/t1\"") {
250+
t.Fatalf("unexpected thread filter: %q", gotFilter)
251+
}
249252
}
250253

251254
func TestExecute_ChatMessagesSend_JSON(t *testing.T) {
252255
origNew := newChatService
253256
t.Cleanup(func() { newChatService = origNew })
254257

255258
var gotText string
259+
var gotThread string
256260

257261
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
258262
if !(r.Method == http.MethodPost && strings.Contains(r.URL.Path, "/messages")) {
@@ -262,6 +266,9 @@ func TestExecute_ChatMessagesSend_JSON(t *testing.T) {
262266
var body map[string]any
263267
_ = json.NewDecoder(r.Body).Decode(&body)
264268
gotText, _ = body["text"].(string)
269+
if thread, ok := body["thread"].(map[string]any); ok {
270+
gotThread, _ = thread["name"].(string)
271+
}
265272

266273
w.Header().Set("Content-Type", "application/json")
267274
_ = json.NewEncoder(w).Encode(map[string]any{
@@ -282,14 +289,17 @@ func TestExecute_ChatMessagesSend_JSON(t *testing.T) {
282289

283290
out := captureStdout(t, func() {
284291
_ = captureStderr(t, func() {
285-
if err := Execute([]string{"--json", "--account", "a@b.com", "chat", "messages", "send", "spaces/aaa", "--text", "hello"}); err != nil {
292+
if err := Execute([]string{"--json", "--account", "a@b.com", "chat", "messages", "send", "spaces/aaa", "--text", "hello", "--thread", "t1"}); err != nil {
286293
t.Fatalf("Execute: %v", err)
287294
}
288295
})
289296
})
290297
if gotText != "hello" {
291298
t.Fatalf("unexpected text: %q", gotText)
292299
}
300+
if gotThread != "spaces/aaa/threads/t1" {
301+
t.Fatalf("unexpected thread: %q", gotThread)
302+
}
293303
if !strings.Contains(out, "spaces/aaa/messages/msg2") {
294304
t.Fatalf("unexpected out=%q", out)
295305
}

0 commit comments

Comments
 (0)