From 4aa6ffb0433f7a49a373406bc84bda9050341118 Mon Sep 17 00:00:00 2001 From: Roman Stolyarchuk Date: Sun, 10 May 2026 08:53:42 +0300 Subject: [PATCH] feat(telegram): mark business messages as read and add tests for handling - Implement markBusinessMessageRead function to mark messages as read - Add tests for successful message read and failure scenarios --- pkg/channels/telegram/telegram.go | 24 ++++++++ pkg/channels/telegram/telegram_test.go | 84 ++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/pkg/channels/telegram/telegram.go b/pkg/channels/telegram/telegram.go index 707dcdbaa..85ca25142 100644 --- a/pkg/channels/telegram/telegram.go +++ b/pkg/channels/telegram/telegram.go @@ -787,9 +787,33 @@ func (c *TelegramChannel) handleBusinessMessage(ctx context.Context, message *te if businessConnectionID == "" { return fmt.Errorf("business message missing business_connection_id") } + c.markBusinessMessageRead(ctx, businessConnectionID, message.Chat.ID, message.MessageID) return c.handleTelegramMessage(ctx, message, businessConnectionID) } +func (c *TelegramChannel) markBusinessMessageRead( + ctx context.Context, + businessConnectionID string, + chatID int64, + messageID int, +) { + if c == nil || c.bot == nil || strings.TrimSpace(businessConnectionID) == "" || chatID == 0 || messageID == 0 { + return + } + if err := c.bot.ReadBusinessMessage(ctx, &telego.ReadBusinessMessageParams{ + BusinessConnectionID: businessConnectionID, + ChatID: chatID, + MessageID: messageID, + }); err != nil { + logger.DebugCF("telegram", "Failed to mark business message as read", map[string]any{ + "business_connection_id": businessConnectionID, + "chat_id": chatID, + "message_id": messageID, + "error": err.Error(), + }) + } +} + func (c *TelegramChannel) handleBusinessConnection(_ context.Context, connection telego.BusinessConnection) error { if !c.businessModeEnabled() { return nil diff --git a/pkg/channels/telegram/telegram_test.go b/pkg/channels/telegram/telegram_test.go index 1393312ad..a70d55c0b 100644 --- a/pkg/channels/telegram/telegram_test.go +++ b/pkg/channels/telegram/telegram_test.go @@ -150,6 +150,90 @@ func newTestChannelWithConstructor( } } +func TestHandleBusinessMessage_MarksMessageRead(t *testing.T) { + messageBus := bus.NewMessageBus() + caller := &stubCaller{ + callFn: func(ctx context.Context, url string, data *ta.RequestData) (*ta.Response, error) { + if !strings.Contains(url, "readBusinessMessage") { + t.Fatalf("unexpected API call: %s", url) + } + b, err := json.Marshal(true) + require.NoError(t, err) + return &ta.Response{Ok: true, Result: b}, nil + }, + } + ch := newTestChannel(t, caller) + ch.BaseChannel = channels.NewBaseChannel("telegram", nil, messageBus, nil) + ch.BaseChannel.SetOwner(ch) + ch.ctx = context.Background() + ch.tgCfg.BusinessMode = true + + msg := &telego.Message{ + Text: "hello from business", + MessageID: 17, + BusinessConnectionID: "biz-conn-1", + Chat: telego.Chat{ + ID: 777, + Type: "private", + }, + From: &telego.User{ + ID: 42, + FirstName: "Alice", + }, + } + + require.NoError(t, ch.handleBusinessMessage(context.Background(), msg)) + require.Len(t, caller.calls, 1) + assert.Contains(t, caller.calls[0].URL, "readBusinessMessage") + + var params struct { + BusinessConnectionID string `json:"business_connection_id"` + ChatID int64 `json:"chat_id"` + MessageID int `json:"message_id"` + } + require.NoError(t, json.Unmarshal(caller.calls[0].Data.BodyRaw, ¶ms)) + assert.Equal(t, "biz-conn-1", params.BusinessConnectionID) + assert.Equal(t, int64(777), params.ChatID) + assert.Equal(t, 17, params.MessageID) + + inbound := <-messageBus.InboundChan() + assert.Equal(t, "hello from business", inbound.Content) +} + +func TestHandleBusinessMessage_ReadFailureStillForwardsMessage(t *testing.T) { + messageBus := bus.NewMessageBus() + caller := &stubCaller{ + callFn: func(ctx context.Context, url string, data *ta.RequestData) (*ta.Response, error) { + return nil, errors.New("missing can_read_messages") + }, + } + ch := newTestChannel(t, caller) + ch.BaseChannel = channels.NewBaseChannel("telegram", nil, messageBus, nil) + ch.BaseChannel.SetOwner(ch) + ch.ctx = context.Background() + ch.tgCfg.BusinessMode = true + + msg := &telego.Message{ + Text: "still forward me", + MessageID: 18, + BusinessConnectionID: "biz-conn-1", + Chat: telego.Chat{ + ID: 777, + Type: "private", + }, + From: &telego.User{ + ID: 42, + FirstName: "Alice", + }, + } + + require.NoError(t, ch.handleBusinessMessage(context.Background(), msg)) + require.Len(t, caller.calls, 1) + + inbound := <-messageBus.InboundChan() + assert.Equal(t, "still forward me", inbound.Content) +} + func TestSendMedia_ImageFallbacksToDocumentOnInvalidDimensions(t *testing.T) { constructor := &multipartRecordingConstructor{} caller := &stubCaller{