mg-transport-core/core/utils.go

211 lines
4.8 KiB
Go

package core
import (
"crypto/sha1"
"crypto/sha256"
"encoding/json"
"errors"
"fmt"
"net/http"
"regexp"
"strings"
"sync/atomic"
"time"
"github.com/aws/aws-sdk-go/aws"
"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/op/go-logging"
v5 "github.com/retailcrm/api-client-go/v5"
v1 "github.com/retailcrm/mg-transport-api-client-go/v1"
)
// Utils service object
type Utils struct {
IsDebug bool
ConfigAWS ConfigAWS
Logger *logging.Logger
TokenCounter uint32
slashRegex *regexp.Regexp
}
// NewUtils will create new Utils instance
func NewUtils(awsConfig ConfigAWS, logger *logging.Logger, debug bool) *Utils {
return &Utils{
IsDebug: debug,
ConfigAWS: awsConfig,
Logger: logger,
TokenCounter: 0,
slashRegex: slashRegex,
}
}
// resetUtils
func (u *Utils) resetUtils(awsConfig ConfigAWS, debug bool, tokenCounter uint32) {
u.TokenCounter = tokenCounter
u.ConfigAWS = awsConfig
u.IsDebug = debug
u.slashRegex = slashRegex
}
// GenerateToken will generate long pseudo-random string.
func (u *Utils) GenerateToken() string {
c := atomic.AddUint32(&u.TokenCounter, 1)
return fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%d%d", time.Now().UnixNano(), c))))
}
// GetAPIClient will initialize retailCRM api client from url and key
func (u *Utils) GetAPIClient(url, key string) (*v5.Client, int, error) {
client := v5.New(url, key)
client.Debug = u.IsDebug
cr, status, e := client.APICredentials()
if e != nil && e.Error() != "" {
u.Logger.Error(url, status, e.Error(), cr)
return nil, http.StatusInternalServerError, errors.New(e.Error())
}
if !cr.Success {
errMsg := "unknown error"
if e != nil {
if e.ApiError() != "" {
errMsg = e.ApiError()
} else if e.ApiErrors() != nil {
errMsg = ""
for key, errText := range e.ApiErrors() {
errMsg += fmt.Sprintf("[%s: %s] ", key, errText)
}
}
}
u.Logger.Error(url, status, errMsg, cr)
return nil, http.StatusBadRequest, errors.New("invalid credentials")
}
if res := u.checkCredentials(cr.Credentials); len(res) != 0 {
u.Logger.Error(url, status, res)
return nil, http.StatusBadRequest, errors.New("missing credentials")
}
return client, 0, nil
}
func (u *Utils) checkCredentials(credential []string) []string {
rc := make([]string, len(credentialsTransport))
copy(rc, credentialsTransport)
for _, vc := range credential {
for kn, vn := range rc {
if vn == vc {
if len(rc) == 1 {
rc = rc[:0]
break
}
rc = append(rc[:kn], rc[kn+1:]...)
}
}
}
return rc
}
// UploadUserAvatar will upload avatar for user
func (u *Utils) UploadUserAvatar(url string) (picURLs3 string, err error) {
s3Config := &aws.Config{
Credentials: credentials.NewStaticCredentials(
u.ConfigAWS.AccessKeyID,
u.ConfigAWS.SecretAccessKey,
""),
Region: aws.String(u.ConfigAWS.Region),
}
s := session.Must(session.NewSession(s3Config))
uploader := s3manager.NewUploader(s)
resp, err := http.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode >= http.StatusBadRequest {
return "", fmt.Errorf("get: %v code: %v", url, resp.StatusCode)
}
result, err := uploader.Upload(&s3manager.UploadInput{
Bucket: aws.String(u.ConfigAWS.Bucket),
Key: aws.String(fmt.Sprintf("%v/%v.jpg", u.ConfigAWS.FolderName, u.GenerateToken())),
Body: resp.Body,
ContentType: aws.String(u.ConfigAWS.ContentType),
ACL: aws.String("public-read"),
})
if err != nil {
return
}
picURLs3 = result.Location
return
}
// RemoveTrailingSlash will remove slash at the end of any string
func (u *Utils) RemoveTrailingSlash(crmURL string) string {
return u.slashRegex.ReplaceAllString(crmURL, ``)
}
// GetMGItemData will upload file to MG by URL and return information about attachable item
func GetMGItemData(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
}
// GetEntitySHA1 will serialize any value to JSON and return SHA1 hash of this JSON
func GetEntitySHA1(v interface{}) (hash string, err error) {
res, _ := json.Marshal(v)
h := sha1.New()
_, err = h.Write(res)
hash = fmt.Sprintf("%x", h.Sum(nil))
return
}
// ReplaceMarkdownSymbols will remove markdown symbols from text
func ReplaceMarkdownSymbols(s string) string {
for _, v := range markdownSymbols {
s = strings.Replace(s, v, "\\"+v, -1)
}
return s
}
// DefaultCurrencies will return default currencies list for all bots
func DefaultCurrencies() map[string]string {
return map[string]string{
"rub": "₽",
"uah": "₴",
"byr": "Br",
"kzt": "₸",
"usd": "$",
"eur": "€",
}
}