picoclaw/pkg/channels/telegram/typing.go
google-labs-jules[bot] d0cc46aae7 refactor(telegram): modularize monolithic telegram.go into domain-specific files
This change breaks down the large `pkg/channels/telegram/telegram.go` file
into several smaller, specialized files:
- events.go: Inbound message handling
- messages.go: Outbound text messaging
- media.go: Media operations (sending and downloading)
- parsing.go: Markdown-to-HTML formatting
- typing.go: Typing indicator logic
- utils.go: Helpers (ID parsing, mention checking)

The core struct and lifecycle methods remain in `telegram.go`.
All functionality and tests are preserved.

Co-authored-by: hobbyistlabs-coder <267281733+hobbyistlabs-coder@users.noreply.github.com>
2026-03-26 22:18:14 +00:00

44 lines
1.1 KiB
Go

package telegram
import (
"context"
"time"
"github.com/mymmrac/telego"
tu "github.com/mymmrac/telego/telegoutil"
)
// StartTyping implements channels.TypingCapable.
// It sends ChatAction(typing) immediately and then repeats every 4 seconds
// (Telegram's typing indicator expires after ~5s) in a background goroutine.
// The returned stop function is idempotent and cancels the goroutine.
func (c *TelegramChannel) StartTyping(ctx context.Context, chatID string) (func(), error) {
cid, threadID, err := parseTelegramChatID(chatID)
if err != nil {
return func() {}, err
}
action := tu.ChatAction(tu.ID(cid), telego.ChatActionTyping)
action.MessageThreadID = threadID
// Send the first typing action immediately
_ = c.bot.SendChatAction(ctx, action)
typingCtx, cancel := context.WithCancel(ctx)
go func() {
ticker := time.NewTicker(4 * time.Second)
defer ticker.Stop()
for {
select {
case <-typingCtx.Done():
return
case <-ticker.C:
a := tu.ChatAction(tu.ID(cid), telego.ChatActionTyping)
a.MessageThreadID = threadID
_ = c.bot.SendChatAction(typingCtx, a)
}
}
}()
return cancel, nil
}