diff --git a/config.go b/config.go index e252e848d9961e155daec5001c9c7aaef50a9bc8..f099886dd0f21cf731c494247089b51056846592 100644 --- a/config.go +++ b/config.go @@ -41,9 +41,10 @@ type telegramConf struct { } type discordConf struct { - Token string - NameFormat string - StickerText bool + Token string + NameFormat string + StickerText bool + NoMentionEveryone bool } type bridgeConf struct { @@ -114,9 +115,10 @@ var defConf = conf{ BypassBacklog: true, }, Discord: discordConf{ - Token: "INSERT_TOKEN_HERE", - NameFormat: "$USER#$DISCRIMINATOR", - StickerText: true, + Token: "INSERT_TOKEN_HERE", + NameFormat: "$USER#$DISCRIMINATOR", + StickerText: true, + NoMentionEveryone: true, }, Bridges: struct{ Item []bridgeConf }{Item: []bridgeConf{ { diff --git a/discord.go b/discord.go index bd6048ee2ce84c2e6b6b55ede8080bdd1c3d3d8c..b07bd70732c299df0c7837a41434bfd2420351a0 100644 --- a/discord.go +++ b/discord.go @@ -5,7 +5,10 @@ import ( "log" ) -var session *discordgo.Session +var ( + session *discordgo.Session + application *discordgo.Application +) func init() { discordgo.Logger = func(msgL, _ int, format string, a ...interface{}) { @@ -45,6 +48,13 @@ func openDiscord() { session.State.User.Username, session.State.User.Discriminator, session.State.User.ID) } + if app, err := session.Application("@me"); err != nil { + log.Fatalf("error getting application: %s", err) + } else { + log.Printf("fetched self discord application %s (%s)", app.Name, app.ID) + application = app + } + ready <- struct{}{} } diff --git a/telegram.go b/telegram.go index 53a9088dd629b0166046fac26241118491fb7b68..3a94de2afb898c1ce973895aae3ef05bc6b9246a 100644 --- a/telegram.go +++ b/telegram.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "github.com/bwmarrin/discordgo" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" "log" @@ -102,7 +103,7 @@ func respondTelegram(update tgbotapi.Update) { header, _ := makeHeader(update.EditedMessage, true) content = header + content } - if _, err := session.ChannelMessageEdit(reference.ChannelID, reference.MessageID, content); err != nil { + if _, err := session.ChannelMessageEdit(reference.ChannelID, reference.MessageID, escape(content)); err != nil { msg := tgbotapi.NewMessage(update.EditedMessage.Chat.ID, "error relaying edit") msg.ReplyToMessageID = update.EditedMessage.MessageID log.Printf("error relaying edit of %v: %s", update.EditedMessage.MessageID, err) @@ -126,19 +127,7 @@ func respondTelegram(update tgbotapi.Update) { } if update.Message.IsCommand() { - message := tgbotapi.NewMessage(update.Message.Chat.ID, "") - switch update.Message.Command() { - case "id": - message.Text = strconv.Itoa(int(update.Message.Chat.ID)) - default: - } - if message.Text != "" { - message.ReplyToMessageID = update.Message.MessageID - if _, err := botAPI.Send(message); err != nil { - log.Printf("error responding to command %v, %s", update.Message.Chat.ID, err) - } - return - } + go telegramCommand(update) } var ( @@ -176,55 +165,45 @@ func respondTelegram(update tgbotapi.Update) { header, has := makeHeader(update.Message, false) - if update.Message.Photo != nil && (len(*update.Message.Photo)/4) > 0 { - fids := "" - files := make([]*discordgo.File, len(*update.Message.Photo)/4) + if update.Message.Photo != nil { + var file *discordgo.File p := *update.Message.Photo - for i := 0; i < len(files); i++ { - // FIXME: multiple images - info := p[((i+1)*4)-1] - - var url string - if u, err := botAPI.GetFileDirectURL(info.FileID); err != nil { - msg := tgbotapi.NewMessage(update.Message.Chat.ID, "error getting URL") - msg.ReplyToMessageID = update.Message.MessageID - log.Printf("error getting URL of %s: %s", info.FileID, err) - _, _ = botAPI.Send(msg) - return - } else { - url = u - } + info := p[len(p)-1] - if resp, err := http.Get(url); err != nil { - msg := tgbotapi.NewMessage(update.Message.Chat.ID, "error getting file") - msg.ReplyToMessageID = update.Message.MessageID - log.Printf("error getting file %s: %s", info.FileID, err) - _, _ = botAPI.Send(msg) - return - } else { - files[i] = &discordgo.File{ - Name: "image.jpg", - ContentType: "image/jpeg", - Reader: resp.Body, - } - //goland:noinspection GoDeferInLoop - defer func() { - if err = resp.Body.Close(); err != nil { - log.Printf("error closing request body: %s", err) - } - }() - } + var url string + if u, err := botAPI.GetFileDirectURL(info.FileID); err != nil { + msg := tgbotapi.NewMessage(update.Message.Chat.ID, "error getting URL") + msg.ReplyToMessageID = update.Message.MessageID + log.Printf("error getting URL of %s: %s", info.FileID, err) + _, _ = botAPI.Send(msg) + return + } else { + url = u + } - if i != 0 { - fids += ", " + if resp, err := http.Get(url); err != nil { + msg := tgbotapi.NewMessage(update.Message.Chat.ID, "error getting file") + msg.ReplyToMessageID = update.Message.MessageID + log.Printf("error getting file %s: %s", info.FileID, err) + _, _ = botAPI.Send(msg) + return + } else { + file = &discordgo.File{ + Name: "image.jpg", + ContentType: "image/jpeg", + Reader: resp.Body, } - fids += info.FileID + defer func() { + if err = resp.Body.Close(); err != nil { + log.Printf("error closing request body: %s", err) + } + }() } if message, err := session.ChannelMessageSendComplex(strconv.Itoa(dc.ID), &discordgo.MessageSend{ - Content: header + update.Message.Caption, - Files: files, + Content: escape(header + update.Message.Caption), + File: file, Reference: reference, }); err != nil { msg := tgbotapi.NewMessage(update.Message.Chat.ID, "error relaying message") @@ -246,7 +225,7 @@ func respondTelegram(update tgbotapi.Update) { hasHeader[update.Message.MessageID] = has log.Printf("T%vM%v -> D%vM%s @%s (%v) [photo]: %s; caption: %s", - tc.ID, update.Message.MessageID, dc.ID, dMessageID, username, id, fids, update.Message.Caption) + tc.ID, update.Message.MessageID, dc.ID, dMessageID, username, id, info.FileID, update.Message.Caption) return } @@ -288,7 +267,7 @@ func respondTelegram(update tgbotapi.Update) { } if message, err := session.ChannelMessageSendComplex(strconv.Itoa(dc.ID), &discordgo.MessageSend{ - Content: content, + Content: escape(content), File: file, Reference: reference, }); err != nil { @@ -322,7 +301,7 @@ func respondTelegram(update tgbotapi.Update) { return } - if message, err := session.ChannelMessageSendReply(strconv.Itoa(dc.ID), header+update.Message.Text, reference); err != nil { + if message, err := session.ChannelMessageSendReply(strconv.Itoa(dc.ID), escape(header+update.Message.Text), reference); err != nil { msg := tgbotapi.NewMessage(update.Message.Chat.ID, "error relaying message") msg.ReplyToMessageID = update.Message.MessageID log.Printf("error relaying message %v: %s", update.Message.MessageID, err.Error()) @@ -359,3 +338,39 @@ func makeHeader(message *tgbotapi.Message, force bool) (string, bool) { } return "", false } + +func escape(str string) string { + if !config.Discord.NoMentionEveryone { + return str + } + return strings.ReplaceAll(strings.ReplaceAll(str, + "@everyone", "@\u200beveryone"), + "@here", "@\u200bhere") +} + +func telegramCommand(update tgbotapi.Update) { + message := tgbotapi.NewMessage(update.Message.Chat.ID, "") + switch update.Message.Command() { + case "start": + if update.Message.Chat.ID == int64(update.Message.From.ID) { + message.ParseMode = "Markdown" + message.Text = "Thanks for using BridgeThing!\n" + + "To find the ID of a Telegram chat, use /id\n" + + "To get the invite URL, use /invite\n" + + "Have fun!" + } + case "id": + message.Text = strconv.Itoa(int(update.Message.Chat.ID)) + case "invite": + message.DisableWebPagePreview = true + message.Text = fmt.Sprintf("https://discord.com/oauth2/authorize?client_id=%s&scope=bot&permissions=8192", + application.ID) + } + if message.Text != "" { + message.ReplyToMessageID = update.Message.MessageID + if _, err := botAPI.Send(message); err != nil { + log.Printf("error responding to command %v, %s", update.Message.Chat.ID, err) + } + return + } +}