commit
3431bbe210
2
go.mod
2
go.mod
@ -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.0.6
|
||||
github.com/retailcrm/mg-transport-api-client-go v1.1.9
|
||||
github.com/retailcrm/mg-transport-api-client-go v1.1.10
|
||||
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
|
||||
|
4
go.sum
4
go.sum
@ -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.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=
|
||||
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=
|
||||
|
1
migrations/1537271655_app.down.sql
Normal file
1
migrations/1537271655_app.down.sql
Normal file
@ -0,0 +1 @@
|
||||
alter table bot drop column channel_settings_hash;
|
1
migrations/1537271655_app.up.sql
Normal file
1
migrations/1537271655_app.up.sql
Normal file
@ -0,0 +1 @@
|
||||
alter table bot add column channel_settings_hash varchar(70);
|
1
migrations/1537452694_app.down.sql
Normal file
1
migrations/1537452694_app.down.sql
Normal file
@ -0,0 +1 @@
|
||||
alter table bot drop column lang;
|
1
migrations/1537452694_app.up.sql
Normal file
1
migrations/1537452694_app.up.sql
Normal file
@ -0,0 +1 @@
|
||||
alter table bot add column lang varchar(2);
|
@ -41,6 +41,13 @@ func getLocalizedMessage(messageID string) string {
|
||||
return localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: messageID})
|
||||
}
|
||||
|
||||
func getLocalizedTemplateMessage(messageID string, templateData map[string]interface{}) string {
|
||||
return localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||
MessageID: messageID,
|
||||
TemplateData: templateData,
|
||||
})
|
||||
}
|
||||
|
||||
func getLocale() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"ButtonSave": getLocalizedMessage("button_save"),
|
||||
@ -52,6 +59,7 @@ func getLocale() map[string]interface{} {
|
||||
"AddBot": getLocalizedMessage("add_bot"),
|
||||
"TableDelete": getLocalizedMessage("table_delete"),
|
||||
"Title": getLocalizedMessage("title"),
|
||||
"Language": getLocalizedMessage("language"),
|
||||
"InfoBot": template.HTML(getLocalizedMessage("info_bot")),
|
||||
"CRMLink": template.HTML(getLocalizedMessage("crm_link")),
|
||||
"DocLink": template.HTML(getLocalizedMessage("doc_link")),
|
||||
|
@ -14,6 +14,8 @@ type Options struct {
|
||||
Config string `short:"c" long:"config" default:"config.yml" description:"Path to configuration file"`
|
||||
}
|
||||
|
||||
const Type = "telegram"
|
||||
|
||||
var (
|
||||
config *TransportConfig
|
||||
orm *Orm
|
||||
|
@ -18,13 +18,15 @@ type Connection struct {
|
||||
|
||||
// Bot model
|
||||
type Bot struct {
|
||||
ID int `gorm:"primary_key"`
|
||||
ConnectionID int `gorm:"connection_id" json:"connectionId,omitempty"`
|
||||
Channel uint64 `gorm:"channel;not null;unique" json:"channel,omitempty"`
|
||||
Token string `gorm:"token type:varchar(100);not null;unique" json:"token,omitempty"`
|
||||
Name string `gorm:"name type:varchar(40)" json:"name,omitempty"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
ID int `gorm:"primary_key"`
|
||||
ConnectionID int `gorm:"connection_id" json:"connectionId,omitempty"`
|
||||
Channel uint64 `gorm:"channel;not null;unique" json:"channel,omitempty"`
|
||||
ChannelSettingsHash string `gorm:"channel_settings_hash type:varchar(70)"`
|
||||
Token string `gorm:"token type:varchar(100);not null;unique" json:"token,omitempty"`
|
||||
Name string `gorm:"name type:varchar(40)" json:"name,omitempty"`
|
||||
Lang string `gorm:"lang type:varchar(2)" json:"lang,omitempty"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// User model
|
||||
|
@ -13,6 +13,13 @@ func getConnection(uid string) *Connection {
|
||||
return &connection
|
||||
}
|
||||
|
||||
func getConnections() []*Connection {
|
||||
var connection []*Connection
|
||||
orm.DB.Find(&connection)
|
||||
|
||||
return connection
|
||||
}
|
||||
|
||||
func getConnectionByURL(urlCrm string) *Connection {
|
||||
var connection Connection
|
||||
orm.DB.First(&connection, "api_url = ?", urlCrm)
|
||||
@ -52,6 +59,10 @@ func getBotByToken(token string) (*Bot, error) {
|
||||
return &bot, nil
|
||||
}
|
||||
|
||||
func (b *Bot) save() error {
|
||||
return orm.DB.Save(b).Error
|
||||
}
|
||||
|
||||
func (b *Bot) deleteBot() error {
|
||||
return orm.DB.Delete(b, "token = ?", b.Token).Error
|
||||
}
|
||||
|
323
src/routing.go
323
src/routing.go
@ -58,36 +58,10 @@ func addBotHandler(c *gin.Context) {
|
||||
}
|
||||
|
||||
b.Name = bot.Self.FirstName
|
||||
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conn := getConnectionById(b.ConnectionID)
|
||||
client := v1.New(conn.MGURL, conn.MGToken)
|
||||
|
||||
var client = v1.New(conn.MGURL, conn.MGToken)
|
||||
data, status, err := client.ActivateTransportChannel(ch)
|
||||
data, status, err := client.ActivateTransportChannel(getChannelSettings())
|
||||
if status != http.StatusCreated {
|
||||
c.AbortWithStatusJSON(BadRequest("error_activating_channel"))
|
||||
logger.Error(conn.APIURL, status, err.Error(), data)
|
||||
@ -143,15 +117,17 @@ func settingsHandler(c *gin.Context) {
|
||||
bots := p.getBotsByClientID()
|
||||
|
||||
res := struct {
|
||||
Conn *Connection
|
||||
Bots Bots
|
||||
Locale map[string]interface{}
|
||||
Year int
|
||||
Conn *Connection
|
||||
Bots Bots
|
||||
Locale map[string]interface{}
|
||||
Year int
|
||||
LangCode []string
|
||||
}{
|
||||
p,
|
||||
bots,
|
||||
getLocale(),
|
||||
time.Now().Year(),
|
||||
[]string{"en", "ru", "es"},
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "form", &res)
|
||||
@ -272,6 +248,25 @@ func activityHandler(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"success": true})
|
||||
}
|
||||
|
||||
func setLangBotHandler(c *gin.Context) {
|
||||
b := c.MustGet("bot").(Bot)
|
||||
cl, err := getBotByToken(b.Token)
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
cl.Lang = b.Lang
|
||||
|
||||
err = cl.save()
|
||||
if err != nil {
|
||||
c.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{})
|
||||
}
|
||||
|
||||
func getIntegrationModule(clientId string) v5.IntegrationModule {
|
||||
return v5.IntegrationModule{
|
||||
Code: config.TransportInfo.Code,
|
||||
@ -305,6 +300,98 @@ func getIntegrationModule(clientId string) v5.IntegrationModule {
|
||||
}
|
||||
}
|
||||
|
||||
func getChannelSettings(cid ...uint64) v1.Channel {
|
||||
var channelID uint64
|
||||
|
||||
if len(cid) > 0 {
|
||||
channelID = cid[0]
|
||||
}
|
||||
|
||||
return v1.Channel{
|
||||
ID: channelID,
|
||||
Type: Type,
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func updateChannelsSettings() {
|
||||
hashSettings, err := getChannelSettingsHash()
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
connections := getConnections()
|
||||
if len(connections) > 0 {
|
||||
for _, conn := range connections {
|
||||
if !conn.Active {
|
||||
logger.Infof(
|
||||
"updateChannelsSettings connection %s deactivated",
|
||||
conn.APIURL,
|
||||
)
|
||||
continue
|
||||
}
|
||||
updateBots(conn, hashSettings)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func updateBots(conn *Connection, hashSettings string) {
|
||||
bots := conn.getBotsByClientID()
|
||||
if len(bots) > 0 {
|
||||
client := v1.New(conn.MGURL, conn.MGToken)
|
||||
for _, bot := range bots {
|
||||
if bot.ChannelSettingsHash == hashSettings {
|
||||
continue
|
||||
}
|
||||
|
||||
data, status, err := client.UpdateTransportChannel(getChannelSettings(bot.Channel))
|
||||
if config.Debug {
|
||||
logger.Infof(
|
||||
"updateChannelsSettings apiURL: %s, ChannelID: %d, Data: %v, Status: %d, err: %v",
|
||||
conn.APIURL, bot.Channel, data, status, err,
|
||||
)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
bot.ChannelSettingsHash = hashSettings
|
||||
err = bot.save()
|
||||
if err != nil {
|
||||
logger.Error(
|
||||
"updateChannelsSettings bot.save apiURL: %s, bot.Channel: %d , err: %v",
|
||||
conn.APIURL, bot.Channel, err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func telegramWebhookHandler(c *gin.Context) {
|
||||
token := c.Param("token")
|
||||
b, err := getBotByToken(token)
|
||||
@ -493,17 +580,26 @@ func mgWebhookHandler(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
setLocale(b.Lang)
|
||||
|
||||
switch msg.Type {
|
||||
case "message_sent":
|
||||
var mb string
|
||||
if msg.Data.Type == v1.MsgTypeProduct {
|
||||
switch msg.Data.Type {
|
||||
case v1.MsgTypeProduct:
|
||||
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",
|
||||
msg.Data.Product.Cost.Value,
|
||||
currency[strings.ToLower(msg.Data.Product.Cost.Currency)],
|
||||
"\n%s: %s\n",
|
||||
getLocalizedMessage("item_cost"),
|
||||
getLocalizedTemplateMessage(
|
||||
"cost_currency",
|
||||
map[string]interface{}{
|
||||
"Amount": msg.Data.Product.Cost.Value,
|
||||
"Currency": currency[strings.ToLower(msg.Data.Product.Cost.Currency)],
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -512,26 +608,9 @@ func mgWebhookHandler(c *gin.Context) {
|
||||
} else {
|
||||
mb += 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 {
|
||||
case v1.MsgTypeOrder:
|
||||
mb = getOrderMessage(msg.Data.Order)
|
||||
case v1.MsgTypeText:
|
||||
mb = msg.Data.Content
|
||||
}
|
||||
|
||||
@ -588,3 +667,135 @@ func mgWebhookHandler(c *gin.Context) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func getOrderMessage(dataOrder *v1.MessageDataOrder) string {
|
||||
mb := getLocalizedMessage("order")
|
||||
|
||||
if dataOrder.Number != "" {
|
||||
mb += " " + dataOrder.Number
|
||||
}
|
||||
|
||||
if dataOrder.Date != "" {
|
||||
mb += fmt.Sprintf(" (%s)", dataOrder.Date)
|
||||
}
|
||||
mb += "\n"
|
||||
if len(dataOrder.Items) > 0 {
|
||||
mb += "\n"
|
||||
for k, v := range dataOrder.Items {
|
||||
mb += fmt.Sprintf(
|
||||
"%d. %s",
|
||||
k+1,
|
||||
v.Name,
|
||||
)
|
||||
|
||||
if v.Quantity != nil {
|
||||
if v.Quantity.Value != 0 {
|
||||
mb += fmt.Sprintf(
|
||||
" %v",
|
||||
v.Quantity.Value,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if v.Price != nil {
|
||||
if val, ok := currency[strings.ToLower(v.Price.Currency)]; ok {
|
||||
mb += fmt.Sprintf(
|
||||
" x %s\n",
|
||||
getLocalizedTemplateMessage(
|
||||
"cost_currency",
|
||||
map[string]interface{}{
|
||||
"Amount": v.Price.Value,
|
||||
"Currency": val,
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
mb += "\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if dataOrder.Delivery != nil {
|
||||
if dataOrder.Delivery.Name != "" {
|
||||
mb += fmt.Sprintf(
|
||||
"\n%s:\n%s",
|
||||
getLocalizedMessage("delivery"),
|
||||
dataOrder.Delivery.Name,
|
||||
)
|
||||
}
|
||||
|
||||
if dataOrder.Delivery.Amount != nil {
|
||||
if val, ok := currency[strings.ToLower(dataOrder.Delivery.Amount.Currency)]; ok && dataOrder.Delivery.Amount.Value != 0 {
|
||||
mb += fmt.Sprintf(
|
||||
"; %s",
|
||||
getLocalizedTemplateMessage(
|
||||
"cost_currency",
|
||||
map[string]interface{}{
|
||||
"Amount": dataOrder.Delivery.Amount.Value,
|
||||
"Currency": val,
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if dataOrder.Delivery.Address != "" {
|
||||
mb += ";\n" + dataOrder.Delivery.Address
|
||||
}
|
||||
|
||||
mb += "\n"
|
||||
}
|
||||
|
||||
if len(dataOrder.Payments) > 0 {
|
||||
mb += fmt.Sprintf(
|
||||
"\n%s:\n",
|
||||
getLocalizedMessage("payment"),
|
||||
)
|
||||
for _, v := range dataOrder.Payments {
|
||||
mb += v.Name
|
||||
|
||||
if v.Amount != nil {
|
||||
if val, ok := currency[strings.ToLower(v.Amount.Currency)]; ok && v.Amount.Value != 0 {
|
||||
mb += fmt.Sprintf(
|
||||
"; %s",
|
||||
getLocalizedTemplateMessage(
|
||||
"cost_currency",
|
||||
map[string]interface{}{
|
||||
"Amount": v.Amount.Value,
|
||||
"Currency": val,
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if v.Status != nil && v.Status.Name != "" {
|
||||
mb += fmt.Sprintf(
|
||||
" (%s)",
|
||||
v.Status.Name,
|
||||
)
|
||||
}
|
||||
|
||||
mb += "\n"
|
||||
}
|
||||
}
|
||||
|
||||
if dataOrder.Cost != nil {
|
||||
if val, ok := currency[strings.ToLower(dataOrder.Cost.Currency)]; ok && dataOrder.Cost.Value != 0 {
|
||||
mb += fmt.Sprintf(
|
||||
"\n%s: %s",
|
||||
getLocalizedMessage("order_total"),
|
||||
getLocalizedTemplateMessage(
|
||||
"cost_currency",
|
||||
map[string]interface{}{
|
||||
"Amount": dataOrder.Cost.Value,
|
||||
"Currency": val,
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return mb
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ func start() {
|
||||
func setup() *gin.Engine {
|
||||
loadTranslateFile()
|
||||
setValidation()
|
||||
updateChannelsSettings()
|
||||
|
||||
if config.Debug == false {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
@ -89,6 +90,7 @@ func setup() *gin.Engine {
|
||||
r.POST("/create/", checkConnectionForRequest(), createHandler)
|
||||
r.POST("/add-bot/", checkBotForRequest(), addBotHandler)
|
||||
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)
|
||||
|
27
src/utils.go
27
src/utils.go
@ -1,7 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@ -13,7 +15,6 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
"github.com/retailcrm/api-client-go/v5"
|
||||
)
|
||||
|
||||
@ -50,12 +51,14 @@ func getAPIClient(url, key string) (*v5.Client, error, int) {
|
||||
if res := checkCredentials(cr.Credentials); len(res) != 0 {
|
||||
logger.Error(url, status, res)
|
||||
return nil,
|
||||
errors.New(localizer.MustLocalize(&i18n.LocalizeConfig{
|
||||
MessageID: "missing_credentials",
|
||||
TemplateData: map[string]interface{}{
|
||||
"Credentials": strings.Join(res, ", "),
|
||||
},
|
||||
})),
|
||||
errors.New(
|
||||
getLocalizedTemplateMessage(
|
||||
"missing_credentials",
|
||||
map[string]interface{}{
|
||||
"Credentials": strings.Join(res, ", "),
|
||||
},
|
||||
),
|
||||
),
|
||||
http.StatusBadRequest
|
||||
}
|
||||
|
||||
@ -119,3 +122,13 @@ func UploadUserAvatar(url string) (picURLs3 string, err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getChannelSettingsHash() (hash string, err error) {
|
||||
res, err := json.Marshal(getChannelSettings())
|
||||
|
||||
h := sha1.New()
|
||||
h.Write(res)
|
||||
hash = fmt.Sprintf("%x", h.Sum(nil))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -1,3 +1,16 @@
|
||||
$(document).on("change", "select", function(e) {
|
||||
send(
|
||||
"/set-lang/",
|
||||
{
|
||||
token: $(this).attr("data-token"),
|
||||
lang: $(this).find(":selected").text()
|
||||
},
|
||||
function () {
|
||||
return 0;
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
$('#save-crm').on("submit", function(e) {
|
||||
e.preventDefault();
|
||||
send(
|
||||
@ -39,6 +52,7 @@ $("#add-bot").on("submit", function(e) {
|
||||
}
|
||||
$("#bots tbody").append(getBotTemplate(data));
|
||||
$("#token").val("");
|
||||
$('select').formSelect();
|
||||
}
|
||||
)
|
||||
});
|
||||
@ -101,6 +115,15 @@ function getBotTemplate(data) {
|
||||
`<tr>
|
||||
<td>${data.name}</td>
|
||||
<td>${data.token}</td>
|
||||
<td>
|
||||
<div class="col s3 sel-lang">
|
||||
<select data-token="${data.token}">
|
||||
<option value="en" selected>en</option>
|
||||
<option value="ru">ru</option>
|
||||
<option value="es">es</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<button class="delete-bot btn btn-small waves-effect waves-light light-blue darken-1" type="submit" name="action"
|
||||
data-token="${data.token}">
|
||||
@ -120,6 +143,7 @@ function formDataToObj(formArray) {
|
||||
}
|
||||
|
||||
$( document ).ready(function() {
|
||||
$('select').formSelect();
|
||||
M.Tabs.init(document.getElementById("tab"));
|
||||
if ($("table tbody").children().length === 0) {
|
||||
$("#bots").addClass("hide");
|
||||
|
@ -32,10 +32,19 @@ main {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#bots .select-wrapper input.select-dropdown,
|
||||
#bots {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#bots .sel-lang{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#bots .select-wrapper ul li span{
|
||||
color: #039be5;
|
||||
}
|
||||
|
||||
#msg{
|
||||
height: 23px;
|
||||
}
|
||||
|
@ -51,19 +51,31 @@
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{{$LangCode := .LangCode}}
|
||||
<table id="bots" class="tab-el-center">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{.Locale.TableName}}</th>
|
||||
<th>{{.Locale.TableToken}}</th>
|
||||
<th>{{.Locale.Language}}</th>
|
||||
<th class="text-left">{{.Locale.TableDelete}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Bots}}
|
||||
{{$lang := .Lang}}
|
||||
<tr>
|
||||
<td>{{.Name}}</td>
|
||||
<td>{{.Token}}</td>
|
||||
<td>
|
||||
<div class="col s3 sel-lang">
|
||||
<select data-token="{{.Token}}">
|
||||
{{range $key, $value := $LangCode}}
|
||||
<option value="{{$value}}" {{if eq $value $lang}}selected{{end}}>{{$value}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<button class="delete-bot btn btn-small waves-effect waves-light light-blue darken-1" type="submit" name="action"
|
||||
data-token="{{.Token}}">
|
||||
|
@ -3,9 +3,9 @@
|
||||
<meta title="Telegram transport">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>{{.Locale.Title}}</title>
|
||||
<link rel="stylesheet" href="/static/materialize.min.css">
|
||||
<link rel="stylesheet" href="/static/font.css" >
|
||||
<link rel="stylesheet" href="/static/jquery-confirm.min.css">
|
||||
<link rel="stylesheet" href="/static/materialize.min.css">
|
||||
<link rel="stylesheet" href="/static/style.css" >
|
||||
</head>
|
||||
<body>
|
||||
@ -29,8 +29,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="/static/materialize.min.js"></script>
|
||||
<script src="/static/jquery-3.3.1.min.js"></script>
|
||||
<script src="/static/materialize.min.js"></script>
|
||||
<script src="/static/jquery-confirm.min.js"></script>
|
||||
<script src="/static/script.js"></script>
|
||||
</body>
|
||||
|
@ -8,6 +8,7 @@ api_key: API key
|
||||
add_bot: Add a bot
|
||||
title: Module of connecting Telegram to retailCRM
|
||||
successful: Data was updated successfully
|
||||
language: Language
|
||||
|
||||
no_bot_token: Enter a token
|
||||
wrong_data: Wrong data
|
||||
@ -41,3 +42,10 @@ video: "[video]"
|
||||
voice: "[voice message]"
|
||||
photo: "[photo]"
|
||||
undefined: "[undefined format of a message]"
|
||||
|
||||
item_cost: "Cost"
|
||||
order: "Order"
|
||||
delivery: "Delivery"
|
||||
payment: "Payment"
|
||||
order_total: "Order total"
|
||||
cost_currency: "{{.Amount}} {{.Currency}}"
|
||||
|
@ -8,6 +8,7 @@ api_key: API key
|
||||
add_bot: Añadir un bot
|
||||
title: Múdulo de conexión de Telegram a retailCRM
|
||||
successful: Datos actualizados con éxito
|
||||
language: Idioma
|
||||
|
||||
no_bot_token: Introduzca un token
|
||||
wrong_data: Datos erróneos
|
||||
@ -41,3 +42,10 @@ video: "[video]"
|
||||
voice: "[mensaje de voz]"
|
||||
photo: "[foto]"
|
||||
other: "[formato indefinido de mensaje]"
|
||||
|
||||
item_cost: "Precio"
|
||||
order: "Pedido"
|
||||
delivery: "Entrega"
|
||||
payment: "Pago"
|
||||
order_total: "Total pedido"
|
||||
cost_currency: "{{.Amount}} {{.Currency}}"
|
||||
|
@ -8,6 +8,7 @@ api_key: API Ключ
|
||||
add_bot: Добавить бота
|
||||
title: Модуль подключения Telegram к retailCRM
|
||||
successful: Данные успешно обновлены
|
||||
language: Язык
|
||||
|
||||
no_bot_token: Введите токен
|
||||
wrong_data: Неверные данные
|
||||
@ -41,3 +42,10 @@ video: "[видео]"
|
||||
voice: "[голосовое сообщение]"
|
||||
photo: "[изображение]"
|
||||
undefined: "[неопределенный формат сообщения]"
|
||||
|
||||
item_cost: "Цена"
|
||||
order: "Заказ"
|
||||
delivery: "Доставка"
|
||||
payment: "Оплата"
|
||||
order_total: "Сумма"
|
||||
cost_currency: "{{.Amount}} {{.Currency}}"
|
||||
|
Loading…
Reference in New Issue
Block a user