95 lines
2.6 KiB
Go
95 lines
2.6 KiB
Go
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 ""
|
|
}
|