2016-11-15 14:15:57 -08:00
|
|
|
package btelegram
|
|
|
|
|
|
|
|
import (
|
2018-06-18 14:38:52 -07:00
|
|
|
"html"
|
Support Telegram animated stickers (tgs) format (#1173)
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.
2020-08-23 13:34:28 -07:00
|
|
|
"log"
|
2017-01-06 14:32:17 -08:00
|
|
|
"strconv"
|
2017-11-12 13:04:35 -08:00
|
|
|
"strings"
|
2017-01-06 14:32:17 -08:00
|
|
|
|
2018-02-26 15:33:21 -08:00
|
|
|
"github.com/42wim/matterbridge/bridge"
|
2016-11-15 14:15:57 -08:00
|
|
|
"github.com/42wim/matterbridge/bridge/config"
|
2017-11-04 06:50:01 -07:00
|
|
|
"github.com/42wim/matterbridge/bridge/helper"
|
2020-01-09 09:14:01 -08:00
|
|
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
2016-11-15 14:15:57 -08:00
|
|
|
)
|
|
|
|
|
2018-11-08 13:20:03 -08:00
|
|
|
const (
|
|
|
|
unknownUser = "unknown"
|
|
|
|
HTMLFormat = "HTML"
|
|
|
|
HTMLNick = "htmlnick"
|
2020-07-12 13:40:22 -07:00
|
|
|
MarkdownV2 = "MarkdownV2"
|
Support Telegram animated stickers (tgs) format (#1173)
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.
2020-08-23 13:34:28 -07:00
|
|
|
FormatPng = "png"
|
|
|
|
FormatWebp = "webp"
|
2018-11-08 13:20:03 -08:00
|
|
|
)
|
|
|
|
|
2016-11-15 14:15:57 -08:00
|
|
|
type Btelegram struct {
|
2017-12-19 14:15:03 -08:00
|
|
|
c *tgbotapi.BotAPI
|
2018-03-04 14:52:14 -08:00
|
|
|
*bridge.Config
|
2018-02-19 15:54:35 -08:00
|
|
|
avatarMap map[string]string // keep cache of userid and avatar sha
|
2016-11-15 14:15:57 -08:00
|
|
|
}
|
|
|
|
|
2018-03-04 14:52:14 -08:00
|
|
|
func New(cfg *bridge.Config) bridge.Bridger {
|
Support Telegram animated stickers (tgs) format (#1173)
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.
2020-08-23 13:34:28 -07:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
2018-03-04 14:52:14 -08:00
|
|
|
return &Btelegram{Config: cfg, avatarMap: make(map[string]string)}
|
2016-11-15 14:15:57 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (b *Btelegram) Connect() error {
|
|
|
|
var err error
|
2018-02-26 15:33:21 -08:00
|
|
|
b.Log.Info("Connecting")
|
2018-03-04 14:52:14 -08:00
|
|
|
b.c, err = tgbotapi.NewBotAPI(b.GetString("Token"))
|
2016-11-15 14:15:57 -08:00
|
|
|
if err != nil {
|
2018-02-26 15:33:21 -08:00
|
|
|
b.Log.Debugf("%#v", err)
|
2016-11-15 14:15:57 -08:00
|
|
|
return err
|
|
|
|
}
|
2018-01-29 03:07:26 -08:00
|
|
|
u := tgbotapi.NewUpdate(0)
|
|
|
|
u.Timeout = 60
|
|
|
|
updates, err := b.c.GetUpdatesChan(u)
|
2016-11-15 14:15:57 -08:00
|
|
|
if err != nil {
|
2018-02-26 15:33:21 -08:00
|
|
|
b.Log.Debugf("%#v", err)
|
2016-11-15 14:15:57 -08:00
|
|
|
return err
|
|
|
|
}
|
2018-02-26 15:33:21 -08:00
|
|
|
b.Log.Info("Connection succeeded")
|
2016-11-15 14:15:57 -08:00
|
|
|
go b.handleRecv(updates)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-02-14 12:12:02 -08:00
|
|
|
func (b *Btelegram) Disconnect() error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-08-12 05:51:41 -07:00
|
|
|
func (b *Btelegram) JoinChannel(channel config.ChannelInfo) error {
|
2016-11-15 14:15:57 -08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-08-27 13:59:37 -07:00
|
|
|
func (b *Btelegram) Send(msg config.Message) (string, error) {
|
2018-02-28 13:23:29 -08:00
|
|
|
b.Log.Debugf("=> Receiving %#v", msg)
|
2018-02-25 14:54:20 -08:00
|
|
|
|
|
|
|
// get the chatid
|
2016-11-15 14:15:57 -08:00
|
|
|
chatid, err := strconv.ParseInt(msg.Channel, 10, 64)
|
|
|
|
if err != nil {
|
2017-08-27 13:59:37 -07:00
|
|
|
return "", err
|
2016-11-15 14:15:57 -08:00
|
|
|
}
|
2017-01-06 14:32:17 -08:00
|
|
|
|
2018-02-19 15:54:35 -08:00
|
|
|
// map the file SHA to our user (caches the avatar)
|
2018-11-15 11:43:43 -08:00
|
|
|
if msg.Event == config.EventAvatarDownload {
|
2018-02-25 14:54:20 -08:00
|
|
|
return b.cacheAvatar(&msg)
|
2018-02-19 15:54:35 -08:00
|
|
|
}
|
|
|
|
|
2018-11-08 13:20:03 -08:00
|
|
|
if b.GetString("MessageFormat") == HTMLFormat {
|
2017-02-24 09:49:52 -08:00
|
|
|
msg.Text = makeHTML(msg.Text)
|
|
|
|
}
|
2017-08-28 11:38:37 -07:00
|
|
|
|
2018-02-25 14:54:20 -08:00
|
|
|
// Delete message
|
2018-11-15 11:43:43 -08:00
|
|
|
if msg.Event == config.EventMsgDelete {
|
2018-12-12 14:50:08 -08:00
|
|
|
return b.handleDelete(&msg, chatid)
|
2017-09-11 14:12:33 -07:00
|
|
|
}
|
|
|
|
|
2018-02-25 14:54:20 -08:00
|
|
|
// Upload a file if it exists
|
|
|
|
if msg.Extra != nil {
|
|
|
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
2020-01-09 09:14:01 -08:00
|
|
|
if _, msgErr := b.sendMessage(chatid, rmsg.Username, rmsg.Text); msgErr != nil {
|
|
|
|
b.Log.Errorf("sendMessage failed: %s", msgErr)
|
2018-11-28 01:57:59 -08:00
|
|
|
}
|
2018-02-25 14:54:20 -08:00
|
|
|
}
|
|
|
|
// check if we have files to upload (from slack, telegram or mattermost)
|
|
|
|
if len(msg.Extra["file"]) > 0 {
|
|
|
|
b.handleUploadFile(&msg, chatid)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-28 11:38:37 -07:00
|
|
|
// edit the message if we have a msg ID
|
|
|
|
if msg.ID != "" {
|
2018-12-12 14:50:08 -08:00
|
|
|
return b.handleEdit(&msg, chatid)
|
2017-08-28 11:38:37 -07:00
|
|
|
}
|
|
|
|
|
2018-02-25 14:54:20 -08:00
|
|
|
// Post normal message
|
2020-01-09 09:14:01 -08:00
|
|
|
// 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
|
2016-11-15 14:15:57 -08:00
|
|
|
}
|
|
|
|
|
2017-06-17 09:25:17 -07:00
|
|
|
func (b *Btelegram) getFileDirectURL(id string) string {
|
|
|
|
res, err := b.c.GetFileDirectURL(id)
|
|
|
|
if err != nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|
2017-11-04 06:50:01 -07:00
|
|
|
|
2018-02-28 14:25:00 -08:00
|
|
|
func (b *Btelegram) sendMessage(chatid int64, username, text string) (string, error) {
|
|
|
|
m := tgbotapi.NewMessage(chatid, "")
|
|
|
|
m.Text = username + text
|
2018-11-08 13:20:03 -08:00
|
|
|
if b.GetString("MessageFormat") == HTMLFormat {
|
2018-02-26 15:33:21 -08:00
|
|
|
b.Log.Debug("Using mode HTML")
|
2017-11-12 15:20:31 -08:00
|
|
|
m.ParseMode = tgbotapi.ModeHTML
|
|
|
|
}
|
2018-03-04 14:52:14 -08:00
|
|
|
if b.GetString("MessageFormat") == "Markdown" {
|
2018-02-26 15:33:21 -08:00
|
|
|
b.Log.Debug("Using mode markdown")
|
2018-02-03 14:31:21 -08:00
|
|
|
m.ParseMode = tgbotapi.ModeMarkdown
|
|
|
|
}
|
2020-07-12 13:40:22 -07:00
|
|
|
if b.GetString("MessageFormat") == MarkdownV2 {
|
|
|
|
b.Log.Debug("Using mode MarkdownV2")
|
|
|
|
m.ParseMode = MarkdownV2
|
|
|
|
}
|
2018-11-08 13:20:03 -08:00
|
|
|
if strings.ToLower(b.GetString("MessageFormat")) == HTMLNick {
|
2018-06-18 14:38:52 -07:00
|
|
|
b.Log.Debug("Using mode HTML - nick only")
|
|
|
|
m.Text = username + html.EscapeString(text)
|
|
|
|
m.ParseMode = tgbotapi.ModeHTML
|
|
|
|
}
|
2020-02-02 09:53:04 -08:00
|
|
|
|
|
|
|
m.DisableWebPagePreview = b.GetBool("DisableWebPagePreview")
|
|
|
|
|
2017-11-12 15:20:31 -08:00
|
|
|
res, err := b.c.Send(m)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return strconv.Itoa(res.MessageID), nil
|
|
|
|
}
|
2018-02-25 14:54:20 -08:00
|
|
|
|
|
|
|
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 != "" {
|
2018-02-26 15:33:21 -08:00
|
|
|
b.Log.Debugf("Added %s to %s in avatarMap", fi.SHA, msg.UserID)
|
2018-02-25 14:54:20 -08:00
|
|
|
b.avatarMap[msg.UserID] = fi.SHA
|
|
|
|
}
|
|
|
|
return "", nil
|
|
|
|
}
|