mirror of
https://github.com/BEARlogin/max-telegram-bridge-bot.git
synced 2026-04-28 03:39:46 +00:00
Replace go-telegram-bot-api/v5 (2021, no forum topics) with go-telegram/bot v1.20.0 (Bot API 9.5) via TGSender adapter pattern. - New TGSender interface + tgBotSender implementation isolating library - Native message_thread_id support: saved at /bridge, used in MAX→TG sends, echoed in all command responses, looked up in queue retries - All 16 files migrated, zero old library references remain - Proper error wrapping: MigrateError, Forbidden, BadRequest, NotFound, TooManyRequests → TGError with codes - ForwardFromChat → ForwardOriginChat (Bot API MessageOrigin pattern) - Repository: GetTgThreadID/SetTgThreadID (migration 000012 already applied) - Tests for convertMsg, convertCallback, wrapErr, toInputFile, toLibInputMedia, tgEntitiesToMarkdown, maxMarkupsToHTML Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
198 lines
4.6 KiB
Go
198 lines
4.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
// --- Custom types for TG adapter ---
|
|
|
|
type ChatInfo struct {
|
|
ID int64
|
|
Type string
|
|
Title string
|
|
}
|
|
|
|
type UserInfo struct {
|
|
ID int64
|
|
IsBot bool
|
|
UserName string
|
|
FirstName string
|
|
LastName string
|
|
}
|
|
|
|
type PhotoSize struct {
|
|
FileID string
|
|
FileSize int
|
|
}
|
|
|
|
type FileInfo struct {
|
|
FileID string
|
|
FileName string
|
|
FileSize int
|
|
}
|
|
|
|
type DocInfo struct {
|
|
FileID string
|
|
FileName string
|
|
FileSize int
|
|
MimeType string
|
|
}
|
|
|
|
type AudioInfo struct {
|
|
FileID string
|
|
FileName string
|
|
FileSize int
|
|
}
|
|
|
|
type StickerInfo struct {
|
|
FileID string
|
|
FileSize int
|
|
IsAnimated bool
|
|
}
|
|
|
|
type Entity struct {
|
|
Type string
|
|
Offset int
|
|
Length int
|
|
URL string
|
|
}
|
|
|
|
type TGMessage struct {
|
|
MessageID int
|
|
MessageThreadID int
|
|
Chat ChatInfo
|
|
From *UserInfo
|
|
SenderChat *ChatInfo
|
|
Text string
|
|
Caption string
|
|
Photo []PhotoSize
|
|
Video *FileInfo
|
|
Document *DocInfo
|
|
Animation *FileInfo
|
|
Sticker *StickerInfo
|
|
Voice *FileInfo
|
|
Audio *AudioInfo
|
|
VideoNote *FileInfo
|
|
MediaGroupID string
|
|
ReplyToMessage *TGMessage
|
|
ForwardOriginChat *ChatInfo // replaces ForwardFromChat, from forward_origin
|
|
MigrateToChatID int64
|
|
Entities []Entity
|
|
CaptionEntities []Entity
|
|
}
|
|
|
|
type TGCallback struct {
|
|
ID string
|
|
From *UserInfo
|
|
Message *TGMessage
|
|
Data string
|
|
}
|
|
|
|
type TGUpdate struct {
|
|
Message *TGMessage
|
|
EditedMessage *TGMessage
|
|
ChannelPost *TGMessage
|
|
EditedChannelPost *TGMessage
|
|
CallbackQuery *TGCallback
|
|
}
|
|
|
|
// SendOpts — optional parameters for send methods.
|
|
type SendOpts struct {
|
|
ThreadID int
|
|
ReplyToID int
|
|
ParseMode string
|
|
Caption string
|
|
ReplyMarkup *InlineKeyboardMarkup
|
|
}
|
|
|
|
type InlineKeyboardMarkup struct {
|
|
Rows [][]InlineKeyboardButton
|
|
}
|
|
|
|
type InlineKeyboardButton struct {
|
|
Text string
|
|
CallbackData string
|
|
}
|
|
|
|
// FileArg — source for file upload: either Bytes (upload) or URL (send from URL).
|
|
type FileArg struct {
|
|
Name string
|
|
Bytes []byte
|
|
URL string
|
|
}
|
|
|
|
// TGInputMedia — item for media groups and edit-media.
|
|
type TGInputMedia struct {
|
|
Type string // "photo", "video", "audio", "document"
|
|
File FileArg
|
|
Caption string
|
|
ParseMode string
|
|
}
|
|
|
|
type BotCommand struct {
|
|
Command string
|
|
Description string
|
|
}
|
|
|
|
type CommandScope struct {
|
|
Type string // "", "all_chat_administrators"
|
|
}
|
|
|
|
// TGError represents a Telegram API error.
|
|
type TGError struct {
|
|
Code int
|
|
Description string
|
|
MigrateToChatID int64
|
|
}
|
|
|
|
func (e *TGError) Error() string {
|
|
return fmt.Sprintf("telegram: %s (%d)", e.Description, e.Code)
|
|
}
|
|
|
|
// --- Keyboard helpers ---
|
|
|
|
func NewInlineKeyboard(rows ...[]InlineKeyboardButton) *InlineKeyboardMarkup {
|
|
return &InlineKeyboardMarkup{Rows: rows}
|
|
}
|
|
|
|
func NewInlineRow(buttons ...InlineKeyboardButton) []InlineKeyboardButton {
|
|
return buttons
|
|
}
|
|
|
|
func NewInlineButton(text, data string) InlineKeyboardButton {
|
|
return InlineKeyboardButton{Text: text, CallbackData: data}
|
|
}
|
|
|
|
// --- Interface ---
|
|
|
|
// TGSender abstracts Telegram Bot API. All TG calls go through this interface.
|
|
type TGSender interface {
|
|
// Send methods return message ID.
|
|
SendMessage(ctx context.Context, chatID int64, text string, opts *SendOpts) (int, error)
|
|
SendPhoto(ctx context.Context, chatID int64, file FileArg, opts *SendOpts) (int, error)
|
|
SendVideo(ctx context.Context, chatID int64, file FileArg, opts *SendOpts) (int, error)
|
|
SendAudio(ctx context.Context, chatID int64, file FileArg, opts *SendOpts) (int, error)
|
|
SendDocument(ctx context.Context, chatID int64, file FileArg, opts *SendOpts) (int, error)
|
|
SendMediaGroup(ctx context.Context, chatID int64, media []TGInputMedia, opts *SendOpts) ([]int, error)
|
|
|
|
EditMessageText(ctx context.Context, chatID int64, msgID int, text string, opts *SendOpts) error
|
|
EditMessageMedia(ctx context.Context, chatID int64, msgID int, media TGInputMedia) error
|
|
|
|
DeleteMessage(ctx context.Context, chatID int64, msgID int) error
|
|
AnswerCallback(ctx context.Context, callbackID string, text string) error
|
|
|
|
GetFile(ctx context.Context, fileID string) (filePath string, err error)
|
|
GetFileDirectURL(filePath string) string
|
|
GetChatMember(ctx context.Context, chatID, userID int64) (status string, err error)
|
|
SetMyCommands(ctx context.Context, commands []BotCommand, scope *CommandScope) error
|
|
GetChat(ctx context.Context, chatID int64) (title string, err error)
|
|
|
|
SetWebhook(ctx context.Context, url string) error
|
|
DeleteWebhook(ctx context.Context) error
|
|
StartWebhook(path string) <-chan TGUpdate
|
|
StartPolling(ctx context.Context) <-chan TGUpdate
|
|
|
|
BotUsername() string
|
|
BotToken() string
|
|
}
|