2018-11-28 10:57:59 +01:00
|
|
|
package btelegram
|
|
|
|
|
|
|
|
import (
|
2018-12-12 23:50:08 +01:00
|
|
|
"html"
|
2021-04-03 23:15:19 +02:00
|
|
|
"path/filepath"
|
2018-11-28 10:57:59 +01:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2019-07-08 22:19:45 +02:00
|
|
|
"unicode/utf16"
|
2018-11-28 10:57:59 +01:00
|
|
|
|
|
|
|
"github.com/42wim/matterbridge/bridge/config"
|
|
|
|
"github.com/42wim/matterbridge/bridge/helper"
|
2019-07-08 22:19:45 +02:00
|
|
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
2018-11-28 10:57:59 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func (b *Btelegram) handleUpdate(rmsg *config.Message, message, posted, edited *tgbotapi.Message) *tgbotapi.Message {
|
|
|
|
// handle channels
|
|
|
|
if posted != nil {
|
|
|
|
message = posted
|
|
|
|
rmsg.Text = message.Text
|
|
|
|
}
|
|
|
|
|
|
|
|
// edited channel message
|
|
|
|
if edited != nil && !b.GetBool("EditDisable") {
|
|
|
|
message = edited
|
|
|
|
rmsg.Text = rmsg.Text + message.Text + b.GetString("EditSuffix")
|
|
|
|
}
|
|
|
|
return message
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleChannels checks if it's a channel message and if the message is a new or edited messages
|
|
|
|
func (b *Btelegram) handleChannels(rmsg *config.Message, message *tgbotapi.Message, update tgbotapi.Update) *tgbotapi.Message {
|
|
|
|
return b.handleUpdate(rmsg, message, update.ChannelPost, update.EditedChannelPost)
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleGroups checks if it's a group message and if the message is a new or edited messages
|
|
|
|
func (b *Btelegram) handleGroups(rmsg *config.Message, message *tgbotapi.Message, update tgbotapi.Update) *tgbotapi.Message {
|
|
|
|
return b.handleUpdate(rmsg, message, update.Message, update.EditedMessage)
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleForwarded handles forwarded messages
|
|
|
|
func (b *Btelegram) handleForwarded(rmsg *config.Message, message *tgbotapi.Message) {
|
2020-05-23 19:15:26 +02:00
|
|
|
if message.ForwardDate == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if message.ForwardFrom == nil {
|
|
|
|
rmsg.Text = "Forwarded from " + unknownUser + ": " + rmsg.Text
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
usernameForward := ""
|
|
|
|
if b.GetBool("UseFirstName") {
|
|
|
|
usernameForward = message.ForwardFrom.FirstName
|
|
|
|
}
|
|
|
|
|
|
|
|
if usernameForward == "" {
|
|
|
|
usernameForward = message.ForwardFrom.UserName
|
2018-11-28 10:57:59 +01:00
|
|
|
if usernameForward == "" {
|
2020-05-23 19:15:26 +02:00
|
|
|
usernameForward = message.ForwardFrom.FirstName
|
2018-11-28 10:57:59 +01:00
|
|
|
}
|
|
|
|
}
|
2020-05-23 19:15:26 +02:00
|
|
|
|
|
|
|
if usernameForward == "" {
|
|
|
|
usernameForward = unknownUser
|
|
|
|
}
|
|
|
|
|
|
|
|
rmsg.Text = "Forwarded from " + usernameForward + ": " + rmsg.Text
|
2018-11-28 10:57:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// handleQuoting handles quoting of previous messages
|
|
|
|
func (b *Btelegram) handleQuoting(rmsg *config.Message, message *tgbotapi.Message) {
|
|
|
|
if message.ReplyToMessage != nil {
|
|
|
|
usernameReply := ""
|
|
|
|
if message.ReplyToMessage.From != nil {
|
|
|
|
if b.GetBool("UseFirstName") {
|
|
|
|
usernameReply = message.ReplyToMessage.From.FirstName
|
|
|
|
}
|
|
|
|
if usernameReply == "" {
|
|
|
|
usernameReply = message.ReplyToMessage.From.UserName
|
|
|
|
if usernameReply == "" {
|
|
|
|
usernameReply = message.ReplyToMessage.From.FirstName
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if usernameReply == "" {
|
|
|
|
usernameReply = unknownUser
|
|
|
|
}
|
|
|
|
if !b.GetBool("QuoteDisable") {
|
|
|
|
rmsg.Text = b.handleQuote(rmsg.Text, usernameReply, message.ReplyToMessage.Text)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleUsername handles the correct setting of the username
|
|
|
|
func (b *Btelegram) handleUsername(rmsg *config.Message, message *tgbotapi.Message) {
|
|
|
|
if message.From != nil {
|
|
|
|
rmsg.UserID = strconv.Itoa(message.From.ID)
|
|
|
|
if b.GetBool("UseFirstName") {
|
|
|
|
rmsg.Username = message.From.FirstName
|
|
|
|
}
|
|
|
|
if rmsg.Username == "" {
|
|
|
|
rmsg.Username = message.From.UserName
|
|
|
|
if rmsg.Username == "" {
|
|
|
|
rmsg.Username = message.From.FirstName
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// only download avatars if we have a place to upload them (configured mediaserver)
|
2020-02-15 18:31:40 +01:00
|
|
|
if b.General.MediaServerUpload != "" || (b.General.MediaServerDownload != "" && b.General.MediaDownloadPath != "") {
|
2018-11-28 10:57:59 +01:00
|
|
|
b.handleDownloadAvatar(message.From.ID, rmsg.Channel)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if we really didn't find a username, set it to unknown
|
|
|
|
if rmsg.Username == "" {
|
|
|
|
rmsg.Username = unknownUser
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *Btelegram) handleRecv(updates <-chan tgbotapi.Update) {
|
|
|
|
for update := range updates {
|
|
|
|
b.Log.Debugf("== Receiving event: %#v", update.Message)
|
|
|
|
|
2019-04-05 00:02:26 +02:00
|
|
|
if update.Message == nil && update.ChannelPost == nil &&
|
|
|
|
update.EditedMessage == nil && update.EditedChannelPost == nil {
|
2018-11-28 10:57:59 +01:00
|
|
|
b.Log.Error("Getting nil messages, this shouldn't happen.")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
var message *tgbotapi.Message
|
|
|
|
|
|
|
|
rmsg := config.Message{Account: b.Account, Extra: make(map[string][]interface{})}
|
|
|
|
|
|
|
|
// handle channels
|
2018-11-29 23:03:50 +01:00
|
|
|
message = b.handleChannels(&rmsg, message, update)
|
2018-11-28 10:57:59 +01:00
|
|
|
|
|
|
|
// handle groups
|
2018-11-29 23:03:50 +01:00
|
|
|
message = b.handleGroups(&rmsg, message, update)
|
2018-11-28 10:57:59 +01:00
|
|
|
|
2019-04-05 00:04:08 +02:00
|
|
|
if message == nil {
|
|
|
|
b.Log.Error("message is nil, this shouldn't happen.")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2018-11-28 10:57:59 +01:00
|
|
|
// set the ID's from the channel or group message
|
|
|
|
rmsg.ID = strconv.Itoa(message.MessageID)
|
|
|
|
rmsg.Channel = strconv.FormatInt(message.Chat.ID, 10)
|
|
|
|
|
|
|
|
// handle username
|
|
|
|
b.handleUsername(&rmsg, message)
|
|
|
|
|
|
|
|
// handle any downloads
|
|
|
|
err := b.handleDownload(&rmsg, message)
|
|
|
|
if err != nil {
|
|
|
|
b.Log.Errorf("download failed: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// handle forwarded messages
|
|
|
|
b.handleForwarded(&rmsg, message)
|
|
|
|
|
|
|
|
// quote the previous message
|
|
|
|
b.handleQuoting(&rmsg, message)
|
|
|
|
|
2019-03-02 22:38:44 +01:00
|
|
|
// handle entities (adding URLs)
|
|
|
|
b.handleEntities(&rmsg, message)
|
|
|
|
|
2018-11-28 10:57:59 +01:00
|
|
|
if rmsg.Text != "" || len(rmsg.Extra) > 0 {
|
|
|
|
rmsg.Text = helper.RemoveEmptyNewLines(rmsg.Text)
|
|
|
|
// channels don't have (always?) user information. see #410
|
|
|
|
if message.From != nil {
|
|
|
|
rmsg.Avatar = helper.GetAvatar(b.avatarMap, strconv.Itoa(message.From.ID), b.General)
|
|
|
|
}
|
|
|
|
|
|
|
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
|
|
|
|
b.Log.Debugf("<= Message is %#v", rmsg)
|
|
|
|
b.Remote <- rmsg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleDownloadAvatar downloads the avatar of userid from channel
|
|
|
|
// sends a EVENT_AVATAR_DOWNLOAD message to the gateway if successful.
|
|
|
|
// logs an error message if it fails
|
|
|
|
func (b *Btelegram) handleDownloadAvatar(userid int, channel string) {
|
2021-02-25 23:28:54 +01:00
|
|
|
rmsg := config.Message{
|
|
|
|
Username: "system",
|
|
|
|
Text: "avatar",
|
|
|
|
Channel: channel,
|
|
|
|
Account: b.Account,
|
|
|
|
UserID: strconv.Itoa(userid),
|
|
|
|
Event: config.EventAvatarDownload,
|
|
|
|
Extra: make(map[string][]interface{}),
|
|
|
|
}
|
2018-11-28 10:57:59 +01:00
|
|
|
|
|
|
|
if _, ok := b.avatarMap[strconv.Itoa(userid)]; !ok {
|
|
|
|
photos, err := b.c.GetUserProfilePhotos(tgbotapi.UserProfilePhotosConfig{UserID: userid, Limit: 1})
|
|
|
|
if err != nil {
|
|
|
|
b.Log.Errorf("Userprofile download failed for %#v %s", userid, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(photos.Photos) > 0 {
|
|
|
|
photo := photos.Photos[0][0]
|
|
|
|
url := b.getFileDirectURL(photo.FileID)
|
|
|
|
name := strconv.Itoa(userid) + ".png"
|
|
|
|
b.Log.Debugf("trying to download %#v fileid %#v with size %#v", name, photo.FileID, photo.FileSize)
|
|
|
|
|
|
|
|
err := helper.HandleDownloadSize(b.Log, &rmsg, name, int64(photo.FileSize), b.General)
|
|
|
|
if err != nil {
|
|
|
|
b.Log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
data, err := helper.DownloadFile(url)
|
|
|
|
if err != nil {
|
|
|
|
b.Log.Errorf("download %s failed %#v", url, err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
helper.HandleDownloadData(b.Log, &rmsg, name, rmsg.Text, "", data, b.General)
|
|
|
|
b.Remote <- rmsg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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 22:34:28 +02:00
|
|
|
func (b *Btelegram) maybeConvertTgs(name *string, data *[]byte) {
|
2021-08-24 22:32:50 +02:00
|
|
|
format := b.GetString("MediaConvertTgs")
|
|
|
|
if helper.SupportsFormat(format) {
|
|
|
|
b.Log.Debugf("Format supported by %s, converting %v", helper.LottieBackend(), name)
|
|
|
|
} else {
|
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 22:34:28 +02:00
|
|
|
// Otherwise, no conversion was requested. Trying to run the usual webp
|
|
|
|
// converter would fail, because '.tgs.webp' is actually a gzipped JSON
|
|
|
|
// file, and has nothing to do with WebP.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err := helper.ConvertTgsToX(data, format, b.Log)
|
|
|
|
if err != nil {
|
|
|
|
b.Log.Errorf("conversion failed: %v", err)
|
|
|
|
} else {
|
|
|
|
*name = strings.Replace(*name, "tgs.webp", format, 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *Btelegram) maybeConvertWebp(name *string, data *[]byte) {
|
|
|
|
if b.GetBool("MediaConvertWebPToPNG") {
|
|
|
|
b.Log.Debugf("WebP to PNG conversion enabled, converting %v", name)
|
|
|
|
err := helper.ConvertWebPToPNG(data)
|
|
|
|
if err != nil {
|
|
|
|
b.Log.Errorf("conversion failed: %v", err)
|
|
|
|
} else {
|
|
|
|
*name = strings.Replace(*name, ".webp", ".png", 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-28 10:57:59 +01:00
|
|
|
// handleDownloadFile handles file download
|
|
|
|
func (b *Btelegram) handleDownload(rmsg *config.Message, message *tgbotapi.Message) error {
|
|
|
|
size := 0
|
|
|
|
var url, name, text string
|
|
|
|
switch {
|
|
|
|
case message.Sticker != nil:
|
|
|
|
text, name, url = b.getDownloadInfo(message.Sticker.FileID, ".webp", true)
|
|
|
|
size = message.Sticker.FileSize
|
|
|
|
case message.Voice != nil:
|
|
|
|
text, name, url = b.getDownloadInfo(message.Voice.FileID, ".ogg", true)
|
|
|
|
size = message.Voice.FileSize
|
|
|
|
case message.Video != nil:
|
|
|
|
text, name, url = b.getDownloadInfo(message.Video.FileID, "", true)
|
|
|
|
size = message.Video.FileSize
|
|
|
|
case message.Audio != nil:
|
|
|
|
text, name, url = b.getDownloadInfo(message.Audio.FileID, "", true)
|
|
|
|
size = message.Audio.FileSize
|
|
|
|
case message.Document != nil:
|
|
|
|
_, _, url = b.getDownloadInfo(message.Document.FileID, "", false)
|
|
|
|
size = message.Document.FileSize
|
|
|
|
name = message.Document.FileName
|
|
|
|
text = " " + message.Document.FileName + " : " + url
|
|
|
|
case message.Photo != nil:
|
|
|
|
photos := *message.Photo
|
|
|
|
size = photos[len(photos)-1].FileSize
|
|
|
|
text, name, url = b.getDownloadInfo(photos[len(photos)-1].FileID, "", true)
|
|
|
|
}
|
|
|
|
|
|
|
|
// if name is empty we didn't match a thing to download
|
|
|
|
if name == "" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
// use the URL instead of native upload
|
|
|
|
if b.GetBool("UseInsecureURL") {
|
|
|
|
b.Log.Debugf("Setting message text to :%s", text)
|
|
|
|
rmsg.Text += text
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
// if we have a file attached, download it (in memory) and put a pointer to it in msg.Extra
|
|
|
|
err := helper.HandleDownloadSize(b.Log, rmsg, name, int64(size), b.General)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
data, err := helper.DownloadFile(url)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
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 22:34:28 +02:00
|
|
|
|
|
|
|
if strings.HasSuffix(name, ".tgs.webp") {
|
|
|
|
b.maybeConvertTgs(&name, data)
|
|
|
|
} else if strings.HasSuffix(name, ".webp") {
|
|
|
|
b.maybeConvertWebp(&name, data)
|
2019-02-27 00:41:50 +01:00
|
|
|
}
|
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 22:34:28 +02:00
|
|
|
|
2021-01-02 00:55:20 +01:00
|
|
|
// rename .oga to .ogg https://github.com/42wim/matterbridge/issues/906#issuecomment-741793512
|
|
|
|
if strings.HasSuffix(name, ".oga") && message.Audio != nil {
|
|
|
|
name = strings.Replace(name, ".oga", ".ogg", 1)
|
|
|
|
}
|
|
|
|
|
2018-11-28 10:57:59 +01:00
|
|
|
helper.HandleDownloadData(b.Log, rmsg, name, message.Caption, "", data, b.General)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *Btelegram) getDownloadInfo(id string, suffix string, urlpart bool) (string, string, string) {
|
|
|
|
url := b.getFileDirectURL(id)
|
|
|
|
name := ""
|
|
|
|
if urlpart {
|
|
|
|
urlPart := strings.Split(url, "/")
|
|
|
|
name = urlPart[len(urlPart)-1]
|
|
|
|
}
|
|
|
|
if suffix != "" && !strings.HasSuffix(name, suffix) {
|
|
|
|
name += suffix
|
|
|
|
}
|
|
|
|
text := " " + url
|
|
|
|
return text, name, url
|
|
|
|
}
|
|
|
|
|
2018-12-12 23:50:08 +01:00
|
|
|
// handleDelete handles message deleting
|
|
|
|
func (b *Btelegram) handleDelete(msg *config.Message, chatid int64) (string, error) {
|
|
|
|
if msg.ID == "" {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
msgid, err := strconv.Atoi(msg.ID)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
_, err = b.c.DeleteMessage(tgbotapi.DeleteMessageConfig{ChatID: chatid, MessageID: msgid})
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleEdit handles message editing.
|
|
|
|
func (b *Btelegram) handleEdit(msg *config.Message, chatid int64) (string, error) {
|
|
|
|
msgid, err := strconv.Atoi(msg.ID)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if strings.ToLower(b.GetString("MessageFormat")) == HTMLNick {
|
|
|
|
b.Log.Debug("Using mode HTML - nick only")
|
|
|
|
msg.Text = html.EscapeString(msg.Text)
|
|
|
|
}
|
|
|
|
m := tgbotapi.NewEditMessageText(chatid, msgid, msg.Username+msg.Text)
|
|
|
|
switch b.GetString("MessageFormat") {
|
|
|
|
case HTMLFormat:
|
|
|
|
b.Log.Debug("Using mode HTML")
|
|
|
|
m.ParseMode = tgbotapi.ModeHTML
|
|
|
|
case "Markdown":
|
|
|
|
b.Log.Debug("Using mode markdown")
|
|
|
|
m.ParseMode = tgbotapi.ModeMarkdown
|
2020-07-12 22:40:22 +02:00
|
|
|
case MarkdownV2:
|
|
|
|
b.Log.Debug("Using mode MarkdownV2")
|
|
|
|
m.ParseMode = MarkdownV2
|
2018-12-12 23:50:08 +01:00
|
|
|
}
|
|
|
|
if strings.ToLower(b.GetString("MessageFormat")) == HTMLNick {
|
|
|
|
b.Log.Debug("Using mode HTML - nick only")
|
|
|
|
m.ParseMode = tgbotapi.ModeHTML
|
|
|
|
}
|
|
|
|
_, err = b.c.Send(m)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
|
2018-11-28 10:57:59 +01:00
|
|
|
// handleUploadFile handles native upload of files
|
|
|
|
func (b *Btelegram) handleUploadFile(msg *config.Message, chatid int64) string {
|
|
|
|
var c tgbotapi.Chattable
|
|
|
|
for _, f := range msg.Extra["file"] {
|
|
|
|
fi := f.(config.FileInfo)
|
|
|
|
file := tgbotapi.FileBytes{
|
|
|
|
Name: fi.Name,
|
|
|
|
Bytes: *fi.Data,
|
|
|
|
}
|
2021-04-03 23:15:19 +02:00
|
|
|
switch filepath.Ext(fi.Name) {
|
|
|
|
case ".jpg", ".jpe", ".png":
|
|
|
|
pc := tgbotapi.NewPhotoUpload(chatid, file)
|
|
|
|
pc.Caption, pc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
|
|
|
c = pc
|
|
|
|
case ".mp4", ".m4v":
|
|
|
|
vc := tgbotapi.NewVideoUpload(chatid, file)
|
|
|
|
vc.Caption, vc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
|
|
|
c = vc
|
|
|
|
case ".mp3", ".oga":
|
|
|
|
ac := tgbotapi.NewAudioUpload(chatid, file)
|
|
|
|
ac.Caption, ac.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
|
|
|
c = ac
|
|
|
|
case ".ogg":
|
|
|
|
voc := tgbotapi.NewVoiceUpload(chatid, file)
|
|
|
|
voc.Caption, voc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
|
|
|
c = voc
|
|
|
|
default:
|
|
|
|
dc := tgbotapi.NewDocumentUpload(chatid, file)
|
|
|
|
dc.Caption, dc.ParseMode = TGGetParseMode(b, msg.Username, fi.Comment)
|
|
|
|
c = dc
|
2018-11-28 10:57:59 +01:00
|
|
|
}
|
|
|
|
_, err := b.c.Send(c)
|
|
|
|
if err != nil {
|
|
|
|
b.Log.Errorf("file upload failed: %#v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *Btelegram) handleQuote(message, quoteNick, quoteMessage string) string {
|
|
|
|
format := b.GetString("quoteformat")
|
|
|
|
if format == "" {
|
|
|
|
format = "{MESSAGE} (re @{QUOTENICK}: {QUOTEMESSAGE})"
|
|
|
|
}
|
2021-02-25 23:28:54 +01:00
|
|
|
quoteMessagelength := len([]rune(quoteMessage))
|
2020-01-30 00:02:33 +01:00
|
|
|
if b.GetInt("QuoteLengthLimit") != 0 && quoteMessagelength >= b.GetInt("QuoteLengthLimit") {
|
|
|
|
runes := []rune(quoteMessage)
|
|
|
|
quoteMessage = string(runes[0:b.GetInt("QuoteLengthLimit")])
|
|
|
|
if quoteMessagelength > b.GetInt("QuoteLengthLimit") {
|
|
|
|
quoteMessage += "..."
|
|
|
|
}
|
|
|
|
}
|
2018-11-28 10:57:59 +01:00
|
|
|
format = strings.Replace(format, "{MESSAGE}", message, -1)
|
|
|
|
format = strings.Replace(format, "{QUOTENICK}", quoteNick, -1)
|
|
|
|
format = strings.Replace(format, "{QUOTEMESSAGE}", quoteMessage, -1)
|
|
|
|
return format
|
|
|
|
}
|
2019-03-02 22:38:44 +01:00
|
|
|
|
|
|
|
// handleEntities handles messageEntities
|
|
|
|
func (b *Btelegram) handleEntities(rmsg *config.Message, message *tgbotapi.Message) {
|
|
|
|
if message.Entities == nil {
|
|
|
|
return
|
|
|
|
}
|
2021-12-07 21:26:28 +01:00
|
|
|
|
2021-12-10 22:13:54 +01:00
|
|
|
indexMovedBy := 0
|
2021-12-07 21:26:28 +01:00
|
|
|
|
2019-03-02 22:38:44 +01:00
|
|
|
// for now only do URL replacements
|
|
|
|
for _, e := range *message.Entities {
|
|
|
|
if e.Type == "text_link" {
|
|
|
|
url, err := e.ParseURL()
|
|
|
|
if err != nil {
|
|
|
|
b.Log.Errorf("entity text_link url parse failed: %s", err)
|
|
|
|
continue
|
|
|
|
}
|
2019-07-08 22:19:45 +02:00
|
|
|
utfEncodedString := utf16.Encode([]rune(rmsg.Text))
|
|
|
|
if e.Offset+e.Length > len(utfEncodedString) {
|
|
|
|
b.Log.Errorf("entity length is too long %d > %d", e.Offset+e.Length, len(utfEncodedString))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
link := utf16.Decode(utfEncodedString[e.Offset : e.Offset+e.Length])
|
|
|
|
rmsg.Text = strings.Replace(rmsg.Text, string(link), url.String(), 1)
|
2019-03-02 22:38:44 +01:00
|
|
|
}
|
2021-12-07 21:26:28 +01:00
|
|
|
|
|
|
|
if e.Type == "code" {
|
2021-12-10 22:13:54 +01:00
|
|
|
offset := e.Offset + indexMovedBy
|
|
|
|
rmsg.Text = rmsg.Text[:offset] + "`" + rmsg.Text[offset:offset+e.Length] + "`" + rmsg.Text[offset+e.Length:]
|
2021-12-07 21:26:28 +01:00
|
|
|
indexMovedBy += 2
|
|
|
|
}
|
|
|
|
|
|
|
|
if e.Type == "pre" {
|
2021-12-10 22:13:54 +01:00
|
|
|
offset := e.Offset + indexMovedBy
|
|
|
|
rmsg.Text = rmsg.Text[:offset] + "```\n" + rmsg.Text[offset:offset+e.Length] + "\n```" + rmsg.Text[offset+e.Length:]
|
2021-12-07 21:26:28 +01:00
|
|
|
indexMovedBy += 8
|
|
|
|
}
|
2019-03-02 22:38:44 +01:00
|
|
|
}
|
|
|
|
}
|