mirror of
https://github.com/42wim/matterbridge.git
synced 2024-11-30 22:52:00 -08:00
b2af76e7dc
This is half a fix for #874 This patch introduces a new config flag: - MediaConvertTgs These need to be treated independently from the existing MediaConvertWebPToPNG flag because Tgs→WebP results in an *animated* WebP, and the WebP→PNG converter can't handle animated WebP files yet. Furthermore, some platforms (like discord) don't even support animated WebP files, so the user may want to fall back to static PNGs (not APNGs). The final reason why this is only half a fix is that this introduces an external dependency, namely lottie, to be installed like this: $ pip3 install lottie cairosvg This patch works by writing the tgs to a temporary file in /tmp, calling lottie to convert it (this conversion may take several seconds!), and then deleting the temporary file. The temporary file is absolutely necessary, as lottie refuses to work on non-seekable files. If anyone comes up with a reasonable use case where /tmp is unavailable, I can add yet another config option for that, if desired. Telegram will bail out if the option is configured but lottie isn't found.
172 lines
4.3 KiB
Go
172 lines
4.3 KiB
Go
package btelegram
|
|
|
|
import (
|
|
"html"
|
|
"log"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/42wim/matterbridge/bridge"
|
|
"github.com/42wim/matterbridge/bridge/config"
|
|
"github.com/42wim/matterbridge/bridge/helper"
|
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
|
)
|
|
|
|
const (
|
|
unknownUser = "unknown"
|
|
HTMLFormat = "HTML"
|
|
HTMLNick = "htmlnick"
|
|
MarkdownV2 = "MarkdownV2"
|
|
FormatPng = "png"
|
|
FormatWebp = "webp"
|
|
)
|
|
|
|
type Btelegram struct {
|
|
c *tgbotapi.BotAPI
|
|
*bridge.Config
|
|
avatarMap map[string]string // keep cache of userid and avatar sha
|
|
}
|
|
|
|
func New(cfg *bridge.Config) bridge.Bridger {
|
|
tgsConvertFormat := cfg.GetString("MediaConvertTgs")
|
|
if tgsConvertFormat != "" {
|
|
err := helper.CanConvertTgsToX()
|
|
if err != nil {
|
|
log.Fatalf("Telegram bridge configured to convert .tgs files to '%s', but lottie does not appear to work:\n%#v", tgsConvertFormat, err)
|
|
}
|
|
if tgsConvertFormat != FormatPng && tgsConvertFormat != FormatWebp {
|
|
log.Fatalf("Telegram bridge configured to convert .tgs files to '%s', but only '%s' and '%s' are supported.", FormatPng, FormatWebp, tgsConvertFormat)
|
|
}
|
|
}
|
|
return &Btelegram{Config: cfg, avatarMap: make(map[string]string)}
|
|
}
|
|
|
|
func (b *Btelegram) Connect() error {
|
|
var err error
|
|
b.Log.Info("Connecting")
|
|
b.c, err = tgbotapi.NewBotAPI(b.GetString("Token"))
|
|
if err != nil {
|
|
b.Log.Debugf("%#v", err)
|
|
return err
|
|
}
|
|
u := tgbotapi.NewUpdate(0)
|
|
u.Timeout = 60
|
|
updates, err := b.c.GetUpdatesChan(u)
|
|
if err != nil {
|
|
b.Log.Debugf("%#v", err)
|
|
return err
|
|
}
|
|
b.Log.Info("Connection succeeded")
|
|
go b.handleRecv(updates)
|
|
return nil
|
|
}
|
|
|
|
func (b *Btelegram) Disconnect() error {
|
|
return nil
|
|
}
|
|
|
|
func (b *Btelegram) JoinChannel(channel config.ChannelInfo) error {
|
|
return nil
|
|
}
|
|
|
|
func (b *Btelegram) Send(msg config.Message) (string, error) {
|
|
b.Log.Debugf("=> Receiving %#v", msg)
|
|
|
|
// get the chatid
|
|
chatid, err := strconv.ParseInt(msg.Channel, 10, 64)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// map the file SHA to our user (caches the avatar)
|
|
if msg.Event == config.EventAvatarDownload {
|
|
return b.cacheAvatar(&msg)
|
|
}
|
|
|
|
if b.GetString("MessageFormat") == HTMLFormat {
|
|
msg.Text = makeHTML(msg.Text)
|
|
}
|
|
|
|
// Delete message
|
|
if msg.Event == config.EventMsgDelete {
|
|
return b.handleDelete(&msg, chatid)
|
|
}
|
|
|
|
// Upload a file if it exists
|
|
if msg.Extra != nil {
|
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
|
if _, msgErr := b.sendMessage(chatid, rmsg.Username, rmsg.Text); msgErr != nil {
|
|
b.Log.Errorf("sendMessage failed: %s", msgErr)
|
|
}
|
|
}
|
|
// check if we have files to upload (from slack, telegram or mattermost)
|
|
if len(msg.Extra["file"]) > 0 {
|
|
b.handleUploadFile(&msg, chatid)
|
|
}
|
|
}
|
|
|
|
// edit the message if we have a msg ID
|
|
if msg.ID != "" {
|
|
return b.handleEdit(&msg, chatid)
|
|
}
|
|
|
|
// Post normal message
|
|
// TODO: recheck it.
|
|
// Ignore empty text field needs for prevent double messages from whatsapp to telegram
|
|
// when sending media with text caption
|
|
if msg.Text != "" {
|
|
return b.sendMessage(chatid, msg.Username, msg.Text)
|
|
}
|
|
|
|
return "", nil
|
|
}
|
|
|
|
func (b *Btelegram) getFileDirectURL(id string) string {
|
|
res, err := b.c.GetFileDirectURL(id)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (b *Btelegram) sendMessage(chatid int64, username, text string) (string, error) {
|
|
m := tgbotapi.NewMessage(chatid, "")
|
|
m.Text = username + text
|
|
if b.GetString("MessageFormat") == HTMLFormat {
|
|
b.Log.Debug("Using mode HTML")
|
|
m.ParseMode = tgbotapi.ModeHTML
|
|
}
|
|
if b.GetString("MessageFormat") == "Markdown" {
|
|
b.Log.Debug("Using mode markdown")
|
|
m.ParseMode = tgbotapi.ModeMarkdown
|
|
}
|
|
if b.GetString("MessageFormat") == MarkdownV2 {
|
|
b.Log.Debug("Using mode MarkdownV2")
|
|
m.ParseMode = MarkdownV2
|
|
}
|
|
if strings.ToLower(b.GetString("MessageFormat")) == HTMLNick {
|
|
b.Log.Debug("Using mode HTML - nick only")
|
|
m.Text = username + html.EscapeString(text)
|
|
m.ParseMode = tgbotapi.ModeHTML
|
|
}
|
|
|
|
m.DisableWebPagePreview = b.GetBool("DisableWebPagePreview")
|
|
|
|
res, err := b.c.Send(m)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return strconv.Itoa(res.MessageID), nil
|
|
}
|
|
|
|
func (b *Btelegram) cacheAvatar(msg *config.Message) (string, error) {
|
|
fi := msg.Extra["file"][0].(config.FileInfo)
|
|
/* if we have a sha we have successfully uploaded the file to the media server,
|
|
so we can now cache the sha */
|
|
if fi.SHA != "" {
|
|
b.Log.Debugf("Added %s to %s in avatarMap", fi.SHA, msg.UserID)
|
|
b.avatarMap[msg.UserID] = fi.SHA
|
|
}
|
|
return "", nil
|
|
}
|