1
0
mirror of synced 2024-11-22 12:26:02 +03:00
mg-transport-telegram/telegram.go

433 lines
10 KiB
Go
Raw Normal View History

package main
import (
2018-05-25 18:09:38 +03:00
"encoding/json"
"errors"
2018-06-08 13:57:51 +03:00
"fmt"
2018-05-25 18:09:38 +03:00
"io/ioutil"
"net/http"
2018-05-25 18:09:38 +03:00
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
2018-05-25 18:09:38 +03:00
"github.com/getsentry/raven-go"
"github.com/go-telegram-bot-api/telegram-bot-api"
2018-06-20 16:14:51 +03:00
"github.com/nicksnyder/go-i18n/v2/i18n"
2018-05-25 18:09:38 +03:00
"github.com/retailcrm/mg-transport-api-client-go/v1"
)
func setTransportRoutes() {
http.HandleFunc("/telegram/", makeHandler(telegramWebhookHandler))
2018-05-28 18:08:15 +03:00
http.HandleFunc("/webhook/", mgWebhookHandler)
}
// GetBotName function
func GetBotName(bot *tgbotapi.BotAPI) string {
return bot.Self.FirstName
}
2018-05-25 18:09:38 +03:00
func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string) {
2018-06-08 13:57:51 +03:00
defer r.Body.Close()
2018-05-31 19:44:23 +03:00
b, err := getBotByToken(token)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(token, err.Error())
w.WriteHeader(http.StatusInternalServerError)
2018-05-25 18:09:38 +03:00
return
}
if b.ID == 0 {
2018-06-08 17:40:50 +03:00
logger.Error(token, "telegramWebhookHandler: missing or deactivated")
w.WriteHeader(http.StatusOK)
2018-05-25 18:09:38 +03:00
return
}
2018-05-31 19:44:23 +03:00
c := getConnectionById(b.ConnectionID)
if !c.Active {
2018-06-08 17:40:50 +03:00
logger.Error(c.ClientID, "telegramWebhookHandler: connection deactivated")
w.WriteHeader(http.StatusOK)
2018-05-31 19:44:23 +03:00
return
}
2018-05-25 18:09:38 +03:00
var update tgbotapi.Update
bytes, err := ioutil.ReadAll(r.Body)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(token, err)
w.WriteHeader(http.StatusInternalServerError)
2018-05-25 18:09:38 +03:00
return
}
2018-06-01 14:46:07 +03:00
if config.Debug {
logger.Debugf("telegramWebhookHandler: %v", string(bytes))
}
2018-05-25 18:09:38 +03:00
err = json.Unmarshal(bytes, &update)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(token, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
var client = v1.New(c.MGURL, c.MGToken)
if update.Message != nil {
2018-06-20 16:14:51 +03:00
if update.Message.Text == "" {
setLocale(update.Message.From.LanguageCode)
update.Message.Text = localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: getMessageID(update.Message)})
}
2018-06-20 16:14:51 +03:00
nickname := update.Message.From.UserName
user := getUserByExternalID(update.Message.From.ID)
2018-06-15 14:09:52 +03:00
2018-06-20 16:14:51 +03:00
if update.Message.From.UserName == "" {
nickname = update.Message.From.FirstName
}
2018-06-20 16:14:51 +03:00
if user.Expired(config.UpdateInterval) || user.ID == 0 {
fileID, fileURL, err := GetFileIDAndURL(b.Token, update.Message.From.ID)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
2018-06-20 16:14:51 +03:00
if fileID != user.UserPhotoID && fileURL != "" {
picURL, err := UploadUserAvatar(fileURL)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
2018-06-20 16:14:51 +03:00
user.UserPhotoID = fileID
user.UserPhotoURL = picURL
}
2018-05-25 18:09:38 +03:00
2018-06-20 16:14:51 +03:00
if user.ExternalID == 0 {
user.ExternalID = update.Message.From.ID
}
2018-06-20 16:14:51 +03:00
err = user.save()
if err != nil {
raven.CaptureErrorAndWait(err, nil)
2018-06-20 16:14:51 +03:00
logger.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
2018-06-20 16:14:51 +03:00
}
2018-07-11 10:17:20 +03:00
lang := update.Message.From.LanguageCode
if len(update.Message.From.LanguageCode) > 2 {
lang = update.Message.From.LanguageCode[:2]
}
2018-06-20 16:14:51 +03:00
if config.Debug {
logger.Debugf("telegramWebhookHandler user %v", user)
}
snd := v1.SendData{
Message: v1.SendMessage{
Message: v1.Message{
ExternalID: strconv.Itoa(update.Message.MessageID),
Type: "text",
Text: update.Message.Text,
},
SentAt: time.Now(),
},
User: v1.User{
ExternalID: strconv.Itoa(update.Message.From.ID),
Nickname: nickname,
Firstname: update.Message.From.FirstName,
Avatar: user.UserPhotoURL,
Lastname: update.Message.From.LastName,
2018-07-11 10:17:20 +03:00
Language: lang,
2018-06-20 16:14:51 +03:00
},
Channel: b.Channel,
ExternalChatID: strconv.FormatInt(update.Message.Chat.ID, 10),
}
2018-07-13 15:57:10 +03:00
if update.Message.ReplyToMessage != nil {
2018-07-13 15:32:26 +03:00
snd.Quote = &v1.SendMessageRequestQuote{ExternalID: strconv.Itoa(update.Message.ReplyToMessage.MessageID)}
}
2018-06-20 16:14:51 +03:00
data, st, err := client.Messages(snd)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(token, err.Error(), st, data)
w.WriteHeader(http.StatusInternalServerError)
return
}
if config.Debug {
logger.Debugf("telegramWebhookHandler Type: SendMessage, Bot: %v, Message: %v, Response: %v", b.ID, snd, data)
2018-06-01 12:08:22 +03:00
}
2018-05-25 18:09:38 +03:00
}
if update.EditedMessage != nil {
2018-06-20 16:14:51 +03:00
if update.EditedMessage.Text == "" {
setLocale(update.EditedMessage.From.LanguageCode)
update.EditedMessage.Text = localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: getMessageID(update.Message)})
}
snd := v1.UpdateData{
Message: v1.UpdateMessage{
Message: v1.Message{
ExternalID: strconv.Itoa(update.EditedMessage.MessageID),
Type: "text",
Text: update.EditedMessage.Text,
2018-05-25 18:09:38 +03:00
},
2018-06-20 16:14:51 +03:00
},
Channel: b.Channel,
}
2018-06-20 16:14:51 +03:00
data, st, err := client.UpdateMessages(snd)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(token, err.Error(), st, data)
w.WriteHeader(http.StatusInternalServerError)
return
}
2018-06-20 16:14:51 +03:00
if config.Debug {
logger.Debugf("telegramWebhookHandler Type: UpdateMessage, Bot: %v, Message: %v, Response: %v", b.ID, snd, data)
2018-06-01 12:08:22 +03:00
}
2018-05-25 18:09:38 +03:00
}
w.WriteHeader(http.StatusOK)
}
func mgWebhookHandler(w http.ResponseWriter, r *http.Request) {
2018-06-08 13:57:51 +03:00
defer r.Body.Close()
clientID := r.Header.Get("Clientid")
if clientID == "" {
logger.Error("mgWebhookHandler clientID is empty")
w.WriteHeader(http.StatusBadRequest)
return
}
c := getConnection(clientID)
if !c.Active {
logger.Error(c.ClientID, "mgWebhookHandler: connection deactivated")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Connection deactivated"))
return
}
bytes, err := ioutil.ReadAll(r.Body)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
2018-06-01 14:46:07 +03:00
if config.Debug {
2018-06-01 14:57:48 +03:00
logger.Debugf("mgWebhookHandler request: %v", string(bytes))
2018-06-01 14:46:07 +03:00
}
var msg v1.WebhookRequest
err = json.Unmarshal(bytes, &msg)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
uid, _ := strconv.Atoi(msg.Data.ExternalMessageID)
2018-06-01 15:24:04 +03:00
cid, _ := strconv.ParseInt(msg.Data.ExternalChatID, 10, 64)
2018-06-20 16:14:51 +03:00
b := getBot(c.ID, msg.Data.ChannelID)
if b.ID == 0 {
2018-06-08 17:40:50 +03:00
logger.Error(msg.Data.ChannelID, "mgWebhookHandler: missing or deactivated")
w.WriteHeader(http.StatusBadRequest)
2018-06-08 12:13:02 +03:00
w.Write([]byte("missing or deactivated"))
return
}
bot, err := tgbotapi.NewBotAPI(b.Token)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
if msg.Type == "message_sent" {
2018-07-13 15:32:26 +03:00
m := tgbotapi.NewMessage(cid, msg.Data.Content)
if msg.Data.QuoteExternalID != "" {
qid, err := strconv.Atoi(msg.Data.QuoteExternalID)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
m.ReplyToMessageID = qid
}
msg, err := bot.Send(m)
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(err)
w.WriteHeader(http.StatusBadRequest)
return
}
2018-06-01 12:08:22 +03:00
if config.Debug {
2018-06-01 14:57:48 +03:00
logger.Debugf("mgWebhookHandler sent %v", msg)
2018-06-01 12:08:22 +03:00
}
2018-06-06 12:48:00 +03:00
rsp, err := json.Marshal(map[string]string{"external_message_id": strconv.Itoa(msg.MessageID)})
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(err)
return
}
if config.Debug {
logger.Debugf("mgWebhookHandler sent response %v", string(rsp))
2018-06-06 12:48:00 +03:00
}
w.WriteHeader(http.StatusOK)
2018-06-06 12:48:00 +03:00
w.Write(rsp)
}
if msg.Type == "message_updated" {
2018-06-01 15:24:04 +03:00
msg, err := bot.Send(tgbotapi.NewEditMessageText(cid, uid, msg.Data.Content))
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(err)
w.WriteHeader(http.StatusBadRequest)
return
}
2018-06-01 12:08:22 +03:00
if config.Debug {
2018-06-01 14:57:48 +03:00
logger.Debugf("mgWebhookHandler update %v", msg)
2018-06-01 12:08:22 +03:00
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("Message updated"))
}
if msg.Type == "message_deleted" {
2018-06-01 15:24:04 +03:00
msg, err := bot.Send(tgbotapi.NewDeleteMessage(cid, uid))
if err != nil {
raven.CaptureErrorAndWait(err, nil)
logger.Error(err)
w.WriteHeader(http.StatusBadRequest)
return
}
2018-06-01 12:08:22 +03:00
if config.Debug {
2018-06-01 14:57:48 +03:00
logger.Debugf("mgWebhookHandler delete %v", msg)
2018-06-01 12:08:22 +03:00
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("Message deleted"))
}
}
2018-06-08 12:13:02 +03:00
//GetFileIDAndURL function
func GetFileIDAndURL(token string, userID int) (fileID, fileURL string, err error) {
bot, err := tgbotapi.NewBotAPI(token)
if err != nil {
return
}
bot.Debug = config.Debug
res, err := bot.GetUserProfilePhotos(
tgbotapi.UserProfilePhotosConfig{
UserID: userID,
Limit: 1,
},
)
if err != nil {
return
}
2018-06-08 17:40:50 +03:00
if config.Debug {
logger.Debugf("GetFileIDAndURL Photos: %v", res.Photos)
}
if len(res.Photos) > 0 {
fileID = res.Photos[0][len(res.Photos[0])-1].FileID
fileURL, err = bot.GetFileDirectURL(fileID)
}
return
}
2018-06-08 12:13:02 +03:00
//UploadUserAvatar function
func UploadUserAvatar(url string) (picURLs3 string, err error) {
s3Config := &aws.Config{
Credentials: credentials.NewStaticCredentials(
config.ConfigAWS.AccessKeyID,
config.ConfigAWS.SecretAccessKey,
""),
Region: aws.String(config.ConfigAWS.Region),
}
s := session.Must(session.NewSession(s3Config))
uploader := s3manager.NewUploader(s)
resp, err := http.Get(url)
if err != nil {
return
}
2018-06-08 13:57:51 +03:00
defer resp.Body.Close()
if resp.StatusCode >= http.StatusBadRequest {
return "", errors.New(fmt.Sprintf("get: %v code: %v", url, resp.StatusCode))
}
result, err := uploader.Upload(&s3manager.UploadInput{
Bucket: aws.String(config.ConfigAWS.Bucket),
2018-06-08 13:57:51 +03:00
Key: aws.String(fmt.Sprintf("%v/%v.jpg", config.ConfigAWS.FolderName, GenerateToken())),
Body: resp.Body,
ContentType: aws.String(config.ConfigAWS.ContentType),
ACL: aws.String("public-read"),
})
if err != nil {
return
}
picURLs3 = result.Location
return
}
2018-06-20 16:14:51 +03:00
func getMessageID(data *tgbotapi.Message) string {
switch {
case data.Sticker != nil:
return "sticker"
case data.Audio != nil:
return "audio"
case data.Contact != nil:
return "contact"
case data.Document != nil:
return "document"
case data.Location != nil:
return "location"
case data.Video != nil:
return "video"
case data.Voice != nil:
return "voice"
case data.Photo != nil:
return "photo"
default:
return "undefined"
}
}