From 5c6cab9fbf38b6f87f99b4abae71ee1d53b15bed Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Fri, 25 May 2018 18:09:38 +0300 Subject: [PATCH] fix remarks pr, improve tests --- routing.go | 150 ++++++++----------------------------- routing_test.go | 73 +++++++++++++++++- telegram.go | 101 ++++++++++++++++++++++++- templates/form.html | 2 +- templates/home.html | 2 +- translate/translate.en.yml | 2 +- translate/translate.ru.yml | 2 +- 7 files changed, 207 insertions(+), 125 deletions(-) diff --git a/routing.go b/routing.go index bacaacd..8f3cf8f 100644 --- a/routing.go +++ b/routing.go @@ -8,8 +8,6 @@ import ( "io/ioutil" "net/http" "regexp" - "strconv" - "time" "github.com/getsentry/raven-go" "github.com/go-telegram-bot-api/telegram-bot-api" @@ -62,6 +60,8 @@ func setWrapperRoutes() { http.HandleFunc("/save/", saveHandler) http.HandleFunc("/create/", createHandler) http.HandleFunc("/actions/activity", activityHandler) + http.HandleFunc("/add-bot/", addBotHandler) + http.HandleFunc("/activity-bot/", activityBotHandler) } func renderTemplate(w http.ResponseWriter, tmpl string, c interface{}) { @@ -100,7 +100,7 @@ func connectHandler(w http.ResponseWriter, r *http.Request) { }{ &p, map[string]interface{}{ - "ButConnect": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "but_connect"}), + "ButtonSave": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "button_save"}), "ApiKey": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "api_key"}), "Title": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "title"}), }, @@ -131,6 +131,13 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { 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") + return + } + cl := getBotByToken(b.Token) if cl.ID != 0 { http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "bot_already_created"}), http.StatusBadRequest) @@ -146,13 +153,19 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { bot.Debug = false - _, err = bot.SetWebhook(tgbotapi.NewWebhook("https://" + config.HTTPServer.Host + "/telegram/" + bot.Token)) + wr, 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 } + if !wr.Ok { + logger.Error(b.Token, wr.ErrorCode, wr.Result) + 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()) @@ -162,13 +175,6 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { b.Name = GetBotName(bot) - 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") - return - } - ch := v1.Channel{ Type: "telegram", Events: []string{ @@ -227,6 +233,13 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { 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") + return + } + ch := v1.Channel{ ID: getBotChannelByToken(b.Token), Type: "telegram", @@ -238,13 +251,6 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { }, } - 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") - return - } - var client = v1.New(c.MGURL, c.MGToken) if b.Active { @@ -265,6 +271,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, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return @@ -297,7 +304,7 @@ func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { p, bots, map[string]interface{}{ - "ButConnect": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "but_connect"}), + "ButtonSave": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "button_save"}), "ApiKey": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "api_key"}), "TabSettings": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "tab_settings"}), "TabBots": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "tab_bots"}), @@ -331,7 +338,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { return } - err = validate(c) + err = validateCrmSettings(c) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) logger.Error(c.APIURL, err.Error()) @@ -371,7 +378,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { c.ClientID = GenerateToken() - err = validate(c) + err = validateCrmSettings(c) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) logger.Error(c.APIURL, err.Error()) @@ -400,6 +407,8 @@ func createHandler(w http.ResponseWriter, r *http.Request) { return } + //TODO: проверка на необходимые методы cr.Credentials + integration := v5.IntegrationModule{ Code: transport, IntegrationCode: transport, @@ -466,7 +475,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { jss, err := json.Marshal(res) 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 } @@ -544,7 +553,7 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { w.Write(jsonString) } -func validate(c Connection) error { +func validateCrmSettings(c Connection) error { if c.APIURL == "" || c.APIKEY == "" { return errors.New(localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "missing_url_key"})) } @@ -555,98 +564,3 @@ func validate(c Connection) error { return nil } - -func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string) { - ok := make(chan bool) - bytes, err := ioutil.ReadAll(r.Body) - if err != nil { - raven.CaptureErrorAndWait(err, nil) - logger.Error(token, err) - return - } - - go func() { - b := getBotByToken(token) - if b.ID == 0 { - logger.Error(token, "missing") - return - } - - if !b.Active { - logger.Error(token, "deactivated") - return - } - - var update tgbotapi.Update - - err = json.Unmarshal(bytes, &update) - if err != nil { - raven.CaptureErrorAndWait(err, nil) - logger.Error(token, err) - 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, - } - - data, status, err := client.Messages(snd) - if err != nil { - logger.Error(token, err.Error(), status, data) - ok <- false - 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, - }, - }, - 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 bbff5ec..02225af 100644 --- a/routing_test.go +++ b/routing_test.go @@ -3,6 +3,7 @@ package main import ( "net/http" "net/http/httptest" + "net/url" "strings" "testing" @@ -41,6 +42,8 @@ func TestRouting_connectHandler(t *testing.T) { func TestRouting_addBotHandler(t *testing.T) { defer gock.Off() + p := url.Values{"url": {"https://test.com/telegram/123123:Qwerty"}} + gock.New("https://api.telegram.org"). Post("/bot123123:Qwerty/getMe"). Reply(200). @@ -49,7 +52,7 @@ func TestRouting_addBotHandler(t *testing.T) { gock.New("https://api.telegram.org"). Post("/bot123123:Qwerty/setWebhook"). MatchType("url"). - BodyString("url=https%3A%2F%2Ftest.com%2Ftelegram%2F123123%3AQwerty"). + BodyString(p.Encode()). Reply(201). BodyString(`{"ok":true}`) @@ -144,6 +147,74 @@ func TestRouting_saveHandler(t *testing.T) { } } +// +//func TestRouting_createHandler(t *testing.T) { +// defer gock.Off() +// +// gock.New("https://test2.retailcrm.ru"). +// Get("/api/credentials"). +// Reply(200). +// BodyString(`{"success": true}`) +// +// integrationModule := v5.IntegrationModule{ +// Code: transport, +// IntegrationCode: transport, +// Active: true, +// Name: "Telegram", +// ClientID: "123", +// Logo: fmt.Sprintf( +// "https://%s/web/telegram_logo.svg", +// config.HTTPServer.Host, +// ), +// BaseURL: fmt.Sprintf( +// "https://%s", +// config.HTTPServer.Host, +// ), +// AccountURL: fmt.Sprintf( +// "https://%s/settings/%s", +// config.HTTPServer.Host, +// "123", +// ), +// Actions: map[string]string{"activity": "/actions/activity"}, +// Integrations: &v5.Integrations{ +// MgTransport: &v5.MgTransport{ +// WebhookUrl: fmt.Sprintf( +// "https://%s/webhook", +// config.HTTPServer.Host, +// ), +// }, +// }, +// } +// +// updateJSON, _ := json.Marshal(&integrationModule) +// p := url.Values{"integrationModule": {string(updateJSON[:])}} +// +// gock.New("https://test2.retailcrm.ru"). +// Post(fmt.Sprintf("/api/v5/integration-modules/%s/edit", integrationModule.Code)). +// MatchType("url"). +// BodyString(p.Encode()). +// MatchHeader("X-API-KEY", "test"). +// Reply(201). +// BodyString(`{"success": true, "info": {"baseUrl": "http://test.te", "token": "test"}}`) +// +// req, err := http.NewRequest("POST", "/create/", +// strings.NewReader( +// `{"api_url": "https://test2.retailcrm.ru","api_key": "test"}`, +// )) +// if err != nil { +// t.Fatal(err) +// } +// +// rr := httptest.NewRecorder() +// handler := http.HandlerFunc(createHandler) +// handler.ServeHTTP(rr, req) +// +// if rr.Code != http.StatusFound { +// t.Errorf("handler returned wrong status code: got %v want %v", +// rr.Code, http.StatusFound) +// } +//} + func TestRouting_activityHandler(t *testing.T) { req, err := http.NewRequest("POST", "/actions/activity", strings.NewReader( diff --git a/telegram.go b/telegram.go index 2901a35..d60c872 100644 --- a/telegram.go +++ b/telegram.go @@ -3,12 +3,17 @@ package main import ( "net/http" + "encoding/json" + "io/ioutil" + "strconv" + "time" + + "github.com/getsentry/raven-go" "github.com/go-telegram-bot-api/telegram-bot-api" + "github.com/retailcrm/mg-transport-api-client-go/v1" ) func setTransportRoutes() { - http.HandleFunc("/add-bot/", addBotHandler) - http.HandleFunc("/activity-bot/", activityBotHandler) http.HandleFunc("/telegram/", makeHandler(telegramWebhookHandler)) } @@ -25,3 +30,95 @@ func GetBotInfo(token string) (*tgbotapi.BotAPI, error) { func GetBotName(bot *tgbotapi.BotAPI) string { return bot.Self.FirstName } + +func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string) { + b := getBotByToken(token) + if b.ID == 0 { + logger.Error(token, "missing") + w.WriteHeader(http.StatusBadRequest) + return + } + + if !b.Active { + logger.Error(token, "deactivated") + w.WriteHeader(http.StatusBadRequest) + return + } + + c := getConnection(b.ClientID) + if c.MGURL == "" || c.MGToken == "" { + logger.Error(token, "MGURL or MGToken is empty") + w.WriteHeader(http.StatusBadRequest) + return + } + + var update tgbotapi.Update + + bytes, err := ioutil.ReadAll(r.Body) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + w.WriteHeader(http.StatusInternalServerError) + logger.Error(token, err) + return + } + + 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 { + 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, + Lastname: update.Message.From.LastName, + Language: update.Message.From.LanguageCode, + }, + Channel: b.Channel, + } + + data, st, err := client.Messages(snd) + if err != nil { + logger.Error(token, err.Error(), st, data) + w.WriteHeader(http.StatusInternalServerError) + 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, + }, + }, + Channel: b.Channel, + } + + data, st, err := client.UpdateMessages(snd) + if err != nil { + logger.Error(token, err.Error(), st, data) + w.WriteHeader(http.StatusInternalServerError) + return + } + } + + w.WriteHeader(http.StatusOK) +} diff --git a/templates/form.html b/templates/form.html index f7f8f3d..49dc0dd 100644 --- a/templates/form.html +++ b/templates/form.html @@ -23,7 +23,7 @@
diff --git a/templates/home.html b/templates/home.html index 2e4dd6e..0de3b89 100644 --- a/templates/home.html +++ b/templates/home.html @@ -15,7 +15,7 @@
diff --git a/translate/translate.en.yml b/translate/translate.en.yml index b7521a9..004525a 100644 --- a/translate/translate.en.yml +++ b/translate/translate.en.yml @@ -1,4 +1,4 @@ -but_connect: Save +button_save: Save tab_settings: Connection settings tab_bots: Bots table_name: Bot name diff --git a/translate/translate.ru.yml b/translate/translate.ru.yml index 5d1b65f..863e850 100644 --- a/translate/translate.ru.yml +++ b/translate/translate.ru.yml @@ -1,4 +1,4 @@ -but_connect: Сохранить +button_save: Сохранить tab_settings: Настройки CRM tab_bots: Боты table_name: Имя