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 421939b..bacaacd 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,7 +65,14 @@ 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) + return + } + + err = tm.Execute(w, &c) if err != nil { raven.CaptureErrorAndWait(err, nil) http.Error(w, err.Error(), http.StatusInternalServerError) @@ -99,9 +109,11 @@ 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 { - http.Error(w, err.Error(), http.StatusInternalServerError) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_adding_bot"}), http.StatusInternalServerError) return } @@ -109,40 +121,51 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &b) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_adding_bot"}), http.StatusInternalServerError) 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) + 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 } b.Name = GetBotName(bot) - c, err := getConnection(b.ClientID) - if err != nil { - http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_find_account"}), http.StatusInternalServerError) - 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_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 +182,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,11 +193,19 @@ 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, 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 { + 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, _ := json.Marshal(b) w.WriteHeader(http.StatusCreated) w.Write(jsonString) } @@ -182,7 +213,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.StatusInternalServerError) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -190,7 +222,8 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &b) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -205,16 +238,10 @@ 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) - 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_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 +250,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 } @@ -238,8 +265,8 @@ 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) + logger.Error(b.ClientID, err.Error()) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -249,32 +276,26 @@ 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 { - raven.CaptureErrorAndWait(err, nil) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - + p := getConnection(uid) if p.ID == 0 { http.Redirect(w, r, "/", http.StatusFound) } bots := Bots{} - bots.getBotsByClientID(uid) - - client := v5.New(p.APIURL, p.APIKEY) - sites, _, _ := client.Sites() + 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 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"}), @@ -292,9 +313,12 @@ 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 { - http.Error(w, err.Error(), http.StatusInternalServerError) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -302,7 +326,8 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &c) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -316,12 +341,13 @@ 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, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) + logger.Error(c.APIURL, err.Error()) 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 +355,8 @@ func createHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -337,7 +364,8 @@ func createHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &c) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } @@ -350,7 +378,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { return } - cl, _ := getConnectionByURL(c.APIURL) + cl := getConnectionByURL(c.APIURL) if cl.ID != 0 { http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "connection_already_created"}), http.StatusBadRequest) return @@ -360,7 +388,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(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 } @@ -403,7 +432,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(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 } @@ -416,6 +446,7 @@ 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 { @@ -424,8 +455,23 @@ func createHandler(w http.ResponseWriter, r *http.Request) { 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 { + raven.CaptureErrorAndWait(err, nil) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_connection"}), http.StatusBadRequest) + return + } + w.WriteHeader(http.StatusFound) - w.Write([]byte("/settings/" + c.ClientID)) + w.Write(jss) } func activityHandler(w http.ResponseWriter, r *http.Request) { @@ -434,7 +480,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 } @@ -443,7 +494,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 } @@ -454,7 +510,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 } @@ -462,13 +523,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) } @@ -483,3 +555,98 @@ 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 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) + } +} 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"}}