package telegram import ( "context" "fmt" "git.yeij.top/AskaEth/Cyrene_v2/internal/channel/adapter" ) // markdownParseMode is the parse_mode sent with outgoing text/captions so the // Markdown capability is actually exercised. const markdownParseMode = "Markdown" // SendMessage delivers the reply messages contained in resp to their target // chats. Each message goes to its own ChannelID (or GroupID) conversation. func (a *Adapter) SendMessage(ctx context.Context, resp adapter.UnifiedResponse) error { if err := a.requireConnected(); err != nil { return err } for _, m := range resp.Messages { if err := a.sendOne(ctx, m, resp.ReplyTo); err != nil { return fmt.Errorf("telegram: send message: %w", err) } } return nil } // SendProactive pushes a message not triggered by a recent inbound message. // Telegram permits arbitrary proactive push, so this is only gated by the // connection state. func (a *Adapter) SendProactive(ctx context.Context, msg adapter.UnifiedMessage) error { if err := a.requireConnected(); err != nil { return err } return a.sendOne(ctx, msg, "") } // sendOne delivers a single message to its conversation, choosing the Bot API // method that matches the content type and the presence of a file_id payload. func (a *Adapter) sendOne(ctx context.Context, m adapter.UnifiedMessage, replyTo string) error { chatID := m.ChannelID if chatID == "" { chatID = m.GroupID } if chatID == "" { return fmt.Errorf("telegram: %w", ErrNoChatTarget) } replyToID := parseReplyToID(replyTo) fileID := mediaFileID(m.Media) switch m.ContentType { case adapter.ContentImage: if fileID != "" { _, err := a.sendPhoto(ctx, chatID, fileID, replyToID, m.Content) return err } case adapter.ContentVoice: if fileID != "" { _, err := a.sendVoice(ctx, chatID, fileID, replyToID, m.Content) return err } case adapter.ContentFile: if fileID != "" { _, err := a.sendDocument(ctx, chatID, fileID, mediaFileName(m.Media), replyToID, m.Content) return err } } if m.Content == "" { return fmt.Errorf("telegram: %w: empty message content", ErrBadResponse) } _, err := a.sendMessage(ctx, chatID, m.Content, replyToID, markdownParseMode) return err } // mediaFileID returns the first non-empty file_id carried by the media list. func mediaFileID(media []adapter.Media) string { for _, md := range media { if md.URL != "" { return md.URL } } return "" } // mediaFileName returns the first non-empty file name carried by the media list. func mediaFileName(media []adapter.Media) string { for _, md := range media { if md.Name != "" { return md.Name } } return "" }