Merge upstream changes
This commit is contained in:
parent
b5d6fbe6ab
commit
42314b495a
3 changed files with 52 additions and 44 deletions
|
|
@ -33,7 +33,8 @@
|
|||
"Bash(golangci-lint run:*)",
|
||||
"WebFetch(domain:core.telegram.org)",
|
||||
"Bash(go doc:*)",
|
||||
"Bash(go install:*)"
|
||||
"Bash(go install:*)",
|
||||
"WebFetch(domain:raw.githubusercontent.com)"
|
||||
]
|
||||
},
|
||||
"remote": {
|
||||
|
|
|
|||
|
|
@ -633,26 +633,43 @@ func (m *Manager) handleTaskStatusSend(ctx context.Context, name string, w *chan
|
|||
|
||||
taskKey := taskStatusKey(name, msg.ChatID, msg.TaskID)
|
||||
|
||||
// Final message: send as permanent (non-draft) message so it persists.
|
||||
// Drafts are ephemeral and disappear after a short time; the completion
|
||||
// message must survive. Clear the draft tracking and send via SendWithID
|
||||
// or regular Send, which creates a permanent Telegram message.
|
||||
// Final message: reuse the existing bubble when possible to avoid
|
||||
// duplicate messages. If a permanent message (messageID) is tracked,
|
||||
// edit it in-place. If a draft (draftID) is tracked, update it with
|
||||
// the completion content (the draft persists in Telegram and serves
|
||||
// as the visible message; sending a separate permanent message would
|
||||
// create a duplicate).
|
||||
if msg.Final {
|
||||
if v, loaded := m.taskMsgIDs.LoadAndDelete(taskKey); loaded {
|
||||
if entry, ok := v.(statusMsgEntry); ok && entry.draftID != 0 {
|
||||
if drafter, ok := w.ch.(DraftSender); ok {
|
||||
if err := drafter.SendDraft(ctx, msg.ChatID, entry.draftID, ""); err != nil {
|
||||
logger.WarnCF("channels", "Failed to dismiss task draft before final message", map[string]any{
|
||||
"task_id": taskKey,
|
||||
"chat_id": msg.ChatID,
|
||||
"draft_id": entry.draftID,
|
||||
"error": err.Error(),
|
||||
})
|
||||
v, loaded := m.taskMsgIDs.LoadAndDelete(taskKey)
|
||||
m.statusEditTimes.Delete(taskKey)
|
||||
|
||||
if loaded {
|
||||
if entry, ok := v.(statusMsgEntry); ok {
|
||||
// Path A: a permanent message exists — edit it in-place.
|
||||
if entry.messageID != "" {
|
||||
if editor, ok := w.ch.(MessageEditor); ok {
|
||||
if err := editor.EditMessage(ctx, msg.ChatID, entry.messageID, msg.Content); err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
// Edit failed — fall through to send a new message.
|
||||
}
|
||||
|
||||
// Path B: a draft exists — update it with the final
|
||||
// content. Drafts persist visibly in Telegram, so do NOT
|
||||
// send a separate permanent message (that causes duplicates).
|
||||
if entry.draftID != 0 {
|
||||
if drafter, ok := w.ch.(DraftSender); ok {
|
||||
if err := drafter.SendDraft(ctx, msg.ChatID, entry.draftID, msg.Content); err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
// Draft update failed — fall through to send permanent.
|
||||
}
|
||||
}
|
||||
}
|
||||
m.statusEditTimes.Delete(taskKey)
|
||||
|
||||
// No existing bubble to reuse — send a new permanent message.
|
||||
if sender, ok := w.ch.(MessageSenderWithID); ok {
|
||||
if msgID, err := sender.SendWithID(ctx, msg.ChatID, msg.Content); err == nil && msgID != "" {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -1439,39 +1439,32 @@ func TestHandleTaskStatusSend_UsesDraftSender(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestHandleTaskStatusSend_Final_DismissesDraftBeforePermanentMessage(t *testing.T) {
|
||||
func TestHandleTaskStatusSend_Final_UpdatesDraftInPlace(t *testing.T) {
|
||||
m := newTestManager()
|
||||
var dismissCalled bool
|
||||
var dismissDraftID int
|
||||
var dismissContent string
|
||||
var finalSendWithIDCalled bool
|
||||
var draftUpdateCalled bool
|
||||
var draftUpdateDraftID int
|
||||
var draftUpdateContent string
|
||||
|
||||
ch := &mockDraftSender{
|
||||
mockChannel: mockChannel{
|
||||
sendFn: func(_ context.Context, _ bus.OutboundMessage) error {
|
||||
t.Fatal("Send should not be called when SendWithID succeeds")
|
||||
t.Fatal("Send should not be called when draft update succeeds")
|
||||
return nil
|
||||
},
|
||||
},
|
||||
draftFn: func(_ context.Context, chatID string, draftID int, content string) error {
|
||||
dismissCalled = true
|
||||
dismissDraftID = draftID
|
||||
dismissContent = content
|
||||
draftUpdateCalled = true
|
||||
draftUpdateDraftID = draftID
|
||||
draftUpdateContent = content
|
||||
if chatID != "123" {
|
||||
t.Fatalf("expected dismiss chatID 123, got %s", chatID)
|
||||
t.Fatalf("expected chatID 123, got %s", chatID)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
editFn: func(_ context.Context, _, _, _ string) error { return nil },
|
||||
sendWithID: func(_ context.Context, chatID, content string) (string, error) {
|
||||
finalSendWithIDCalled = true
|
||||
if chatID != "123" {
|
||||
t.Fatalf("expected final chatID 123, got %s", chatID)
|
||||
}
|
||||
if content != "task completed" {
|
||||
t.Fatalf("expected final content 'task completed', got %s", content)
|
||||
}
|
||||
return "task-final-1", nil
|
||||
sendWithID: func(_ context.Context, _, _ string) (string, error) {
|
||||
t.Fatal("SendWithID should not be called when draft update succeeds")
|
||||
return "", nil
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -1490,17 +1483,14 @@ func TestHandleTaskStatusSend_Final_DismissesDraftBeforePermanentMessage(t *test
|
|||
}
|
||||
m.handleTaskStatusSend(context.Background(), "test", w, msg)
|
||||
|
||||
if !dismissCalled {
|
||||
t.Fatal("expected SendDraft dismiss call for final task status")
|
||||
if !draftUpdateCalled {
|
||||
t.Fatal("expected SendDraft to update draft with final content")
|
||||
}
|
||||
if dismissDraftID != 42 {
|
||||
t.Fatalf("expected dismiss draftID 42, got %d", dismissDraftID)
|
||||
if draftUpdateDraftID != 42 {
|
||||
t.Fatalf("expected draftID 42, got %d", draftUpdateDraftID)
|
||||
}
|
||||
if dismissContent != "" {
|
||||
t.Fatalf("expected empty dismiss content, got %q", dismissContent)
|
||||
}
|
||||
if !finalSendWithIDCalled {
|
||||
t.Fatal("expected final SendWithID to be called")
|
||||
if draftUpdateContent != "task completed" {
|
||||
t.Fatalf("expected draft content 'task completed', got %q", draftUpdateContent)
|
||||
}
|
||||
if _, loaded := m.taskMsgIDs.Load(taskStatusKey("test", "123", "task-final")); loaded {
|
||||
t.Fatal("expected taskMsgIDs entry to be deleted for final task status")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue