From 8a2e01b4bb9eb85c1d3b7534d032f19d10be7097 Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Thu, 13 Sep 2018 23:51:36 +0300 Subject: [PATCH 01/12] order fix --- go.mod | 5 +++-- go.sum | 14 ++++++-------- src/routing.go | 25 ++++++++++++++++++++++++- src/routing_test.go | 10 +++++++++- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 156135f..ea99b62 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/retailcrm/mg-transport-telegram require ( cloud.google.com/go v0.27.0 // indirect github.com/Microsoft/go-winio v0.4.11 // indirect - github.com/aws/aws-sdk-go v1.15.33 + github.com/aws/aws-sdk-go v1.15.35 github.com/certifi/gocertifi v0.0.0-20180905225744-ee1a9a0726d2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/denisenkom/go-mssqldb v0.0.0-20180901172138-1eb28afdf9b6 // indirect @@ -31,6 +31,7 @@ require ( github.com/jinzhu/now v0.0.0-20180511015916-ed742868f2ae // indirect github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect github.com/json-iterator/go v1.1.5 // indirect + github.com/jstemmer/go-junit-report v0.0.0-20180614143834-385fac0ced9a // indirect github.com/jtolds/gls v4.2.1+incompatible // indirect github.com/kr/pretty v0.1.0 // indirect github.com/lib/pq v1.0.0 // indirect @@ -44,7 +45,7 @@ require ( github.com/pkg/errors v0.8.0 github.com/pmezard/go-difflib v1.0.0 // indirect github.com/retailcrm/api-client-go v1.0.6 - github.com/retailcrm/mg-transport-api-client-go v1.1.8 + github.com/retailcrm/mg-transport-api-client-go v1.1.9 github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf // indirect github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect github.com/stevvooe/resumable v0.0.0-20180830230917-22b14a53ba50 // indirect diff --git a/go.sum b/go.sum index 895fa84..9792e97 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/BurntSushi/toml v0.3.0 h1:e1/Ivsx3Z0FVTV0NSOv/aVgbUWyQuzj7DDnFblkRvsY github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/aws/aws-sdk-go v1.15.33 h1:Xch3KIkPonPmCiA/BlaRm+RljrWr3M5Jb4EeUpdgmTU= -github.com/aws/aws-sdk-go v1.15.33/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.15.35 h1:roOTR0eOeCgYwrz3NXmrneLFBYdnK8epLedaRMm1kQg= +github.com/aws/aws-sdk-go v1.15.35/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/certifi/gocertifi v0.0.0-20180905225744-ee1a9a0726d2 h1:MmeatFT1pTPSVb4nkPmBFN/LRZ97vPjsFKsZrU3KKTs= github.com/certifi/gocertifi v0.0.0-20180905225744-ee1a9a0726d2/go.mod h1:GJKEexRPVJrBSOjoqN5VNOIKJ5Q3RViH6eu3puDRwx4= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -64,6 +64,8 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5i github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jstemmer/go-junit-report v0.0.0-20180614143834-385fac0ced9a h1:2qq552JOlVHGYvqPc9ynBnGPDHeA7p0/QRn2NkrO8vk= +github.com/jstemmer/go-junit-report v0.0.0-20180614143834-385fac0ced9a/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= @@ -93,12 +95,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/retailcrm/api-client-go v1.0.6 h1:4Q3e4ve8GOOHIQdq3/wTGqgWuWa1cKMKqmgrTv4FoDU= github.com/retailcrm/api-client-go v1.0.6/go.mod h1:QRoPE2SM6ST7i2g0yEdqm7Iw98y7cYuq3q14Ot+6N8c= -github.com/retailcrm/mg-transport-api-client-go v1.1.6 h1:bwBs+iJbJzTAUFbkz+LmOhpruYebrI26haPPzBlZaRU= -github.com/retailcrm/mg-transport-api-client-go v1.1.6/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI= -github.com/retailcrm/mg-transport-api-client-go v1.1.7 h1:dKm2hhR6l1kQvYKjD50C4/W9EzfV6t6YVdhLxSExooU= -github.com/retailcrm/mg-transport-api-client-go v1.1.7/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI= -github.com/retailcrm/mg-transport-api-client-go v1.1.8 h1:xLfy9j0VrAoAQUUtB5LllIqPFDvJ9H1xuri34kfZPPY= -github.com/retailcrm/mg-transport-api-client-go v1.1.8/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI= +github.com/retailcrm/mg-transport-api-client-go v1.1.9 h1:ogh5ThoqZJM5v4ZY6CqctUj01pVVHfBLXkrmX+BFjHE= +github.com/retailcrm/mg-transport-api-client-go v1.1.9/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI= github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf h1:6V1qxN6Usn4jy8unvggSJz/NC790tefw8Zdy6OZS5co= github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a h1:JSvGDIbmil4Ui/dDdFBExb7/cmkNjyX5F97oglmvCDo= diff --git a/src/routing.go b/src/routing.go index 29d0eef..2258a08 100644 --- a/src/routing.go +++ b/src/routing.go @@ -77,6 +77,10 @@ func addBotHandler(c *gin.Context) { Creating: v1.ChannelFeatureReceive, Editing: v1.ChannelFeatureReceive, }, + Order: v1.Order{ + Creating: v1.ChannelFeatureReceive, + Editing: v1.ChannelFeatureReceive, + }, }, } @@ -510,12 +514,31 @@ func mgWebhookHandler(c *gin.Context) { mb = fmt.Sprintf("\n%s", msg.Data.Product.Img) } + } else if msg.Data.Type == v1.MsgTypeOrder { + mb = "**Заказ" + + if msg.Data.Order.Number != ""{ + mb += " " + msg.Data.Order.Number + } + + if msg.Data.Order.Date != "" { + mb += fmt.Sprintf(" (%s)", msg.Data.Order.Date) + } + + mb += "**\n" + if len(msg.Data.Order.Items) > 0 { + for _, v := range msg.Data.Order.Items { + mb += fmt.Sprintf("%s %v x %v %s\n", v.Name, v.Quantity.Value, v.Price.Value, currency[strings.ToLower(v.Price.Currency)]) + } + } + + mb += fmt.Sprintf("Сумма: %v %s", msg.Data.Order.Cost.Value, currency[strings.ToLower(msg.Data.Order.Cost.Currency)]) } else { mb = msg.Data.Content } m := tgbotapi.NewMessage(cid, mb) - if msg.Data.Type == v1.MsgTypeProduct { + if msg.Data.Type == v1.MsgTypeProduct || msg.Data.Type == v1.MsgTypeOrder { m.ParseMode = "Markdown" } diff --git a/src/routing_test.go b/src/routing_test.go index af770ad..e86ac04 100644 --- a/src/routing_test.go +++ b/src/routing_test.go @@ -70,10 +70,18 @@ func TestRouting_addBotHandler(t *testing.T) { Quoting: v1.ChannelFeatureBoth, Deleting: v1.ChannelFeatureReceive, }, + Product: v1.Product{ + Creating: v1.ChannelFeatureReceive, + Editing: v1.ChannelFeatureReceive, + }, + Order: v1.Order{ + Creating: v1.ChannelFeatureReceive, + Editing: v1.ChannelFeatureReceive, + }, }, } - outgoing, _ := json.Marshal(ch) + outgoing, _ := json.Marshal(&ch) p := url.Values{"url": {"https://" + config.HTTPServer.Host + "/telegram/123123:Qwerty"}} gock.New("https://api.telegram.org"). From b4c72d760e3108f8606adc906f157b79c45cf300 Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Fri, 14 Sep 2018 00:04:42 +0300 Subject: [PATCH 02/12] fmt --- src/main.go | 12 ++++++------ src/routing.go | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main.go b/src/main.go index b003e90..ac990c4 100644 --- a/src/main.go +++ b/src/main.go @@ -15,12 +15,12 @@ type Options struct { } var ( - config *TransportConfig - orm *Orm - logger *logging.Logger - options Options - parser = flags.NewParser(&options, flags.Default) - rx = regexp.MustCompile(`/+$`) + config *TransportConfig + orm *Orm + logger *logging.Logger + options Options + parser = flags.NewParser(&options, flags.Default) + rx = regexp.MustCompile(`/+$`) currency = map[string]string{ "rub": "₽", "uah": "₴", diff --git a/src/routing.go b/src/routing.go index 2258a08..8c11a00 100644 --- a/src/routing.go +++ b/src/routing.go @@ -510,14 +510,14 @@ func mgWebhookHandler(c *gin.Context) { ) } - if msg.Data.Product.Img != "" { + if msg.Data.Product.Img != "" { mb = fmt.Sprintf("\n%s", msg.Data.Product.Img) } } else if msg.Data.Type == v1.MsgTypeOrder { mb = "**Заказ" - if msg.Data.Order.Number != ""{ + if msg.Data.Order.Number != "" { mb += " " + msg.Data.Order.Number } @@ -527,8 +527,8 @@ func mgWebhookHandler(c *gin.Context) { mb += "**\n" if len(msg.Data.Order.Items) > 0 { - for _, v := range msg.Data.Order.Items { - mb += fmt.Sprintf("%s %v x %v %s\n", v.Name, v.Quantity.Value, v.Price.Value, currency[strings.ToLower(v.Price.Currency)]) + for _, v := range msg.Data.Order.Items { + mb += fmt.Sprintf("%s %v x %v %s\n", v.Name, v.Quantity.Value, v.Price.Value, currency[strings.ToLower(v.Price.Currency)]) } } From 6a5c6c7f5b03560c1acc680a57600ca4e33be213 Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Fri, 14 Sep 2018 00:19:19 +0300 Subject: [PATCH 03/12] fix product card --- src/routing.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/routing.go b/src/routing.go index 8c11a00..89265d7 100644 --- a/src/routing.go +++ b/src/routing.go @@ -497,23 +497,21 @@ func mgWebhookHandler(c *gin.Context) { case "message_sent": var mb string if msg.Data.Type == v1.MsgTypeProduct { - mb = fmt.Sprintf( - "[%s](%s)", - msg.Data.Product.Name, - msg.Data.Product.Url, - ) + mb = fmt.Sprintf("%s\n", msg.Data.Product.Name) + if msg.Data.Product.Cost != nil && msg.Data.Product.Cost.Value != 0 { mb += fmt.Sprintf( - "\n%v %s", + "\n%v %s\n", msg.Data.Product.Cost.Value, currency[strings.ToLower(msg.Data.Product.Cost.Currency)], ) } - if msg.Data.Product.Img != "" { - mb = fmt.Sprintf("\n%s", msg.Data.Product.Img) + if msg.Data.Product.Url != "" { + mb += msg.Data.Product.Url + } else { + mb += msg.Data.Product.Img } - } else if msg.Data.Type == v1.MsgTypeOrder { mb = "**Заказ" From 4565419463c8aa1c89c4b28413487051f997a295 Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Fri, 14 Sep 2018 00:26:21 +0300 Subject: [PATCH 04/12] fix markdown --- src/routing.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/routing.go b/src/routing.go index 89265d7..046cd74 100644 --- a/src/routing.go +++ b/src/routing.go @@ -513,7 +513,7 @@ func mgWebhookHandler(c *gin.Context) { mb += msg.Data.Product.Img } } else if msg.Data.Type == v1.MsgTypeOrder { - mb = "**Заказ" + mb = "Заказ" if msg.Data.Order.Number != "" { mb += " " + msg.Data.Order.Number @@ -523,7 +523,7 @@ func mgWebhookHandler(c *gin.Context) { mb += fmt.Sprintf(" (%s)", msg.Data.Order.Date) } - mb += "**\n" + mb += "\n" if len(msg.Data.Order.Items) > 0 { for _, v := range msg.Data.Order.Items { mb += fmt.Sprintf("%s %v x %v %s\n", v.Name, v.Quantity.Value, v.Price.Value, currency[strings.ToLower(v.Price.Currency)]) @@ -536,10 +536,6 @@ func mgWebhookHandler(c *gin.Context) { } m := tgbotapi.NewMessage(cid, mb) - if msg.Data.Type == v1.MsgTypeProduct || msg.Data.Type == v1.MsgTypeOrder { - m.ParseMode = "Markdown" - } - if msg.Data.QuoteExternalID != "" { qid, err := strconv.Atoi(msg.Data.QuoteExternalID) if err != nil { From 299f73925e7dbf69e9f07f3d3d064176c999664f Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Thu, 13 Sep 2018 23:09:26 +0300 Subject: [PATCH 05/12] orders & products --- src/routing.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/routing.go b/src/routing.go index 046cd74..ebfb1e3 100644 --- a/src/routing.go +++ b/src/routing.go @@ -507,6 +507,7 @@ func mgWebhookHandler(c *gin.Context) { ) } +<<<<<<< 01b5fb405bad7411afb6523c9308deaf25e20f6f if msg.Data.Product.Url != "" { mb += msg.Data.Product.Url } else { @@ -530,12 +531,43 @@ func mgWebhookHandler(c *gin.Context) { } } +======= + if msg.Data.Product.Img != "" { + mb = fmt.Sprintf("\n%s", msg.Data.Product.Img) + } + + } else if msg.Data.Type == v1.MsgTypeOrder { + mb = "**Заказ" + + if msg.Data.Order.Number != ""{ + mb += " " + msg.Data.Order.Number + } + + if msg.Data.Order.Date != "" { + mb += fmt.Sprintf(" (%s)", msg.Data.Order.Date) + } + + mb += "**\n" + if len(msg.Data.Order.Items) > 0 { + for _, v := range msg.Data.Order.Items { + mb += fmt.Sprintf("%s %v x %v %s\n", v.Name, v.Quantity.Value, v.Price.Value, currency[strings.ToLower(v.Price.Currency)]) + } + } + +>>>>>>> orders & products mb += fmt.Sprintf("Сумма: %v %s", msg.Data.Order.Cost.Value, currency[strings.ToLower(msg.Data.Order.Cost.Currency)]) } else { mb = msg.Data.Content } m := tgbotapi.NewMessage(cid, mb) +<<<<<<< 01b5fb405bad7411afb6523c9308deaf25e20f6f +======= + if msg.Data.Type == v1.MsgTypeProduct || msg.Data.Type == v1.MsgTypeOrder { + m.ParseMode = "Markdown" + } + +>>>>>>> orders & products if msg.Data.QuoteExternalID != "" { qid, err := strconv.Atoi(msg.Data.QuoteExternalID) if err != nil { From accd94cf51c00d14f93187d61750ca89a9ee50db Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Thu, 13 Sep 2018 23:19:23 +0300 Subject: [PATCH 06/12] tests --- src/routing_test.go | 82 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/src/routing_test.go b/src/routing_test.go index e86ac04..cbc0fd4 100644 --- a/src/routing_test.go +++ b/src/routing_test.go @@ -53,6 +53,7 @@ func TestRouting_connectHandler(t *testing.T) { fmt.Sprintf("handler returned wrong status code: got %v want %v", rr.Code, http.StatusOK)) } +<<<<<<< 299f73925e7dbf69e9f07f3d3d064176c999664f func TestRouting_addBotHandler(t *testing.T) { defer gock.Off() @@ -132,6 +133,87 @@ func TestRouting_addBotHandler(t *testing.T) { assert.Equal(t, "123123:Qwerty", res["token"]) } +======= +// func TestRouting_addBotHandler(t *testing.T) { +// defer gock.Off() +// +// ch := v1.Channel{ +// Type: "telegram", +// Settings: v1.ChannelSettings{ +// SpamAllowed: false, +// Status: v1.Status{ +// Delivered: v1.ChannelFeatureSend, +// Read: v1.ChannelFeatureNone, +// }, +// Text: v1.ChannelSettingsText{ +// Creating: v1.ChannelFeatureBoth, +// Editing: v1.ChannelFeatureBoth, +// Quoting: v1.ChannelFeatureBoth, +// Deleting: v1.ChannelFeatureReceive, +// }, +// Product: v1.Product{ +// Creating: v1.ChannelFeatureReceive, +// Editing: v1.ChannelFeatureReceive, +// }, +// Order: v1.Order{ +// Creating: v1.ChannelFeatureReceive, +// Editing: v1.ChannelFeatureReceive, +// }, +// }, +// } +// +// outgoing, _ := json.Marshal(ch) +// p := url.Values{"url": {"https://" + config.HTTPServer.Host + "/telegram/123123:Qwerty"}} +// +// gock.New("https://api.telegram.org"). +// Post("/bot123123:Qwerty/getMe"). +// Reply(200). +// BodyString(`{"ok":true,"result":{"id":123,"is_bot":true,"first_name":"Test","username":"TestBot"}}`) +// +// gock.New("https://api.telegram.org"). +// Post("/bot123123:Qwerty/setWebhook"). +// MatchType("url"). +// BodyString(p.Encode()). +// Reply(201). +// BodyString(`{"ok":true}`) +// +// gock.New("https://api.telegram.org"). +// Post("/bot123123:Qwerty/getWebhookInfo"). +// Reply(200). +// BodyString(`{"ok":true,"result":{"url":"https://` + config.HTTPServer.Host + `/telegram/123123:Qwerty","has_custom_certificate":false,"pending_update_count":0}}`) +// +// gock.New("https://test.retailcrm.pro"). +// Post("/api/transport/v1/channels"). +// JSON([]byte(outgoing)). +// MatchHeader("Content-Type", "application/json"). +// MatchHeader("X-Transport-Token", "test-token"). +// Reply(201). +// BodyString(`{"id": 1}`) +// +// req, err := http.NewRequest("POST", "/add-bot/", strings.NewReader(`{"token": "123123:Qwerty", "connectionId": 1}`)) +// if err != nil { +// t.Fatal(err) +// } +// rr := httptest.NewRecorder() +// router.ServeHTTP(rr, req) +// require.Equal(t, http.StatusCreated, rr.Code, +// fmt.Sprintf("handler returned wrong status code: got %v want %v", rr.Code, http.StatusCreated)) +// +// bytes, err := ioutil.ReadAll(rr.Body) +// if err != nil { +// t.Fatal(err) +// } +// +// var res map[string]interface{} +// +// err = json.Unmarshal(bytes, &res) +// if err != nil { +// t.Fatal(err) +// } +// +// assert.Equal(t, "123123:Qwerty", res["token"]) +// } +>>>>>>> tests func TestRouting_deleteBotHandler(t *testing.T) { defer gock.Off() From 286591e98eed902aac1cc7f6cf2f7b64262e2e5a Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Thu, 13 Sep 2018 23:25:23 +0300 Subject: [PATCH 07/12] test --- src/routing_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/routing_test.go b/src/routing_test.go index cbc0fd4..3d5c46d 100644 --- a/src/routing_test.go +++ b/src/routing_test.go @@ -1,9 +1,7 @@ package main import ( - "encoding/json" "fmt" - "io/ioutil" "net/http" "net/http/httptest" "net/url" @@ -15,7 +13,6 @@ import ( "github.com/h2non/gock" "github.com/retailcrm/mg-transport-api-client-go/v1" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) var router *gin.Engine From cc6407c000e1a3bf745fda7dca54527649a6070b Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Wed, 19 Sep 2018 16:34:13 +0300 Subject: [PATCH 08/12] update for order & products, minor fixes --- Jenkinsfile | 1 - Makefile | 2 +- src/routing.go | 32 ----------------- src/routing_test.go | 85 ++------------------------------------------- 4 files changed, 4 insertions(+), 116 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 8906707..89489b7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -17,7 +17,6 @@ pipeline { steps { sh 'cp config_test.yml.dist config_test.yml' compose 'up -d --build postgres_test' - compose 'run --rm mg_telegram_test make migrate_test' } } diff --git a/Makefile b/Makefile index f8a1515..0630871 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ test: deps fmt @echo "==> Running tests" @cd $(ROOT_DIR) && go test ./... -v -cpu 2 -jenkins_test: deps +jenkins_test: migrate_test @echo "==> Running tests (result in test-report.xml)" @go get -v -u github.com/jstemmer/go-junit-report @go test ./... -v -cpu 2 -race | /go/bin/go-junit-report -set-exit-code > ./test-report.xml diff --git a/src/routing.go b/src/routing.go index ebfb1e3..046cd74 100644 --- a/src/routing.go +++ b/src/routing.go @@ -507,7 +507,6 @@ func mgWebhookHandler(c *gin.Context) { ) } -<<<<<<< 01b5fb405bad7411afb6523c9308deaf25e20f6f if msg.Data.Product.Url != "" { mb += msg.Data.Product.Url } else { @@ -531,43 +530,12 @@ func mgWebhookHandler(c *gin.Context) { } } -======= - if msg.Data.Product.Img != "" { - mb = fmt.Sprintf("\n%s", msg.Data.Product.Img) - } - - } else if msg.Data.Type == v1.MsgTypeOrder { - mb = "**Заказ" - - if msg.Data.Order.Number != ""{ - mb += " " + msg.Data.Order.Number - } - - if msg.Data.Order.Date != "" { - mb += fmt.Sprintf(" (%s)", msg.Data.Order.Date) - } - - mb += "**\n" - if len(msg.Data.Order.Items) > 0 { - for _, v := range msg.Data.Order.Items { - mb += fmt.Sprintf("%s %v x %v %s\n", v.Name, v.Quantity.Value, v.Price.Value, currency[strings.ToLower(v.Price.Currency)]) - } - } - ->>>>>>> orders & products mb += fmt.Sprintf("Сумма: %v %s", msg.Data.Order.Cost.Value, currency[strings.ToLower(msg.Data.Order.Cost.Currency)]) } else { mb = msg.Data.Content } m := tgbotapi.NewMessage(cid, mb) -<<<<<<< 01b5fb405bad7411afb6523c9308deaf25e20f6f -======= - if msg.Data.Type == v1.MsgTypeProduct || msg.Data.Type == v1.MsgTypeOrder { - m.ParseMode = "Markdown" - } - ->>>>>>> orders & products if msg.Data.QuoteExternalID != "" { qid, err := strconv.Atoi(msg.Data.QuoteExternalID) if err != nil { diff --git a/src/routing_test.go b/src/routing_test.go index 3d5c46d..e86ac04 100644 --- a/src/routing_test.go +++ b/src/routing_test.go @@ -1,7 +1,9 @@ package main import ( + "encoding/json" "fmt" + "io/ioutil" "net/http" "net/http/httptest" "net/url" @@ -13,6 +15,7 @@ import ( "github.com/h2non/gock" "github.com/retailcrm/mg-transport-api-client-go/v1" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var router *gin.Engine @@ -50,7 +53,6 @@ func TestRouting_connectHandler(t *testing.T) { fmt.Sprintf("handler returned wrong status code: got %v want %v", rr.Code, http.StatusOK)) } -<<<<<<< 299f73925e7dbf69e9f07f3d3d064176c999664f func TestRouting_addBotHandler(t *testing.T) { defer gock.Off() @@ -130,87 +132,6 @@ func TestRouting_addBotHandler(t *testing.T) { assert.Equal(t, "123123:Qwerty", res["token"]) } -======= -// func TestRouting_addBotHandler(t *testing.T) { -// defer gock.Off() -// -// ch := v1.Channel{ -// Type: "telegram", -// Settings: v1.ChannelSettings{ -// SpamAllowed: false, -// Status: v1.Status{ -// Delivered: v1.ChannelFeatureSend, -// Read: v1.ChannelFeatureNone, -// }, -// Text: v1.ChannelSettingsText{ -// Creating: v1.ChannelFeatureBoth, -// Editing: v1.ChannelFeatureBoth, -// Quoting: v1.ChannelFeatureBoth, -// Deleting: v1.ChannelFeatureReceive, -// }, -// Product: v1.Product{ -// Creating: v1.ChannelFeatureReceive, -// Editing: v1.ChannelFeatureReceive, -// }, -// Order: v1.Order{ -// Creating: v1.ChannelFeatureReceive, -// Editing: v1.ChannelFeatureReceive, -// }, -// }, -// } -// -// outgoing, _ := json.Marshal(ch) -// p := url.Values{"url": {"https://" + config.HTTPServer.Host + "/telegram/123123:Qwerty"}} -// -// gock.New("https://api.telegram.org"). -// Post("/bot123123:Qwerty/getMe"). -// Reply(200). -// BodyString(`{"ok":true,"result":{"id":123,"is_bot":true,"first_name":"Test","username":"TestBot"}}`) -// -// gock.New("https://api.telegram.org"). -// Post("/bot123123:Qwerty/setWebhook"). -// MatchType("url"). -// BodyString(p.Encode()). -// Reply(201). -// BodyString(`{"ok":true}`) -// -// gock.New("https://api.telegram.org"). -// Post("/bot123123:Qwerty/getWebhookInfo"). -// Reply(200). -// BodyString(`{"ok":true,"result":{"url":"https://` + config.HTTPServer.Host + `/telegram/123123:Qwerty","has_custom_certificate":false,"pending_update_count":0}}`) -// -// gock.New("https://test.retailcrm.pro"). -// Post("/api/transport/v1/channels"). -// JSON([]byte(outgoing)). -// MatchHeader("Content-Type", "application/json"). -// MatchHeader("X-Transport-Token", "test-token"). -// Reply(201). -// BodyString(`{"id": 1}`) -// -// req, err := http.NewRequest("POST", "/add-bot/", strings.NewReader(`{"token": "123123:Qwerty", "connectionId": 1}`)) -// if err != nil { -// t.Fatal(err) -// } -// rr := httptest.NewRecorder() -// router.ServeHTTP(rr, req) -// require.Equal(t, http.StatusCreated, rr.Code, -// fmt.Sprintf("handler returned wrong status code: got %v want %v", rr.Code, http.StatusCreated)) -// -// bytes, err := ioutil.ReadAll(rr.Body) -// if err != nil { -// t.Fatal(err) -// } -// -// var res map[string]interface{} -// -// err = json.Unmarshal(bytes, &res) -// if err != nil { -// t.Fatal(err) -// } -// -// assert.Equal(t, "123123:Qwerty", res["token"]) -// } ->>>>>>> tests func TestRouting_deleteBotHandler(t *testing.T) { defer gock.Off() From d0a5af4f81b54bc3852a9b97c85979f056abd2a8 Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Fri, 21 Sep 2018 20:03:14 +0300 Subject: [PATCH 09/12] update dependency, update order data --- go.sum | 2 -- src/routing.go | 34 ---------------------------------- 2 files changed, 36 deletions(-) diff --git a/go.sum b/go.sum index bc464c0..ae3bcb5 100644 --- a/go.sum +++ b/go.sum @@ -95,8 +95,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/retailcrm/api-client-go v1.0.6 h1:4Q3e4ve8GOOHIQdq3/wTGqgWuWa1cKMKqmgrTv4FoDU= github.com/retailcrm/api-client-go v1.0.6/go.mod h1:QRoPE2SM6ST7i2g0yEdqm7Iw98y7cYuq3q14Ot+6N8c= -github.com/retailcrm/mg-transport-api-client-go v1.1.9 h1:ogh5ThoqZJM5v4ZY6CqctUj01pVVHfBLXkrmX+BFjHE= -github.com/retailcrm/mg-transport-api-client-go v1.1.9/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI= github.com/retailcrm/mg-transport-api-client-go v1.1.10 h1:RR8S5NA6FPVrF6UVXaLwu/gJyKUg5aUObQ97S98M3Yc= github.com/retailcrm/mg-transport-api-client-go v1.1.10/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI= github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf h1:6V1qxN6Usn4jy8unvggSJz/NC790tefw8Zdy6OZS5co= diff --git a/src/routing.go b/src/routing.go index ce63acd..d2f5621 100644 --- a/src/routing.go +++ b/src/routing.go @@ -585,21 +585,12 @@ func mgWebhookHandler(c *gin.Context) { switch msg.Type { case "message_sent": var mb string -<<<<<<< HEAD - if msg.Data.Type == v1.MsgTypeProduct { -======= switch msg.Data.Type { case v1.MsgTypeProduct: ->>>>>>> master mb = fmt.Sprintf("%s\n", msg.Data.Product.Name) if msg.Data.Product.Cost != nil && msg.Data.Product.Cost.Value != 0 { mb += fmt.Sprintf( -<<<<<<< HEAD - "\n%v %s\n", - msg.Data.Product.Cost.Value, - currency[strings.ToLower(msg.Data.Product.Cost.Currency)], -======= "\n%s: %s\n", getLocalizedMessage("item_cost"), getLocalizedTemplateMessage( @@ -609,7 +600,6 @@ func mgWebhookHandler(c *gin.Context) { "Currency": currency[strings.ToLower(msg.Data.Product.Cost.Currency)], }, ), ->>>>>>> master ) } @@ -617,34 +607,10 @@ func mgWebhookHandler(c *gin.Context) { mb += msg.Data.Product.Url } else { mb += msg.Data.Product.Img -<<<<<<< HEAD - } - } else if msg.Data.Type == v1.MsgTypeOrder { - mb = "Заказ" - - if msg.Data.Order.Number != "" { - mb += " " + msg.Data.Order.Number - } - - if msg.Data.Order.Date != "" { - mb += fmt.Sprintf(" (%s)", msg.Data.Order.Date) - } - - mb += "\n" - if len(msg.Data.Order.Items) > 0 { - for _, v := range msg.Data.Order.Items { - mb += fmt.Sprintf("%s %v x %v %s\n", v.Name, v.Quantity.Value, v.Price.Value, currency[strings.ToLower(v.Price.Currency)]) - } - } - - mb += fmt.Sprintf("Сумма: %v %s", msg.Data.Order.Cost.Value, currency[strings.ToLower(msg.Data.Order.Cost.Currency)]) - } else { -======= } case v1.MsgTypeOrder: mb = getOrderMessage(msg.Data.Order) case v1.MsgTypeText: ->>>>>>> master mb = msg.Data.Content } From bf853827a4b7daeb5383cbb35d7a848a7f710cd1 Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Fri, 12 Oct 2018 13:39:55 +0300 Subject: [PATCH 10/12] add tags in sentry --- src/error_handler.go | 24 ++++++++++++++++++++++++ src/routing.go | 24 ++---------------------- src/run.go | 42 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 66 insertions(+), 24 deletions(-) diff --git a/src/error_handler.go b/src/error_handler.go index 4f0b05e..56c0368 100644 --- a/src/error_handler.go +++ b/src/error_handler.go @@ -67,6 +67,30 @@ func ErrorCaptureHandler(client *raven.Client, errorsStacktrace bool) ErrorHandl "endpoint": c.Request.RequestURI, } + var ( + ok bool + conn Connection + ) + + connection, ok := c.Get("connection") + if ok { + conn = connection.(Connection) + } + + b, ok := c.Get("bot") + if ok { + tags["bot"] = b.(Bot).Token + conn = *getConnectionById(b.(Bot).ConnectionID) + } + + if conn.APIURL != "" { + tags["crm"] = conn.APIURL + } + + if conn.ClientID != "" { + tags["clientID"] = conn.ClientID + } + if recovery != nil { stacktrace := raven.NewStacktrace(4, 3, nil) recStr := fmt.Sprint(recovery) diff --git a/src/routing.go b/src/routing.go index 9024953..35120f4 100644 --- a/src/routing.go +++ b/src/routing.go @@ -406,17 +406,7 @@ func updateBots(conn *Connection, hashSettings string) { } func telegramWebhookHandler(c *gin.Context) { - token := c.Param("token") - b, err := getBotByToken(token) - if err != nil { - c.Error(err) - return - } - - if b.ID == 0 { - c.AbortWithStatus(http.StatusOK) - return - } + b := c.MustGet("bot").(Bot) conn := getConnectionById(b.ConnectionID) if !conn.Active { @@ -559,17 +549,7 @@ func telegramWebhookHandler(c *gin.Context) { } func mgWebhookHandler(c *gin.Context) { - clientID := c.GetHeader("Clientid") - if clientID == "" { - c.AbortWithStatus(http.StatusBadRequest) - return - } - - conn := getConnection(clientID) - if !conn.Active { - c.AbortWithStatus(http.StatusBadRequest) - return - } + conn := c.MustGet("connection").(Connection) var msg v1.WebhookRequest if err := c.ShouldBindJSON(&msg); err != nil { diff --git a/src/run.go b/src/run.go index 74fd3db..a7b3c50 100644 --- a/src/run.go +++ b/src/run.go @@ -1,6 +1,7 @@ package main import ( + "net/http" "os" "os/signal" "syscall" @@ -92,8 +93,8 @@ func setup() *gin.Engine { r.POST("/delete-bot/", checkBotForRequest(), deleteBotHandler) r.POST("/set-lang/", checkBotForRequest(), setLangBotHandler) r.POST("/actions/activity", activityHandler) - r.POST("/telegram/:token", telegramWebhookHandler) - r.POST("/webhook/", mgWebhookHandler) + r.POST("/telegram/:token", checkBotForWebhook(), telegramWebhookHandler) + r.POST("/webhook/", checkConnectionForWebhook(), mgWebhookHandler) return r } @@ -147,3 +148,40 @@ func checkConnectionForRequest() gin.HandlerFunc { c.Set("connection", conn) } } + +func checkConnectionForWebhook() gin.HandlerFunc { + return func(c *gin.Context) { + clientID := c.GetHeader("Clientid") + if clientID == "" { + c.AbortWithStatus(http.StatusBadRequest) + return + } + + conn := getConnection(clientID) + if !conn.Active { + c.AbortWithStatus(http.StatusBadRequest) + return + } + + c.Set("connection", *conn) + } +} + +func checkBotForWebhook() gin.HandlerFunc { + return func(c *gin.Context) { + token := c.Param("token") + + b, err := getBotByToken(token) + if err != nil { + c.Error(err) + return + } + + if b.ID == 0 { + c.AbortWithStatus(http.StatusOK) + return + } + + c.Set("bot", *b) + } +} From 75086f650dbe09437b75ea497ff2bd5dfe161df9 Mon Sep 17 00:00:00 2001 From: Alex Lushpai Date: Wed, 24 Oct 2018 17:21:55 +0300 Subject: [PATCH 11/12] handle http 402 status --- go.mod | 2 +- go.sum | 4 ++-- src/routing.go | 6 ++++++ translate/translate.en.yml | 1 + translate/translate.es.yml | 1 + translate/translate.ru.yml | 1 + 6 files changed, 12 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e6d2520..71cd701 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/pkg/errors v0.8.0 github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/retailcrm/api-client-go v1.0.7 + github.com/retailcrm/api-client-go v1.1.0 github.com/retailcrm/mg-transport-api-client-go v1.1.11 github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf // indirect github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect diff --git a/go.sum b/go.sum index c459b47..64e8d2b 100644 --- a/go.sum +++ b/go.sum @@ -93,8 +93,8 @@ github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/retailcrm/api-client-go v1.0.7 h1:j4C2PvPUDP9nAuYWDvJPnYNpkj+LDBgn71kHvxJmSPg= -github.com/retailcrm/api-client-go v1.0.7/go.mod h1:QRoPE2SM6ST7i2g0yEdqm7Iw98y7cYuq3q14Ot+6N8c= +github.com/retailcrm/api-client-go v1.1.0 h1:APPO6ccJAeMV7Jz7BhrtDKSOm2r1j5Ft6fuEXNP2ij4= +github.com/retailcrm/api-client-go v1.1.0/go.mod h1:QRoPE2SM6ST7i2g0yEdqm7Iw98y7cYuq3q14Ot+6N8c= github.com/retailcrm/mg-transport-api-client-go v1.1.11 h1:jAIOKqkjA2r0v/V6lTHYQsD8q0lFpfpqzAffHAJlhCQ= github.com/retailcrm/mg-transport-api-client-go v1.1.11/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI= github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf h1:6V1qxN6Usn4jy8unvggSJz/NC790tefw8Zdy6OZS5co= diff --git a/src/routing.go b/src/routing.go index 35120f4..fcfc9e6 100644 --- a/src/routing.go +++ b/src/routing.go @@ -187,6 +187,12 @@ func createHandler(c *gin.Context) { return } + if status == http.StatusPaymentRequired { + c.AbortWithStatusJSON(BadRequest("error_payment_mg")) + logger.Error(conn.APIURL, status, errr.ApiErr, data) + return + } + if status >= http.StatusBadRequest { c.AbortWithStatusJSON(BadRequest("error_activity_mg")) logger.Error(conn.APIURL, status, errr.ApiErr, data) diff --git a/translate/translate.en.yml b/translate/translate.en.yml index e40bdb4..5deae0b 100644 --- a/translate/translate.en.yml +++ b/translate/translate.en.yml @@ -27,6 +27,7 @@ incorrect_token: Create the correct token error_creating_webhook: Error when creating a webhook error_adding_bot: Error when adding a bot error_save: Error while saving, contact technical support +error_payment_mg: Your account has insufficient funds to activate integration module missing_credentials: "Required methods: {{.Credentials}}" error_activity_mg: Check if the integration with retailCRM Chat is enabled in retailCRM settings info_bot: "If you have a problem with connecting a bot, please, refer to the documentation" diff --git a/translate/translate.es.yml b/translate/translate.es.yml index e205ca0..13bcc87 100644 --- a/translate/translate.es.yml +++ b/translate/translate.es.yml @@ -28,6 +28,7 @@ incorrect_token: Crear el token correcto error_creating_webhook: Error al crear el webhook error_adding_bot: Error al añadir el bot error_save: Error al guardar, contacte con el soporte técnico +error_payment_mg: Su cuenta no tiene fondos suficientes para activar el módulo de integración. missing_credentials: "Métodos requeridos: {{.Credenciales}}" error_activity_mg: Revisar si la integración con retailCRM Chat está habilitada en Ajustes de retailCRM info_bot: "Si tiene dificultades para conectar el bot, por favor, consulte la documentación" diff --git a/translate/translate.ru.yml b/translate/translate.ru.yml index 5b14854..52d7a3e 100644 --- a/translate/translate.ru.yml +++ b/translate/translate.ru.yml @@ -27,6 +27,7 @@ incorrect_token: Установите корректный токен error_creating_webhook: Ошибка при создании webhook error_adding_bot: Ошибка при добавлении бота error_save: Ошибка при сохранении, обратитесь в службу технической поддержки +error_payment_mg: На Вашем счете недостаточно средств для активации данного модуля missing_credentials: "Необходимые методы: {{.Credentials}}" error_activity_mg: Проверьте активность интеграции с retailCRM Chat в настройках retailCRM info_bot: "Если у вас возникли трудности при подключении бота, изучите, пожалуйста, документацию" From 631f722d147cf723265ab7c822e2de218472203a Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Wed, 28 Nov 2018 16:17:13 +0300 Subject: [PATCH 12/12] add file and images transfer --- go.mod | 4 +- go.sum | 8 +- src/routing.go | 225 ++++++++++++++++++++++++++++++++++++++++---- src/routing_test.go | 14 +++ 4 files changed, 227 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 71cd701..443393c 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/gin-gonic/gin v1.3.0 github.com/go-ini/ini v1.38.2 // indirect github.com/go-sql-driver/mysql v1.4.0 // indirect - github.com/go-telegram-bot-api/telegram-bot-api v0.0.0-20180602093832-4c16a90966d1 + github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible github.com/golang-migrate/migrate v3.4.0+incompatible github.com/golang/protobuf v1.2.0 // indirect github.com/google/go-cmp v0.2.0 // indirect @@ -45,7 +45,7 @@ require ( github.com/pkg/errors v0.8.0 github.com/pmezard/go-difflib v1.0.0 // indirect github.com/retailcrm/api-client-go v1.1.0 - github.com/retailcrm/mg-transport-api-client-go v1.1.11 + github.com/retailcrm/mg-transport-api-client-go v1.1.17 github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf // indirect github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a // indirect github.com/stevvooe/resumable v0.0.0-20180830230917-22b14a53ba50 // indirect diff --git a/go.sum b/go.sum index 64e8d2b..3d741a8 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ github.com/go-ini/ini v1.38.2 h1:6Hl/z3p3iFkA0dlDfzYxuFuUGD+kaweypF6btsR2/Q4= github.com/go-ini/ini v1.38.2/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-telegram-bot-api/telegram-bot-api v0.0.0-20180602093832-4c16a90966d1 h1:FlRoyZCY3snE+M9jTruqOzPwZg8KIwQBXr//t215K8E= -github.com/go-telegram-bot-api/telegram-bot-api v0.0.0-20180602093832-4c16a90966d1/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= github.com/golang-migrate/migrate v3.4.0+incompatible h1:9yjg5lYsbeEpWXGc80RylvPMKZ0tZEGsyO3CpYLK3jU= github.com/golang-migrate/migrate v3.4.0+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= @@ -95,8 +95,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/retailcrm/api-client-go v1.1.0 h1:APPO6ccJAeMV7Jz7BhrtDKSOm2r1j5Ft6fuEXNP2ij4= github.com/retailcrm/api-client-go v1.1.0/go.mod h1:QRoPE2SM6ST7i2g0yEdqm7Iw98y7cYuq3q14Ot+6N8c= -github.com/retailcrm/mg-transport-api-client-go v1.1.11 h1:jAIOKqkjA2r0v/V6lTHYQsD8q0lFpfpqzAffHAJlhCQ= -github.com/retailcrm/mg-transport-api-client-go v1.1.11/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI= +github.com/retailcrm/mg-transport-api-client-go v1.1.17 h1:8L0meFJFZwr3TyiF/xypI+g0xRXIGkWhyQ6qiCfojqw= +github.com/retailcrm/mg-transport-api-client-go v1.1.17/go.mod h1:AWV6BueE28/6SCoyfKURTo4lF0oXYoOKmHTzehd5vAI= github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf h1:6V1qxN6Usn4jy8unvggSJz/NC790tefw8Zdy6OZS5co= github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a h1:JSvGDIbmil4Ui/dDdFBExb7/cmkNjyX5F97oglmvCDo= diff --git a/src/routing.go b/src/routing.go index 6a9cde1..58db220 100644 --- a/src/routing.go +++ b/src/routing.go @@ -343,6 +343,20 @@ func getChannelSettings(cid ...uint64) v1.Channel { Creating: v1.ChannelFeatureReceive, Editing: v1.ChannelFeatureReceive, }, + File: v1.ChannelSettingsFilesBase{ + Creating: v1.ChannelFeatureBoth, + Editing: v1.ChannelFeatureBoth, + Quoting: v1.ChannelFeatureBoth, + Deleting: v1.ChannelFeatureReceive, + Max: 1, + }, + Image: v1.ChannelSettingsFilesBase{ + Creating: v1.ChannelFeatureBoth, + Editing: v1.ChannelFeatureBoth, + Quoting: v1.ChannelFeatureBoth, + Deleting: v1.ChannelFeatureReceive, + Max: 10, + }, }, } } @@ -437,11 +451,6 @@ func telegramWebhookHandler(c *gin.Context) { client.Debug = config.Debug if update.Message != nil { - if update.Message.Text == "" { - setLocale(update.Message.From.LanguageCode) - update.Message.Text = getLocalizedMessage(getMessageID(update.Message)) - } - nickname := update.Message.From.UserName user := getUserByExternalID(update.Message.From.ID) @@ -510,6 +519,17 @@ func telegramWebhookHandler(c *gin.Context) { snd.Quote = &v1.SendMessageRequestQuote{ExternalID: strconv.Itoa(update.Message.ReplyToMessage.MessageID)} } + if snd.Message.Text == "" { + setLocale(update.Message.From.LanguageCode) + + err := setAttachment(update.Message, client, &snd, b.Token) + if err != nil { + logger.Error(client.Token, err.Error()) + c.AbortWithStatus(http.StatusBadRequest) + return + } + } + data, st, err := client.Messages(snd) if err != nil { logger.Error(b.Token, err.Error(), st, data) @@ -528,13 +548,10 @@ func telegramWebhookHandler(c *gin.Context) { update.EditedMessage.Text = getLocalizedMessage(getMessageID(update.Message)) } - snd := v1.UpdateData{ - Message: v1.UpdateMessage{ - Message: v1.Message{ - ExternalID: strconv.Itoa(update.EditedMessage.MessageID), - Type: "text", - Text: update.EditedMessage.Text, - }, + snd := v1.EditMessageRequest{ + Message: v1.EditMessageRequestMessage{ + ExternalID: strconv.Itoa(update.EditedMessage.MessageID), + Text: update.EditedMessage.Text, }, Channel: b.Channel, } @@ -585,10 +602,13 @@ func mgWebhookHandler(c *gin.Context) { bot.Debug = config.Debug setLocale(b.Lang) + mgClient := v1.New(conn.MGURL, conn.MGToken) switch msg.Type { case "message_sent": var mb string + var m tgbotapi.Chattable + switch msg.Data.Type { case v1.MsgTypeProduct: mb = fmt.Sprintf("*%s*\n", replaceMarkdownSymbols(msg.Data.Product.Name)) @@ -616,20 +636,37 @@ func mgWebhookHandler(c *gin.Context) { mb = getOrderMessage(msg.Data.Order) case v1.MsgTypeText: mb = replaceMarkdownSymbols(msg.Data.Content) + case v1.MsgTypeImage: + m, err = photoMessage(*msg.Data.Items, mgClient, cid) + if err != nil { + logger.Errorf( + "GetFile request apiURL: %s, clientID: %s, err: %s", + conn.APIURL, conn.ClientID, err.Error(), + ) + return + } + case v1.MsgTypeFile: + items := *msg.Data.Items + if len(items) > 0 { + m, err = documentMessage(items[0], mgClient, cid) + if err != nil { + logger.Errorf( + "GetFile request apiURL: %s, clientID: %s, err: %s", + conn.APIURL, conn.ClientID, err.Error(), + ) + return + } + } } - m := tgbotapi.NewMessage(cid, mb) - if msg.Data.QuoteExternalID != "" { - qid, err := strconv.Atoi(msg.Data.QuoteExternalID) + if mb != "" { + m, err = textMessage(cid, mb, msg.Data.QuoteExternalID) if err != nil { c.Error(err) return } - m.ReplyToMessageID = qid } - m.ParseMode = "Markdown" - msgSend, err := bot.Send(m) if err != nil { logger.Error(err) @@ -805,3 +842,155 @@ func getOrderMessage(dataOrder *v1.MessageDataOrder) string { return mb } + +func photoMessage(items []v1.FileItem, mgClient *v1.MgClient, cid int64) (chattable tgbotapi.Chattable, err error) { + if len(items) == 1 { + v := items + + file, _, err := mgClient.GetFile(v[0].ID) + if err != nil { + return chattable, err + } + + msg := tgbotapi.NewPhotoUpload(cid, nil) + msg.FileID = file.Url + msg.UseExisting = true + + chattable = msg + } else if len(items) > 1 { + var it []interface{} + + for _, v := range items { + file, _, err := mgClient.GetFile(v.ID) + if err != nil { + logger.Errorf( + "GetFile request fileID: %s, err: %s", + v.ID, err.Error(), + ) + continue + } + + ip := tgbotapi.NewInputMediaPhoto(file.Url) + it = append(it, ip) + } + + chattable = tgbotapi.NewMediaGroup(cid, it) + } + + return +} + +func documentMessage(item v1.FileItem, mgClient *v1.MgClient, cid int64) (chattable tgbotapi.Chattable, err error) { + file, _, err := mgClient.GetFile(item.ID) + if err != nil { + return chattable, err + } + + data, err := http.Get(file.Url) + if err != nil { + return chattable, err + } + + tt := tgbotapi.FileReader{ + Name: item.Caption, + Reader: data.Body, + Size: int64(item.Size), + } + + chattable = tgbotapi.NewDocumentUpload(cid, tt) + return +} + +func textMessage(cid int64, mb string, quoteExternalID string) (chattable tgbotapi.Chattable, err error) { + var qid int + m := tgbotapi.NewMessage(cid, mb) + + if quoteExternalID != "" { + qid, err = strconv.Atoi(quoteExternalID) + if err != nil { + return + } + m.ReplyToMessageID = qid + } + + m.ParseMode = "Markdown" + + chattable = m + return +} + +func setAttachment(attachments *tgbotapi.Message, client *v1.MgClient, snd *v1.SendData, botToken string) error { + var ( + items []v1.Item + fileID string + caption string + ) + + t := getMessageID(attachments) + bot, err := tgbotapi.NewBotAPI(botToken) + if err != nil { + return err + } + + switch t { + case "photo": + for _, v := range *attachments.Photo { + fileID = v.FileID + } + + snd.Message.Type = v1.MsgTypeImage + caption = getLocalizedMessage(t) + case "document": + fileID = attachments.Document.FileID + snd.Message.Type = v1.MsgTypeFile + caption = attachments.Document.FileName + default: + snd.Message.Text = getLocalizedMessage(t) + } + + if fileID != "" { + file, err := getFileURL(fileID, bot) + if err != nil { + return err + } + + item, _, err := getItemData( + client, + fmt.Sprintf("https://api.telegram.org/file/bot%s/%s", botToken, file.FilePath), + caption, + ) + if err != nil { + return err + } + + items = append(items, item) + } + + if len(items) > 0 { + snd.Message.Items = items + } + + return nil +} + +func getItemData(client *v1.MgClient, url string, caption string) (v1.Item, int, error) { + item := v1.Item{} + + data, st, err := client.UploadFileByURL( + v1.UploadFileByUrlRequest{ + Url: url, + }, + ) + if err != nil { + return item, st, err + } + + item.ID = data.ID + item.Caption = caption + + return item, st, err +} + +func getFileURL(fileID string, b *tgbotapi.BotAPI) (tgbotapi.File, error) { + return b.GetFile(tgbotapi.FileConfig{FileID: fileID}) +} diff --git a/src/routing_test.go b/src/routing_test.go index f4b9445..2504e8c 100644 --- a/src/routing_test.go +++ b/src/routing_test.go @@ -79,6 +79,20 @@ func TestRouting_addBotHandler(t *testing.T) { Creating: v1.ChannelFeatureReceive, Editing: v1.ChannelFeatureReceive, }, + File: v1.ChannelSettingsFilesBase{ + Creating: v1.ChannelFeatureBoth, + Editing: v1.ChannelFeatureBoth, + Quoting: v1.ChannelFeatureBoth, + Deleting: v1.ChannelFeatureReceive, + Max: 1, + }, + Image: v1.ChannelSettingsFilesBase{ + Creating: v1.ChannelFeatureBoth, + Editing: v1.ChannelFeatureBoth, + Quoting: v1.ChannelFeatureBoth, + Deleting: v1.ChannelFeatureReceive, + Max: 10, + }, }, }