From 74b5205768acdfb21770ea271142e7a09dfa356c Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Wed, 23 May 2018 18:03:11 +0300 Subject: [PATCH 1/4] add telegram webhook, improve template, minor fixes --- config.go | 14 ++- routing.go | 179 ++++++++++++++++++++++++++++++------- telegram.go | 1 + templates/form.html | 15 ++-- templates/home.html | 11 +-- templates/layout.html | 8 +- translate/translate.en.yml | 8 +- translate/translate.ru.yml | 8 +- web/script.js | 20 +++-- web/style.css | 10 +++ 10 files changed, 207 insertions(+), 67 deletions(-) diff --git a/config.go b/config.go index 8190ae0..cb5aae8 100644 --- a/config.go +++ b/config.go @@ -10,10 +10,11 @@ import ( // TransportConfig struct type TransportConfig struct { - LogLevel logging.Level `yaml:"log_level"` - Database DatabaseConfig `yaml:"database"` - SentryDSN string `yaml:"sentry_dsn"` - HTTPServer HTTPServerConfig `yaml:"http_server"` + LogLevel logging.Level `yaml:"log_level"` + Database DatabaseConfig `yaml:"database"` + SentryDSN string `yaml:"sentry_dsn"` + HTTPServer HTTPServerConfig `yaml:"http_server"` + TelegramConfig TelegramConfig `yaml:"telegram"` } // DatabaseConfig struct @@ -32,6 +33,11 @@ type HTTPServerConfig struct { Listen string `yaml:"listen"` } +// TelegramConfig struct +type TelegramConfig struct { + Debug bool `yaml:"debug"` +} + // LoadConfig read configuration file func LoadConfig(path string) *TransportConfig { var err error diff --git a/routing.go b/routing.go index 421939b..8ec651c 100644 --- a/routing.go +++ b/routing.go @@ -8,8 +8,11 @@ import ( "io/ioutil" "net/http" "regexp" + "strconv" + "time" "github.com/getsentry/raven-go" + "github.com/go-telegram-bot-api/telegram-bot-api" "github.com/nicksnyder/go-i18n/v2/i18n" "github.com/retailcrm/api-client-go/v5" "github.com/retailcrm/mg-transport-api-client-go/v1" @@ -19,7 +22,7 @@ import ( var ( templates = template.Must(template.ParseFiles("templates/layout.html", "templates/form.html", "templates/home.html")) - validPath = regexp.MustCompile("^/(save|settings)/([a-zA-Z0-9]+)$") + validPath = regexp.MustCompile(`^/(save|settings|telegram)/([a-zA-Z0-9-:_+]+)$`) localizer *i18n.Localizer bundle = &i18n.Bundle{DefaultLanguage: language.English} matcher = language.NewMatcher([]language.Tag{ @@ -62,10 +65,16 @@ func setWrapperRoutes() { } func renderTemplate(w http.ResponseWriter, tmpl string, c interface{}) { - err := templates.ExecuteTemplate(w, tmpl+".html", c) + tm, err := template.ParseFiles("templates/layout.html", "templates/"+tmpl+".html") if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) + } + + err = tm.Execute(w, &c) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + http.Error(w, err.Error(), http.StatusBadRequest) } } @@ -101,7 +110,7 @@ func connectHandler(w http.ResponseWriter, r *http.Request) { func addBotHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -109,25 +118,41 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &b) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } if b.Token == "" { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "no_bot_token"}), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "no_bot_token"}), http.StatusBadRequest) return } cl, _ := getBotByToken(b.Token) if cl.ID != 0 { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "bot_already_created"}), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "bot_already_created"}), http.StatusBadRequest) return } bot, err := GetBotInfo(b.Token) if err != nil { logger.Error(b.Token, err.Error()) - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_token"}), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_token"}), http.StatusBadRequest) + return + } + + bot.Debug = false + + _, err = bot.SetWebhook(tgbotapi.NewWebhook("https://" + config.HTTPServer.Host + "/telegram/" + bot.Token)) + if err != nil { + logger.Error(b.Token, err.Error()) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_webhook"}), http.StatusBadRequest) + return + } + + _, err = bot.GetWebhookInfo() + if err != nil { + logger.Error(b.Token, err.Error()) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_webhook"}), http.StatusBadRequest) return } @@ -135,14 +160,14 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { c, err := getConnection(b.ClientID) if err != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_find_account"}), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) logger.Error(b.ClientID, err.Error()) return } if c.MGURL == "" || c.MGToken == "" { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_find_account"}), http.StatusInternalServerError) - logger.Error(b.ClientID) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) + logger.Error(b.ClientID, "MGURL or MGToken is empty") return } @@ -159,7 +184,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { var client = v1.New(c.MGURL, c.MGToken) data, status, err := client.ActivateTransportChannel(ch) if status != http.StatusCreated { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_activating_channel"}), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_activating_channel"}), http.StatusBadRequest) logger.Error(c.APIURL, status, err.Error(), data) return } @@ -170,7 +195,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { err = b.createBot() if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -182,7 +207,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { func activityBotHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -190,7 +215,7 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &b) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -207,14 +232,14 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { c, err := getConnection(b.ClientID) if err != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_find_account"}), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) logger.Error(b.ClientID, err.Error()) return } if c.MGURL == "" || c.MGToken == "" { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_find_account"}), http.StatusInternalServerError) - logger.Error(b.ClientID, "not find account") + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) + logger.Error(b.ClientID, "MGURL or MGToken is empty") return } @@ -223,14 +248,14 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { if b.Active { data, status, err := client.DeactivateTransportChannel(ch.ID) if status > http.StatusOK { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_deactivating_channel"}), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_deactivating_channel"}), http.StatusBadRequest) logger.Error(b.ClientID, status, err.Error(), data) return } } else { data, status, err := client.ActivateTransportChannel(ch) if status > http.StatusCreated { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_activating_channel"}), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_activating_channel"}), http.StatusBadRequest) logger.Error(b.ClientID, status, err.Error(), data) return } @@ -239,7 +264,7 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { err = b.setBotActivity() if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -252,7 +277,7 @@ func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { p, err := getConnection(uid) if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -294,7 +319,7 @@ func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { func saveHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -302,7 +327,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &c) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -316,12 +341,12 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { err = c.saveConnection() if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) - w.Write([]byte("/settings/" + r.FormValue("clientId"))) + w.Write([]byte(localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "successful"}))) } func createHandler(w http.ResponseWriter, r *http.Request) { @@ -329,7 +354,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -337,7 +362,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &c) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -416,16 +441,30 @@ func createHandler(w http.ResponseWriter, r *http.Request) { c.MGURL = data.Info["baseUrl"] c.MGToken = data.Info["token"] + c.Active = true err = c.createConnection() if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_connection"}), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_connection"}), http.StatusBadRequest) return } + res := struct { + Url string + Message string + }{ + Url: "/settings/" + c.ClientID, + Message: localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "successful"}), + } + + jss, err := json.Marshal(res) + if err != nil { + logger.Error(c.APIURL, err) + } + w.WriteHeader(http.StatusFound) - w.Write([]byte("/settings/" + c.ClientID)) + w.Write(jss) } func activityHandler(w http.ResponseWriter, r *http.Request) { @@ -483,3 +522,83 @@ func validate(c Connection) error { return nil } + +func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string) { + t := time.Now() + b, err := getBotByToken(token) + if err != nil { + logger.Error(token, err) + } + + if !b.Active { + logger.Error(token, err) + } + + bot, err := GetBotInfo(token) + if err != nil { + logger.Error(token, err) + } + + bot.Debug = false + + bytes, _ := ioutil.ReadAll(r.Body) + + var update tgbotapi.Update + json.Unmarshal(bytes, &update) + + c, err := getConnection(b.ClientID) + if err != nil { + logger.Error(token, err.Error()) + return + } + + if c.MGURL == "" || c.MGToken == "" { + logger.Error(token, "MGURL or MGToken is empty") + return + } + + var client = v1.New(c.MGURL, c.MGToken) + + if update.Message != nil { + 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: update.Message.From.UserName, + Firstname: update.Message.From.FirstName, + }, + Channel: b.Channel, + } + + data, status, err := client.Messages(snd) + if err != nil { + logger.Error(token, err.Error(), status, data) + } + } + + if update.EditedMessage != nil { + snd := v1.UpdateData{ + Message: v1.UpdateMessage{ + Message: v1.Message{ + ExternalID: strconv.Itoa(update.EditedMessage.MessageID), + Type: "text", + Text: update.EditedMessage.Text, + }, + }, + Channel: b.Channel, + } + + data, status, err := client.UpdateMessages(snd) + if err != nil { + logger.Error(token, err.Error(), status, data) + } + } + fmt.Println("Time working: ", time.Since(t)) +} diff --git a/telegram.go b/telegram.go index 2a79e55..2901a35 100644 --- a/telegram.go +++ b/telegram.go @@ -9,6 +9,7 @@ import ( func setTransportRoutes() { http.HandleFunc("/add-bot/", addBotHandler) http.HandleFunc("/activity-bot/", activityBotHandler) + http.HandleFunc("/telegram/", makeHandler(telegramWebhookHandler)) } // GetBotInfo function diff --git a/templates/form.html b/templates/form.html index 02d5190..f7f8f3d 100644 --- a/templates/form.html +++ b/templates/form.html @@ -1,17 +1,14 @@ -{{template "header"}} +{{define "body"}}
-
+ -
-
-
-
+
@@ -36,7 +33,7 @@
- +
@@ -51,7 +48,7 @@
- +
@@ -77,4 +74,4 @@ -{{template "footer"}} +{{end}} diff --git a/templates/home.html b/templates/home.html index 92f3fb5..2e4dd6e 100644 --- a/templates/home.html +++ b/templates/home.html @@ -1,9 +1,6 @@ -{{template "header"}} -
-
-
-
-
+{{define "body"}} +
+
@@ -25,4 +22,4 @@
-{{template "footer"}} +{{end}} diff --git a/templates/layout.html b/templates/layout.html index 297f802..4089a39 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -1,9 +1,8 @@ -{{ define "header" }} - + {{.Locale.Title}} @@ -13,13 +12,10 @@
-{{ end }} - -{{ define "footer" }} + {{template "body" .}}
-{{ end }} diff --git a/translate/translate.en.yml b/translate/translate.en.yml index 3902433..7af5c92 100644 --- a/translate/translate.en.yml +++ b/translate/translate.en.yml @@ -5,12 +5,15 @@ table_name: Bot name table_token: Bot token table_activity: Activity api_key: API Key +add_bot: Add bot +title: Telegram transport for retailCRM +successful: Data successfully updated no_bot_token: Enter the bot token wrong_data: Incorrect data set_method: Set POST method bot_already_created: Bot already created -not_find_account: Could not find account, please contact technical support +not_found_account: The account could not be found, contact technical support error_activating_channel: Error while activating the channel error_deactivating_channel: Error while deactivating the channel incorrect_url_key: Enter the correct CRM url or apiKey @@ -20,5 +23,4 @@ connection_already_created: Connection already created missing_url_key: Missing crm url or apiKey incorrect_url: Enter the correct CRM url incorrect_token: Set correct bot token -add_bot: Add bot -title: Telegram transport for retailCRM +error_creating_webhook: Error while creating webhook diff --git a/translate/translate.ru.yml b/translate/translate.ru.yml index 0aae946..6a79f5b 100644 --- a/translate/translate.ru.yml +++ b/translate/translate.ru.yml @@ -5,12 +5,15 @@ table_name: Имя table_token: Токен table_activity: Активность api_key: API Ключ +add_bot: Добавить бота +title: Модуль подключения Telegram к retailCRM +successful: Данные успешно обновлены no_bot_token: Введите токен wrong_data: Неверные данные set_method: Установить метод POST bot_already_created: Бот уже создан -not_find_account: Не удалось найти учетную запись, обратитесь в службу технической поддержки +not_found_account: Не удалось найти учетную запись, обратитесь в службу технической поддержки error_activating_channel: Ошибка при активации канала error_deactivating_channel: Ошибка при отключении канала incorrect_url_key: Введите корректный URL или apiKey @@ -20,5 +23,4 @@ connection_already_created: Соединение уже создано missing_url_key: Отсутствует URL или apiKey incorrect_url: Введите корректный URL CRM incorrect_token: Установите корректный токен -add_bot: Добавить бота -title: Модуль подключения Telegram к retailCRM +error_creating_webhook: Ошибка при создании webhook diff --git a/web/script.js b/web/script.js index 0a9a99f..a94887f 100644 --- a/web/script.js +++ b/web/script.js @@ -14,8 +14,8 @@ $("#save").on("submit", function(e) { send( $(this).attr('action'), formDataToObj($(this).serializeArray()), - function () { - return 0; + function (data) { + M.toast({html: data}); } ) }); @@ -31,6 +31,7 @@ $("#add-bot").on("submit", function(e) { bots.removeClass("hide") } $("#bots tbody").append(getBotTemplate(data)); + $("#token").val(""); } ) }); @@ -56,7 +57,6 @@ $(document).on("click", ".activity-bot", function(e) { }); function send(url, data, callback) { - $('#msg').empty(); $.ajax({ url: url, data: JSON.stringify(data), @@ -65,12 +65,14 @@ function send(url, data, callback) { error: function (res){ if (res.status < 400) { if (res.responseText) { + let resObj = JSON.parse(res.responseText); + localStorage.setItem("createdMsg", resObj.Message); + document.location.replace( - location.protocol.concat("//").concat(window.location.host) + res.responseText + location.protocol.concat("//").concat(window.location.host) + resObj.Url ); } } else { - //$('#msg').html(`

${res.responseText}

`); M.toast({html: res.responseText}) } } @@ -106,4 +108,12 @@ $( document ).ready(function() { if ($("table tbody").children().length === 0) { $("#bots").addClass("hide"); } + + let createdMsg = localStorage.getItem("createdMsg"); + if (createdMsg) { + setTimeout(function() { + M.toast({html: createdMsg}); + localStorage.removeItem("createdMsg"); + }, 1000); + } }); diff --git a/web/style.css b/web/style.css index cbda80d..69bda59 100644 --- a/web/style.css +++ b/web/style.css @@ -6,6 +6,16 @@ text-align: right; } +#tab{ + width: 50%; + margin: 0 auto 23px; +} + +.tab-el-center{ + width: 67%; + margin: 0 auto; +} + #bots .activity-bot{ float: right; } From adff7e14b4204ea50f5d7b49be568e8d6c147731 Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Thu, 24 May 2018 17:16:21 +0300 Subject: [PATCH 2/4] correct response statuses --- routing.go | 135 +++++++++++++++++++++++++++---------- translate/translate.en.yml | 1 + translate/translate.ru.yml | 1 + web/script.js | 6 +- 4 files changed, 103 insertions(+), 40 deletions(-) diff --git a/routing.go b/routing.go index 8ec651c..80214bb 100644 --- a/routing.go +++ b/routing.go @@ -68,13 +68,14 @@ func renderTemplate(w http.ResponseWriter, tmpl string, c interface{}) { tm, err := template.ParseFiles("templates/layout.html", "templates/"+tmpl+".html") if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusBadRequest) + http.Error(w, err.Error(), http.StatusInternalServerError) + return } err = tm.Execute(w, &c) if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusBadRequest) + http.Error(w, err.Error(), http.StatusInternalServerError) } } @@ -110,7 +111,8 @@ func connectHandler(w http.ResponseWriter, r *http.Request) { func addBotHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -118,7 +120,8 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &b) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -127,7 +130,12 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { return } - cl, _ := getBotByToken(b.Token) + cl, err := getBotByToken(b.Token) + if err != nil { + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "no_bot_token"}), http.StatusBadRequest) + return + } + if cl.ID != 0 { http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "bot_already_created"}), http.StatusBadRequest) return @@ -194,12 +202,18 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { err = b.createBot() if err != nil { - raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusBadRequest) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_bot"}), http.StatusBadRequest) + logger.Error(c.APIURL, err.Error()) + return + } + + jsonString, err := json.Marshal(b) + if err != nil { + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_bot"}), http.StatusBadRequest) + logger.Error(c.APIURL, err.Error()) return } - jsonString, _ := json.Marshal(b) w.WriteHeader(http.StatusCreated) w.Write(jsonString) } @@ -207,7 +221,8 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { func activityBotHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -215,7 +230,8 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &b) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -263,7 +279,7 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { err = b.setBotActivity() if err != nil { - raven.CaptureErrorAndWait(err, nil) + logger.Error(b.ClientID, err.Error()) http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -276,8 +292,8 @@ func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { p, err := getConnection(uid) if err != nil { - raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusBadRequest) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) + logger.Error(p.ClientID, err.Error()) return } @@ -288,18 +304,13 @@ func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { bots := Bots{} bots.getBotsByClientID(uid) - client := v5.New(p.APIURL, p.APIKEY) - sites, _, _ := client.Sites() - res := struct { Conn *Connection Bots Bots - Sites map[string]v5.Site Locale map[string]interface{} }{ p, bots, - sites.Sites, map[string]interface{}{ "ButConnect": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "but_connect"}), "ApiKey": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "api_key"}), @@ -319,7 +330,8 @@ func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { func saveHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -327,7 +339,8 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &c) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -340,8 +353,8 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { err = c.saveConnection() if err != nil { - raven.CaptureErrorAndWait(err, nil) http.Error(w, err.Error(), http.StatusBadRequest) + logger.Error(c.APIURL, err.Error()) return } @@ -354,7 +367,8 @@ func createHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -362,7 +376,8 @@ func createHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &c) if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -375,7 +390,13 @@ func createHandler(w http.ResponseWriter, r *http.Request) { return } - cl, _ := getConnectionByURL(c.APIURL) + cl, err := getConnectionByURL(c.APIURL) + if err != nil { + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) + logger.Error(cl.ClientID, err.Error()) + return + } + if cl.ID != 0 { http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "connection_already_created"}), http.StatusBadRequest) return @@ -385,7 +406,8 @@ func createHandler(w http.ResponseWriter, r *http.Request) { cr, status, errr := client.APICredentials() if errr.RuntimeErr != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_url_key"}), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusInternalServerError) logger.Error(c.APIURL, status, errr.RuntimeErr, cr) return } @@ -428,7 +450,8 @@ func createHandler(w http.ResponseWriter, r *http.Request) { data, status, errr := client.IntegrationModuleEdit(integration) if errr.RuntimeErr != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_integration"}), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_integration"}), http.StatusInternalServerError) logger.Error(c.APIURL, status, errr.RuntimeErr, data) return } @@ -460,7 +483,9 @@ func createHandler(w http.ResponseWriter, r *http.Request) { jss, err := json.Marshal(res) if err != nil { - logger.Error(c.APIURL, err) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_connection"}), http.StatusBadRequest) + return } w.WriteHeader(http.StatusFound) @@ -473,7 +498,12 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { res.Error = localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "set_method"}) - jsonString, _ := json.Marshal(res) + jsonString, err := json.Marshal(res) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + logger.Error(err) + return + } w.Write(jsonString) return } @@ -482,7 +512,12 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { if err != nil { raven.CaptureErrorAndWait(err, nil) res.Error = localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_data"}) - jsonString, _ := json.Marshal(res) + jsonString, err := json.Marshal(res) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + logger.Error(err) + return + } w.Write(jsonString) return } @@ -493,7 +528,12 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { if err != nil { raven.CaptureErrorAndWait(err, nil) res.Error = localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_data"}) - jsonString, _ := json.Marshal(res) + jsonString, err := json.Marshal(res) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + logger.Error(err) + return + } w.Write(jsonString) return } @@ -501,13 +541,24 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { if err := rec.setConnectionActivity(); err != nil { raven.CaptureErrorAndWait(err, nil) res.Error = localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_data"}) - jsonString, _ := json.Marshal(res) + jsonString, err := json.Marshal(res) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + logger.Error(err) + return + } w.Write(jsonString) return } res.Success = true - jsonString, _ := json.Marshal(res) + jsonString, err := json.Marshal(res) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + logger.Error(err) + return + } + w.Write(jsonString) } @@ -524,27 +575,38 @@ func validate(c Connection) error { } func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string) { - t := time.Now() b, err := getBotByToken(token) if err != nil { logger.Error(token, err) + return } if !b.Active { - logger.Error(token, err) + logger.Error(token, "deactivated") + return } bot, err := GetBotInfo(token) if err != nil { logger.Error(token, err) + return } bot.Debug = false - bytes, _ := ioutil.ReadAll(r.Body) + bytes, err := ioutil.ReadAll(r.Body) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + return + } var update tgbotapi.Update - json.Unmarshal(bytes, &update) + + err = json.Unmarshal(bytes, &update) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + return + } c, err := getConnection(b.ClientID) if err != nil { @@ -600,5 +662,4 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string logger.Error(token, err.Error(), status, data) } } - fmt.Println("Time working: ", time.Since(t)) } diff --git a/translate/translate.en.yml b/translate/translate.en.yml index 7af5c92..c8625fe 100644 --- a/translate/translate.en.yml +++ b/translate/translate.en.yml @@ -24,3 +24,4 @@ missing_url_key: Missing crm url or apiKey incorrect_url: Enter the correct CRM url incorrect_token: Set correct bot token error_creating_webhook: Error while creating webhook +error_creating_bot: Error while creating bot diff --git a/translate/translate.ru.yml b/translate/translate.ru.yml index 6a79f5b..4b7e786 100644 --- a/translate/translate.ru.yml +++ b/translate/translate.ru.yml @@ -24,3 +24,4 @@ missing_url_key: Отсутствует URL или apiKey incorrect_url: Введите корректный URL CRM incorrect_token: Установите корректный токен error_creating_webhook: Ошибка при создании webhook +error_creating_bot: Ошибка при создании бота diff --git a/web/script.js b/web/script.js index a94887f..e78d8bf 100644 --- a/web/script.js +++ b/web/script.js @@ -66,7 +66,7 @@ function send(url, data, callback) { if (res.status < 400) { if (res.responseText) { let resObj = JSON.parse(res.responseText); - localStorage.setItem("createdMsg", resObj.Message); + sessionStorage.setItem("createdMsg", resObj.Message); document.location.replace( location.protocol.concat("//").concat(window.location.host) + resObj.Url @@ -109,11 +109,11 @@ $( document ).ready(function() { $("#bots").addClass("hide"); } - let createdMsg = localStorage.getItem("createdMsg"); + let createdMsg = sessionStorage.getItem("createdMsg"); if (createdMsg) { setTimeout(function() { M.toast({html: createdMsg}); - localStorage.removeItem("createdMsg"); + sessionStorage.removeItem("createdMsg"); }, 1000); } }); From 91e1bc6a36a64531ab5ea9d0d28296199521a751 Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Thu, 24 May 2018 18:08:48 +0300 Subject: [PATCH 3/4] minor fixes --- repository.go | 12 ++--- routing.go | 89 +++++++++++++------------------------- translate/translate.en.yml | 3 +- translate/translate.ru.yml | 3 +- 4 files changed, 41 insertions(+), 66 deletions(-) diff --git a/repository.go b/repository.go index 5ac999c..609ada7 100644 --- a/repository.go +++ b/repository.go @@ -1,17 +1,17 @@ package main -func getConnection(uid string) (*Connection, error) { +func getConnection(uid string) *Connection { var connection Connection orm.DB.First(&connection, "client_id = ?", uid) - return &connection, nil + return &connection } -func getConnectionByURL(urlCrm string) (*Connection, error) { +func getConnectionByURL(urlCrm string) *Connection { var connection Connection orm.DB.First(&connection, "api_url = ?", urlCrm) - return &connection, nil + return &connection } func (c *Connection) setConnectionActivity() error { @@ -26,11 +26,11 @@ func (c *Connection) saveConnection() error { return orm.DB.Model(c).Where("client_id = ?", c.ClientID).Update(c).Error } -func getBotByToken(token string) (*Bot, error) { +func getBotByToken(token string) *Bot { var bot Bot orm.DB.First(&bot, "token = ?", token) - return &bot, nil + return &bot } func (b *Bot) createBot() error { diff --git a/routing.go b/routing.go index 80214bb..960049a 100644 --- a/routing.go +++ b/routing.go @@ -112,7 +112,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_adding_bot"}), http.StatusInternalServerError) return } @@ -121,7 +121,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &b) if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_adding_bot"}), http.StatusInternalServerError) return } @@ -130,12 +130,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { return } - cl, err := getBotByToken(b.Token) - if err != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "no_bot_token"}), http.StatusBadRequest) - return - } - + cl := getBotByToken(b.Token) if cl.ID != 0 { http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "bot_already_created"}), http.StatusBadRequest) return @@ -166,13 +161,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { b.Name = GetBotName(bot) - c, err := getConnection(b.ClientID) - if err != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) - logger.Error(b.ClientID, err.Error()) - return - } - + c := getConnection(b.ClientID) if c.MGURL == "" || c.MGToken == "" { http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) logger.Error(b.ClientID, "MGURL or MGToken is empty") @@ -202,14 +191,16 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { err = b.createBot() if err != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_bot"}), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_adding_bot"}), http.StatusInternalServerError) logger.Error(c.APIURL, err.Error()) return } jsonString, err := json.Marshal(b) if err != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_bot"}), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_adding_bot"}), http.StatusInternalServerError) logger.Error(c.APIURL, err.Error()) return } @@ -222,7 +213,7 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -231,7 +222,7 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &b) if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -246,13 +237,7 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { }, } - c, err := getConnection(b.ClientID) - if err != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) - logger.Error(b.ClientID, err.Error()) - return - } - + c := getConnection(b.ClientID) if c.MGURL == "" || c.MGToken == "" { http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) logger.Error(b.ClientID, "MGURL or MGToken is empty") @@ -280,7 +265,7 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { err = b.setBotActivity() if err != nil { logger.Error(b.ClientID, err.Error()) - http.Error(w, err.Error(), http.StatusBadRequest) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -290,19 +275,18 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { setLocale(r.Header.Get("Accept-Language")) - p, err := getConnection(uid) - if err != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) - logger.Error(p.ClientID, err.Error()) - return - } - + p := getConnection(uid) if p.ID == 0 { http.Redirect(w, r, "/", http.StatusFound) } bots := Bots{} - bots.getBotsByClientID(uid) + err := bots.getBotsByClientID(uid) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) + return + } res := struct { Conn *Connection @@ -331,7 +315,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -340,7 +324,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &c) if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -353,7 +337,8 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { err = c.saveConnection() if err != nil { - http.Error(w, err.Error(), http.StatusBadRequest) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) logger.Error(c.APIURL, err.Error()) return } @@ -368,7 +353,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -377,7 +362,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &c) if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -390,13 +375,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { return } - cl, err := getConnectionByURL(c.APIURL) - if err != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusBadRequest) - logger.Error(cl.ClientID, err.Error()) - return - } - + cl := getConnectionByURL(c.APIURL) if cl.ID != 0 { http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "connection_already_created"}), http.StatusBadRequest) return @@ -469,7 +448,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { err = c.createConnection() if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_connection"}), http.StatusBadRequest) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_connection"}), http.StatusInternalServerError) return } @@ -575,9 +554,9 @@ func validate(c Connection) error { } func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string) { - b, err := getBotByToken(token) - if err != nil { - logger.Error(token, err) + b := getBotByToken(token) + if b.ID == 0 { + logger.Error(token, "missing") return } @@ -589,7 +568,6 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string bot, err := GetBotInfo(token) if err != nil { logger.Error(token, err) - return } bot.Debug = false @@ -608,12 +586,7 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string return } - c, err := getConnection(b.ClientID) - if err != nil { - logger.Error(token, err.Error()) - return - } - + c := getConnection(b.ClientID) if c.MGURL == "" || c.MGToken == "" { logger.Error(token, "MGURL or MGToken is empty") return diff --git a/translate/translate.en.yml b/translate/translate.en.yml index c8625fe..b7521a9 100644 --- a/translate/translate.en.yml +++ b/translate/translate.en.yml @@ -24,4 +24,5 @@ missing_url_key: Missing crm url or apiKey incorrect_url: Enter the correct CRM url incorrect_token: Set correct bot token error_creating_webhook: Error while creating webhook -error_creating_bot: Error while creating bot +error_adding_bot: Error while adding bot +error_save: An error occurred while saving, contact technical support diff --git a/translate/translate.ru.yml b/translate/translate.ru.yml index 4b7e786..5d1b65f 100644 --- a/translate/translate.ru.yml +++ b/translate/translate.ru.yml @@ -24,4 +24,5 @@ missing_url_key: Отсутствует URL или apiKey incorrect_url: Введите корректный URL CRM incorrect_token: Установите корректный токен error_creating_webhook: Ошибка при создании webhook -error_creating_bot: Ошибка при создании бота +error_adding_bot: Ошибка при добавлении бота +error_save: Ошибка при сохранении, обратитесь в службу технической поддержки From 84cf4ae56d7988883b790ea195587a119c18c7d1 Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Fri, 25 May 2018 15:56:31 +0300 Subject: [PATCH 4/4] add tests, improve receiving updates from telegram --- config.go | 14 ++--- routing.go | 148 ++++++++++++++++++++++++++---------------------- routing_test.go | 133 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 197 insertions(+), 98 deletions(-) diff --git a/config.go b/config.go index cb5aae8..8190ae0 100644 --- a/config.go +++ b/config.go @@ -10,11 +10,10 @@ import ( // TransportConfig struct type TransportConfig struct { - LogLevel logging.Level `yaml:"log_level"` - Database DatabaseConfig `yaml:"database"` - SentryDSN string `yaml:"sentry_dsn"` - HTTPServer HTTPServerConfig `yaml:"http_server"` - TelegramConfig TelegramConfig `yaml:"telegram"` + LogLevel logging.Level `yaml:"log_level"` + Database DatabaseConfig `yaml:"database"` + SentryDSN string `yaml:"sentry_dsn"` + HTTPServer HTTPServerConfig `yaml:"http_server"` } // DatabaseConfig struct @@ -33,11 +32,6 @@ type HTTPServerConfig struct { Listen string `yaml:"listen"` } -// TelegramConfig struct -type TelegramConfig struct { - Debug bool `yaml:"debug"` -} - // LoadConfig read configuration file func LoadConfig(path string) *TransportConfig { var err error diff --git a/routing.go b/routing.go index 960049a..bacaacd 100644 --- a/routing.go +++ b/routing.go @@ -109,6 +109,7 @@ func connectHandler(w http.ResponseWriter, r *http.Request) { } func addBotHandler(w http.ResponseWriter, r *http.Request) { + setLocale(r.Header.Get("Accept-Language")) body, err := ioutil.ReadAll(r.Body) if err != nil { raven.CaptureErrorAndWait(err, nil) @@ -312,6 +313,8 @@ func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { } func saveHandler(w http.ResponseWriter, r *http.Request) { + setLocale(r.Header.Get("Accept-Language")) + body, err := ioutil.ReadAll(r.Body) if err != nil { raven.CaptureErrorAndWait(err, nil) @@ -385,7 +388,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { cr, status, errr := client.APICredentials() if errr.RuntimeErr != nil { - raven.CaptureErrorAndWait(err, nil) + raven.CaptureErrorAndWait(errr.RuntimeErr, nil) http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_found_account"}), http.StatusInternalServerError) logger.Error(c.APIURL, status, errr.RuntimeErr, cr) return @@ -429,7 +432,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { data, status, errr := client.IntegrationModuleEdit(integration) if errr.RuntimeErr != nil { - raven.CaptureErrorAndWait(err, nil) + raven.CaptureErrorAndWait(errr.RuntimeErr, nil) http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_integration"}), http.StatusInternalServerError) logger.Error(c.APIURL, status, errr.RuntimeErr, data) return @@ -554,85 +557,96 @@ func validate(c Connection) error { } func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string) { - b := getBotByToken(token) - if b.ID == 0 { - logger.Error(token, "missing") - return - } - - if !b.Active { - logger.Error(token, "deactivated") - return - } - - bot, err := GetBotInfo(token) - if err != nil { - logger.Error(token, err) - } - - bot.Debug = false - + ok := make(chan bool) bytes, err := ioutil.ReadAll(r.Body) if err != nil { raven.CaptureErrorAndWait(err, nil) + logger.Error(token, err) return } - var update tgbotapi.Update - - err = json.Unmarshal(bytes, &update) - if err != nil { - raven.CaptureErrorAndWait(err, nil) - return - } - - c := getConnection(b.ClientID) - if c.MGURL == "" || c.MGToken == "" { - logger.Error(token, "MGURL or MGToken is empty") - return - } - - var client = v1.New(c.MGURL, c.MGToken) - - if update.Message != nil { - 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: update.Message.From.UserName, - Firstname: update.Message.From.FirstName, - }, - Channel: b.Channel, + go func() { + b := getBotByToken(token) + if b.ID == 0 { + logger.Error(token, "missing") + return } - data, status, err := client.Messages(snd) + if !b.Active { + logger.Error(token, "deactivated") + return + } + + var update tgbotapi.Update + + err = json.Unmarshal(bytes, &update) if err != nil { - logger.Error(token, err.Error(), status, data) + raven.CaptureErrorAndWait(err, nil) + logger.Error(token, err) + return } - } - if update.EditedMessage != nil { - snd := v1.UpdateData{ - Message: v1.UpdateMessage{ - Message: v1.Message{ - ExternalID: strconv.Itoa(update.EditedMessage.MessageID), - Type: "text", - Text: update.EditedMessage.Text, + c := getConnection(b.ClientID) + if c.MGURL == "" || c.MGToken == "" { + logger.Error(token, "MGURL or MGToken is empty") + return + } + + var client = v1.New(c.MGURL, c.MGToken) + + if update.Message != nil { + snd := v1.SendData{ + Message: v1.SendMessage{ + Message: v1.Message{ + ExternalID: strconv.Itoa(update.Message.MessageID), + Type: "text", + Text: update.Message.Text, + }, + SentAt: time.Now(), }, - }, - Channel: b.Channel, + User: v1.User{ + ExternalID: strconv.Itoa(update.Message.From.ID), + Nickname: update.Message.From.UserName, + Firstname: update.Message.From.FirstName, + }, + Channel: b.Channel, + } + + data, status, err := client.Messages(snd) + if err != nil { + logger.Error(token, err.Error(), status, data) + ok <- false + return + } } - data, status, err := client.UpdateMessages(snd) - if err != nil { - logger.Error(token, err.Error(), status, data) + if update.EditedMessage != nil { + snd := v1.UpdateData{ + Message: v1.UpdateMessage{ + Message: v1.Message{ + ExternalID: strconv.Itoa(update.EditedMessage.MessageID), + Type: "text", + Text: update.EditedMessage.Text, + }, + }, + Channel: b.Channel, + } + + data, status, err := client.UpdateMessages(snd) + if err != nil { + logger.Error(token, err.Error(), status, data) + ok <- false + return + } } + + ok <- true + }() + + if <-ok { + w.WriteHeader(http.StatusOK) + w.Write([]byte("SendMessage")) + } else { + w.WriteHeader(http.StatusBadRequest) } } diff --git a/routing_test.go b/routing_test.go index ed2e7ef..bbff5ec 100644 --- a/routing_test.go +++ b/routing_test.go @@ -3,16 +3,24 @@ package main import ( "net/http" "net/http/httptest" + "strings" "testing" - "strings" - - "encoding/json" - "github.com/h2non/gock" - "github.com/retailcrm/mg-transport-api-client-go/v1" ) +func init() { + c := Connection{ + ClientID: "123123", + APIKEY: "test", + APIURL: "https://test.retailcrm.ru", + MGURL: "https://test.retailcrm.pro", + MGToken: "test-token", + Active: true, + } + + c.createConnection() +} func TestRouting_connectHandler(t *testing.T) { req, err := http.NewRequest("GET", "/", nil) if err != nil { @@ -34,40 +42,123 @@ func TestRouting_addBotHandler(t *testing.T) { defer gock.Off() gock.New("https://api.telegram.org"). - Post("/botbot123:test/getMe"). + Post("/bot123123:Qwerty/getMe"). Reply(200). BodyString(`{"ok":true,"result":{"id":123,"is_bot":true,"first_name":"Test","username":"TestBot"}}`) - ch := v1.Channel{ - Type: "telegram", - Events: []string{ - "message_sent", - "message_updated", - "message_deleted", - "message_read", - }, - } - str, _ := json.Marshal(ch) + gock.New("https://api.telegram.org"). + Post("/bot123123:Qwerty/setWebhook"). + MatchType("url"). + BodyString("url=https%3A%2F%2Ftest.com%2Ftelegram%2F123123%3AQwerty"). + Reply(201). + BodyString(`{"ok":true}`) - gock.New("https://mg-test.com"). + gock.New("https://api.telegram.org"). + Post("/bot123123:Qwerty/getWebhookInfo"). + Reply(200). + BodyString(`{"ok":true,"result":{"url":"https://test.com/telegram/123123:Qwerty","has_custom_certificate":false,"pending_update_count":0}}`) + + gock.New("https://test.retailcrm.pro"). Post("/api/v1/transport/channels"). - JSON(str). + BodyString(`{"ID":0,"Type":"telegram","Events":["message_sent","message_updated","message_deleted","message_read"]}`). MatchHeader("Content-Type", "application/json"). MatchHeader("X-Transport-Token", "test-token"). - Reply(200). + Reply(201). BodyString(`{"id": 1}`) - req, err := http.NewRequest("POST", "/add-bot/", strings.NewReader(`{"token": "bot123:test", "clientId": "test"}`)) + req, err := http.NewRequest("POST", "/add-bot/", strings.NewReader(`{"token": "123123:Qwerty", "clientId": "123123"}`)) if err != nil { t.Fatal(err) } rr := httptest.NewRecorder() handler := http.HandlerFunc(addBotHandler) - handler.ServeHTTP(rr, req) + if rr.Code != http.StatusCreated { t.Errorf("handler returned wrong status code: got %v want %v", rr.Code, http.StatusCreated) } } + +func TestRouting_activityBotHandler(t *testing.T) { + defer gock.Off() + + gock.New("https://test.retailcrm.pro"). + Post("/api/v1/transport/channels"). + BodyString(`{"ID":1,"Type":"telegram","Events":["message_sent","message_updated","message_deleted","message_read"]}`). + MatchHeader("Content-Type", "application/json"). + MatchHeader("X-Transport-Token", "123123"). + Reply(200). + BodyString(`{"id": 1}`) + + req, err := http.NewRequest("POST", "/activity-bot/", strings.NewReader(`{"token": "123123:Qwerty", "active": false, "clientId": "123123"}`)) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(activityBotHandler) + handler.ServeHTTP(rr, req) + + if rr.Code != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + rr.Code, http.StatusOK) + } +} + +func TestRouting_settingsHandler(t *testing.T) { + req, err := http.NewRequest("GET", "/settings/123123", nil) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(makeHandler(settingsHandler)) + handler.ServeHTTP(rr, req) + + if rr.Code != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + rr.Code, http.StatusOK) + } +} + +func TestRouting_saveHandler(t *testing.T) { + req, err := http.NewRequest("POST", "/save/", + strings.NewReader( + `{"clientId": "123123", + "api_url": "https://test.retailcrm.ru", + "api_key": "test"}`, + )) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(saveHandler) + handler.ServeHTTP(rr, req) + + if rr.Code != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + rr.Code, http.StatusOK) + } +} + +func TestRouting_activityHandler(t *testing.T) { + req, err := http.NewRequest("POST", "/actions/activity", + strings.NewReader( + `{"clientId": "123123","activity": {"active": true}}`, + )) + if err != nil { + t.Fatal(err) + } + + rr := httptest.NewRecorder() + handler := http.HandlerFunc(activityHandler) + handler.ServeHTTP(rr, req) + + if rr.Code != http.StatusOK { + t.Errorf("handler returned wrong status code: got %v want %v", + rr.Code, http.StatusOK) + } +}
{{.Locale.TableName}}