mirror of
https://github.com/retailcrm/mg-bot-api-client-go.git
synced 2025-04-11 13:00:54 +00:00
Compare commits
68 commits
Author | SHA1 | Date | |
---|---|---|---|
9e5fb7afec | |||
|
3b56a36b3b | ||
1ba7024ccc | |||
|
fe5c8e9676 | ||
e2205fb4d9 | |||
223e63b268 | |||
7cec2bb237 | |||
c338d2e19e | |||
a101bd502a | |||
021568afd8 | |||
f7e352a622 | |||
5466d2d1ad | |||
0e970386ce | |||
|
8b0193186b | ||
|
c7b7f73c4f | ||
|
22d56ef2dc | ||
|
f6affa2063 | ||
|
d5aa1a0794 | ||
|
bc9702741e | ||
|
46a262a5dc | ||
7b80d3d542 | |||
|
b0e374f88e | ||
8eb473d7d2 | |||
|
bbea93671e | ||
|
ca83218213 | ||
074f787d0f | |||
d01abbc1bb | |||
|
88eeda804b | ||
|
e090080325 | ||
|
3e9078ee86 | ||
|
de3eca3a55 | ||
|
73b06d5de4 | ||
3d84ddaee6 | |||
|
6090ceebcf | ||
506a6a1d61 | |||
|
272cdaa60c | ||
edf67afb08 | |||
|
9ecd6f85a1 | ||
9ee3653827 | |||
|
ae8c5793dc | ||
4058284e32 | |||
1c8f6885e6 | |||
|
8a0219a962 | ||
5190445cc4 | |||
|
632153073d | ||
3fb19e388b | |||
c68299f924 | |||
942cf81ce6 | |||
|
2c5a6ef463 | ||
|
56bf4df310 | ||
21e9551b32 | |||
582acf20eb | |||
|
1ea6a6ec9d | ||
6674d05af5 | |||
|
a9d74ceee4 | ||
d21f159a57 | |||
|
d74d2fea2a | ||
|
f3ea711138 | ||
77f3af2445 | |||
|
3cf9c28f51 | ||
9400a2b045 | |||
|
68d7defc91 | ||
a42575b51c | |||
|
431c55576f | ||
78201aa2d3 | |||
|
3555b34ad3 | ||
f2c1365a51 | |||
|
2e4ba1e681 |
5 changed files with 734 additions and 158 deletions
18
.github/workflows/ci.yml
vendored
18
.github/workflows/ci.yml
vendored
|
@ -19,33 +19,33 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up latest Go 1.x version
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Go 1.24
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.17'
|
||||
go-version: '1.24'
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go mod tidy
|
||||
cp .env.dist .env
|
||||
- name: Lint code with golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
version: v1.36
|
||||
version: v1.62.2
|
||||
only-new-issues: true
|
||||
tests:
|
||||
name: Tests
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: ['1.13', '1.14', '1.15', '1.16']
|
||||
go-version: ['1.13', '1.14', '1.15', '1.16', '1.17', '1.18', '1.19', '1.20', '1.21', '1.22', '1.23', '1.24']
|
||||
steps:
|
||||
- name: Set up Go ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v2
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Get dependencies
|
||||
run: |
|
||||
go mod tidy
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
run:
|
||||
skip-dirs-use-default: true
|
||||
allow-parallel-runners: true
|
||||
modules-download-mode: readonly
|
||||
|
||||
output:
|
||||
format: colored-line-number
|
||||
formats:
|
||||
- format: colored-line-number
|
||||
sort-results: true
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- deadcode
|
||||
- errcheck
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- unused
|
||||
- unparam
|
||||
- varcheck
|
||||
- bodyclose
|
||||
- dogsled
|
||||
- dupl
|
||||
- errorlint
|
||||
- exhaustive
|
||||
- exportloopref
|
||||
- copyloopvar
|
||||
- funlen
|
||||
- gocognit
|
||||
- goconst
|
||||
|
@ -32,26 +30,23 @@ linters:
|
|||
- gocyclo
|
||||
- godot
|
||||
- goimports
|
||||
- golint
|
||||
- gomnd
|
||||
- revive
|
||||
- mnd
|
||||
- gosec
|
||||
- ifshort
|
||||
- interfacer
|
||||
- lll
|
||||
- makezero
|
||||
- maligned
|
||||
- misspell
|
||||
- nestif
|
||||
- prealloc
|
||||
- predeclared
|
||||
- scopelint
|
||||
- sqlclosecheck
|
||||
- unconvert
|
||||
- whitespace
|
||||
- unused
|
||||
- testifylint
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
check-shadowing: false
|
||||
disable-all: true
|
||||
enable:
|
||||
- assign
|
||||
|
@ -70,7 +65,6 @@ linters-settings:
|
|||
- unmarshal
|
||||
- unreachable
|
||||
- unsafeptr
|
||||
- unused
|
||||
settings:
|
||||
printf:
|
||||
funcs:
|
||||
|
@ -119,8 +113,6 @@ linters-settings:
|
|||
- log.Printf
|
||||
- log.Println
|
||||
- runtime/trace.Logf
|
||||
unused:
|
||||
check-exported: false
|
||||
unparam:
|
||||
check-exported: false
|
||||
dogsled:
|
||||
|
@ -129,11 +121,13 @@ linters-settings:
|
|||
threshold: 200
|
||||
errorlint:
|
||||
errorf: true
|
||||
asserts: true
|
||||
comparison: true
|
||||
exhaustive:
|
||||
check-generated: false
|
||||
default-signifies-exhaustive: false
|
||||
funlen:
|
||||
lines: 60
|
||||
lines: 90
|
||||
statements: 40
|
||||
gocognit:
|
||||
min-complexity: 25
|
||||
|
@ -143,8 +137,6 @@ linters-settings:
|
|||
local-prefixes: github.com/retailcrm/mg-bot-api-client-go
|
||||
lll:
|
||||
line-length: 120
|
||||
maligned:
|
||||
suggest-new: true
|
||||
misspell:
|
||||
locale: US
|
||||
nestif:
|
||||
|
@ -157,7 +149,8 @@ issues:
|
|||
exclude-rules:
|
||||
- path: _test\.go
|
||||
linters:
|
||||
- gomnd
|
||||
- dupl
|
||||
- mnd
|
||||
- lll
|
||||
- bodyclose
|
||||
- errcheck
|
||||
|
@ -183,7 +176,4 @@ issues:
|
|||
|
||||
severity:
|
||||
default-severity: error
|
||||
case-sensitive: false
|
||||
|
||||
service:
|
||||
golangci-lint-version: 1.36.x
|
||||
case-sensitive: false
|
137
v1/client.go
137
v1/client.go
|
@ -14,16 +14,46 @@ import (
|
|||
"github.com/google/go-querystring/query"
|
||||
)
|
||||
|
||||
type Option func(*MgClient)
|
||||
|
||||
// OptionHTTPClient set custom http.Client for MgClient.
|
||||
func OptionHTTPClient(client *http.Client) func(*MgClient) {
|
||||
return func(c *MgClient) {
|
||||
c.httpClient = client
|
||||
}
|
||||
}
|
||||
|
||||
// OptionLogger sets the provided logger instance into the MgClient.
|
||||
func OptionLogger(logger BasicLogger) func(*MgClient) {
|
||||
return func(c *MgClient) {
|
||||
c.logger = logger
|
||||
}
|
||||
}
|
||||
|
||||
// OptionDebug enables debug mode for MgClient.
|
||||
func OptionDebug() func(*MgClient) {
|
||||
return func(c *MgClient) {
|
||||
c.Debug = true
|
||||
}
|
||||
}
|
||||
|
||||
// New initialize client
|
||||
func New(url string, token string) *MgClient {
|
||||
return &MgClient{
|
||||
func New(url string, token string, opts ...Option) *MgClient {
|
||||
c := &MgClient{
|
||||
URL: url,
|
||||
Token: token,
|
||||
httpClient: &http.Client{Timeout: time.Minute},
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// WithLogger sets the provided logger instance into the Client.
|
||||
// Deprecated: Use functional option OptionLogger instead.
|
||||
func (c *MgClient) WithLogger(logger BasicLogger) *MgClient {
|
||||
c.logger = logger
|
||||
return c
|
||||
|
@ -427,6 +457,50 @@ func (c *MgClient) DialogClose(request uint64) (map[string]interface{}, int, err
|
|||
return resp, status, err
|
||||
}
|
||||
|
||||
// DialogsTagsAdd allows to assign dialog to Bot or User
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var client = v1.New("https://demo.url", "09jIJ")
|
||||
//
|
||||
// data, status, err := client.DialogsTagsAdd(DialogTagsAddRequest{DialogID: uint64(1),Tags: []TagsAdd{{Name: "foo"}}})
|
||||
func (c *MgClient) DialogsTagsAdd(request DialogTagsAddRequest) (int, error) {
|
||||
outgoing, _ := json.Marshal(&request)
|
||||
|
||||
data, status, err := c.PatchRequest(fmt.Sprintf("/dialogs/%d/tags/add", request.DialogID), outgoing)
|
||||
if err != nil {
|
||||
return status, err
|
||||
}
|
||||
|
||||
if status != http.StatusOK {
|
||||
return status, c.Error(data)
|
||||
}
|
||||
|
||||
return status, err
|
||||
}
|
||||
|
||||
// DialogTagsDelete allows to assign dialog to Bot or User
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// var client = v1.New("https://demo.url", "09jIJ")
|
||||
//
|
||||
// data, status, err := client.DialogsTagsAdd(DialogTagsDelete{DialogID: uint64(1),Tags: []TagsDelete{{Name: "foo"}}})
|
||||
func (c *MgClient) DialogTagsDelete(request DialogTagsDeleteRequest) (int, error) {
|
||||
outgoing, _ := json.Marshal(&request)
|
||||
|
||||
data, status, err := c.PatchRequest(fmt.Sprintf("/dialogs/%d/tags/delete", request.DialogID), outgoing)
|
||||
if err != nil {
|
||||
return status, err
|
||||
}
|
||||
|
||||
if status != http.StatusOK {
|
||||
return status, c.Error(data)
|
||||
}
|
||||
|
||||
return status, err
|
||||
}
|
||||
|
||||
// Messages get all available messages
|
||||
//
|
||||
// Example:
|
||||
|
@ -838,8 +912,57 @@ func (c *MgClient) UploadFileByURL(request UploadFileByUrlRequest) (UploadFileRe
|
|||
return resp, status, err
|
||||
}
|
||||
|
||||
// UpdateFileMetadata update file metadata
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// response, status, err := c.UpdateFileMetadata(UploadFileByUrlRequest{
|
||||
// ID: "e038aa39-2338-4285-be86-e2a0bb424daa"
|
||||
// Transcription: "demo transcription",
|
||||
// })
|
||||
//
|
||||
// if err != nil {
|
||||
// fmt.Printf("%v", err)
|
||||
// }
|
||||
//
|
||||
// fmt.Printf("%s\n%s", response.ID, status)
|
||||
func (c *MgClient) UpdateFileMetadata(request UpdateFileMetadataRequest) (UploadFileResponse, int, error) {
|
||||
var resp UploadFileResponse
|
||||
outgoing, err := json.Marshal(&request)
|
||||
if err != nil {
|
||||
return resp, 0, err
|
||||
}
|
||||
|
||||
data, status, err := c.PutRequest(fmt.Sprintf("/files/%s/meta", request.ID), outgoing)
|
||||
if err != nil {
|
||||
return resp, status, err
|
||||
}
|
||||
|
||||
if status != http.StatusOK {
|
||||
return resp, status, c.Error(data)
|
||||
}
|
||||
|
||||
if e := json.Unmarshal(data, &resp); e != nil {
|
||||
return resp, status, e
|
||||
}
|
||||
|
||||
return resp, status, err
|
||||
}
|
||||
|
||||
type wsParams struct {
|
||||
options []string
|
||||
}
|
||||
|
||||
type WsParams interface {
|
||||
apply(*wsParams)
|
||||
}
|
||||
|
||||
func (c WsOption) apply(opts *wsParams) {
|
||||
opts.options = append(opts.options, string(c))
|
||||
}
|
||||
|
||||
// WsMeta let you receive url & headers to open web socket connection
|
||||
func (c *MgClient) WsMeta(events []string) (string, http.Header, error) {
|
||||
func (c *MgClient) WsMeta(events []string, urlParams ...WsParams) (string, http.Header, error) {
|
||||
var url string
|
||||
|
||||
if len(events) < 1 {
|
||||
|
@ -849,6 +972,14 @@ func (c *MgClient) WsMeta(events []string) (string, http.Header, error) {
|
|||
|
||||
url = fmt.Sprintf("%s%s%s%s", strings.Replace(c.URL, "https", "wss", 1), prefix, "/ws?events=", strings.Join(events[:], ","))
|
||||
|
||||
var params wsParams
|
||||
for _, param := range urlParams {
|
||||
param.apply(¶ms)
|
||||
}
|
||||
if len(params.options) > 0 {
|
||||
url = fmt.Sprintf("%s&options=%s", url, strings.Join(params.options, ","))
|
||||
}
|
||||
|
||||
if url == "" {
|
||||
err := errors.New("empty WS URL")
|
||||
return url, nil, err
|
||||
|
|
|
@ -2,8 +2,12 @@ package v1
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/require"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
|
@ -44,14 +48,12 @@ var (
|
|||
debug, _ = strconv.ParseBool(os.Getenv("DEBUG"))
|
||||
)
|
||||
|
||||
func client() *MgClient {
|
||||
c := New(mgURL, mgToken)
|
||||
|
||||
func client(opts ...Option) *MgClient {
|
||||
if debug != false {
|
||||
c.Debug = true
|
||||
opts = append(opts, OptionDebug())
|
||||
}
|
||||
|
||||
return c
|
||||
return New(mgURL, mgToken, opts...)
|
||||
}
|
||||
|
||||
func TestMgClient_Bots(t *testing.T) {
|
||||
|
@ -71,7 +73,7 @@ func TestMgClient_Bots(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, data)
|
||||
|
||||
for _, bot := range data {
|
||||
|
@ -150,7 +152,7 @@ func TestMgClient_Channels(t *testing.T) {
|
|||
]`)
|
||||
|
||||
channels, status, err := c.Channels(ChannelsRequest{Active: 1})
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 200, status)
|
||||
assert.Len(t, channels, 1)
|
||||
|
||||
|
@ -214,7 +216,7 @@ func TestMgClient_Users(t *testing.T) {
|
|||
gock.New(mgURL).
|
||||
Get("/api/bot/v1/users").
|
||||
Reply(200).
|
||||
BodyString(`[{"id": 1, "external_id":"1", "username": "Test", "first_name":"Test", "last_name":"Test", "created_at": "2018-01-01T00:00:00.000000Z", "is_active": true, "is_online": true}]`)
|
||||
BodyString(`[{"id": 1, "external_id":"1", "username": "Test", "first_name":"Test", "last_name":"Test", "created_at": "2018-01-01T00:00:00.000000Z", "is_active": true, "is_online": true, "is_technical_account": true}]`)
|
||||
|
||||
req := UsersRequest{Active: 1}
|
||||
|
||||
|
@ -223,11 +225,19 @@ func TestMgClient_Users(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, data)
|
||||
|
||||
for _, user := range data {
|
||||
assert.NotEmpty(t, user.FirstName)
|
||||
assert.Equal(t, uint64(1), user.ID)
|
||||
assert.Equal(t, "1", user.ExternalID)
|
||||
assert.Equal(t, "Test", user.Username)
|
||||
assert.Equal(t, "Test", user.FirstName)
|
||||
assert.Equal(t, "Test", user.LastName)
|
||||
assert.Equal(t, "2018-01-01T00:00:00.000000Z", user.CreatedAt)
|
||||
assert.True(t, user.IsActive)
|
||||
assert.True(t, user.IsOnline)
|
||||
assert.True(t, user.IsTechnicalAccount)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,10 +246,44 @@ func TestMgClient_Customers(t *testing.T) {
|
|||
|
||||
defer gock.Off()
|
||||
|
||||
response := `
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"channel_id": 1,
|
||||
"created_at":
|
||||
"2018-01-01T00:00:00.000000Z",
|
||||
"utm": {
|
||||
"source": "test"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"channel_id": 1,
|
||||
"created_at":
|
||||
"2018-01-01T00:00:00.000000Z",
|
||||
"utm": {
|
||||
"source": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"channel_id": 1,
|
||||
"created_at":
|
||||
"2018-01-01T00:00:00.000000Z",
|
||||
"utm": null
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"channel_id": 1,
|
||||
"created_at": "2018-01-01T00:00:00.000000Z"
|
||||
}
|
||||
]`
|
||||
|
||||
gock.New(mgURL).
|
||||
Get("/api/bot/v1/customers").
|
||||
Reply(200).
|
||||
BodyString(`[{"id": 1,"channel_id": 1, "created_at": "2018-01-01T00:00:00.000000Z"}]`)
|
||||
BodyString(response)
|
||||
|
||||
req := CustomersRequest{}
|
||||
|
||||
|
@ -248,12 +292,17 @@ func TestMgClient_Customers(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, data)
|
||||
|
||||
for _, customer := range data {
|
||||
assert.NotEmpty(t, customer.ChannelId)
|
||||
}
|
||||
|
||||
assert.Equal(t, "test", data[0].Utm.Source)
|
||||
assert.Equal(t, "", data[1].Utm.Source)
|
||||
assert.Nil(t, data[2].Utm)
|
||||
assert.Nil(t, data[3].Utm)
|
||||
}
|
||||
|
||||
func TestMgClient_Chats(t *testing.T) {
|
||||
|
@ -264,16 +313,22 @@ func TestMgClient_Chats(t *testing.T) {
|
|||
gock.New(mgURL).
|
||||
Get("/api/bot/v1/chats").
|
||||
Reply(200).
|
||||
BodyString(`[{"id": 1,"customer": {"id": 1, "name": "Test"}, "created_at": "2018-01-01T00:00:00.000000Z"}]`)
|
||||
BodyString(`[
|
||||
{"id": 2,"customer": {"id": 2, "name": "Foo"}, "created_at": "2018-01-01T00:00:00.000000Z"},
|
||||
{"id": 3,"customer": {"id": 3, "name": "Bar"}, "created_at": "2018-01-02T00:00:00.000000Z"}
|
||||
]`)
|
||||
|
||||
req := ChatsRequest{ChannelType: ChannelTypeTelegram}
|
||||
req := ChatsRequest{
|
||||
ChannelType: ChannelTypeTelegram,
|
||||
SinceID: 1,
|
||||
}
|
||||
|
||||
data, status, err := c.Chats(req)
|
||||
if err != nil {
|
||||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, data)
|
||||
|
||||
for _, chat := range data {
|
||||
|
@ -298,7 +353,7 @@ func TestMgClient_Members(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, member := range data {
|
||||
assert.NotEmpty(t, member.ChatID)
|
||||
|
@ -315,14 +370,14 @@ func TestMgClient_Dialogs(t *testing.T) {
|
|||
Reply(200).
|
||||
BodyString(`[{"id": 1, "chat_id": 1, "created_at": "2018-01-01T00:00:00.000000Z"}]`)
|
||||
|
||||
req := DialogsRequest{Active: 0}
|
||||
req := DialogsRequest{Active: 0, SinceID: 1}
|
||||
|
||||
data, status, err := c.Dialogs(req)
|
||||
if err != nil {
|
||||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, data)
|
||||
|
||||
for _, dialog := range data {
|
||||
|
@ -364,7 +419,7 @@ func TestMgClient_DialogUnassign(t *testing.T) {
|
|||
|
||||
resp, status, err := c.DialogUnassign(777)
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, status)
|
||||
|
||||
assert.Equal(t, int64(111), resp.PreviousResponsible.ID)
|
||||
|
@ -426,6 +481,59 @@ func TestMgClient_DialogClose(t *testing.T) {
|
|||
assert.Equal(t, http.StatusBadRequest, status)
|
||||
}
|
||||
|
||||
func TestMgClient_DialogsTagsAdd(t *testing.T) {
|
||||
c := client()
|
||||
|
||||
color := ColorBlue
|
||||
req := DialogTagsAddRequest{
|
||||
DialogID: uint64(1),
|
||||
Tags: []TagsAdd{
|
||||
{Name: "foo", ColorCode: nil},
|
||||
{Name: "bar", ColorCode: &color},
|
||||
},
|
||||
}
|
||||
r, _ := json.Marshal(req)
|
||||
|
||||
defer gock.Off()
|
||||
|
||||
gock.New(mgURL).
|
||||
Patch("/api/bot/v1/dialogs/1/tags/add").
|
||||
JSON(r).
|
||||
Reply(200).
|
||||
BodyString(`{}`)
|
||||
|
||||
status, err := c.DialogsTagsAdd(req)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, status)
|
||||
}
|
||||
|
||||
func TestMgClient_DialogsTagsDelete(t *testing.T) {
|
||||
c := client()
|
||||
|
||||
req := DialogTagsDeleteRequest{
|
||||
DialogID: uint64(1),
|
||||
Tags: []TagsDelete{
|
||||
{Name: "foo"},
|
||||
{Name: "bar"},
|
||||
},
|
||||
}
|
||||
r, _ := json.Marshal(req)
|
||||
|
||||
defer gock.Off()
|
||||
|
||||
gock.New(mgURL).
|
||||
Patch("/api/bot/v1/dialogs/1/tags/delete").
|
||||
JSON(r).
|
||||
Reply(200).
|
||||
BodyString(`{}`)
|
||||
|
||||
status, err := c.DialogTagsDelete(req)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, status)
|
||||
}
|
||||
|
||||
func TestMgClient_Messages(t *testing.T) {
|
||||
c := client()
|
||||
|
||||
|
@ -443,7 +551,7 @@ func TestMgClient_Messages(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, data)
|
||||
|
||||
for _, message := range data {
|
||||
|
@ -451,6 +559,83 @@ func TestMgClient_Messages(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestMgClient_MessagesDialog(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
c := client()
|
||||
|
||||
defer gock.Off()
|
||||
|
||||
gock.New(mgURL).
|
||||
Get("/api/bot/v1/messages").
|
||||
Reply(200).
|
||||
BodyString(`[
|
||||
{
|
||||
"id": 1,
|
||||
"time": "2024-11-14T20:48:21Z",
|
||||
"type": "system",
|
||||
"scope": "private",
|
||||
"chat_id": 1,
|
||||
"is_read": false,
|
||||
"is_edit": false,
|
||||
"status": "received",
|
||||
"dialog": {
|
||||
"id": 2054
|
||||
},
|
||||
"action": "dialog_closed",
|
||||
"channel_id": 71,
|
||||
"created_at": "2024-11-14T20:48:21.907566Z",
|
||||
"updated_at": "2024-11-14T20:48:21.907566Z"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"time": "2024-11-14T19:58:42Z",
|
||||
"type": "text",
|
||||
"scope": "public",
|
||||
"chat_id": 1,
|
||||
"is_read": false,
|
||||
"is_edit": false,
|
||||
"status": "failed",
|
||||
"from": {
|
||||
"id": 1,
|
||||
"external_id": "1",
|
||||
"type": "user",
|
||||
"avatar": "http://avatars-test.jpeg",
|
||||
"name": "John Smith",
|
||||
"first_name": "John",
|
||||
"last_name": "Smith",
|
||||
"available": true
|
||||
},
|
||||
"dialog": {
|
||||
"id": 2054
|
||||
},
|
||||
"error": {
|
||||
"code": "malformed_response"
|
||||
},
|
||||
"content": "Message from user John Smith",
|
||||
"quote": null,
|
||||
"channel_id": 71,
|
||||
"created_at": "2024-11-14T19:58:42.933025Z",
|
||||
"updated_at": "2024-11-14T19:58:45.01619Z"
|
||||
}
|
||||
]`)
|
||||
|
||||
req := MessagesRequest{}
|
||||
|
||||
data, status, err := c.Messages(req)
|
||||
if err != nil {
|
||||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, data, 2)
|
||||
|
||||
for _, m := range data {
|
||||
assert.NotNil(t, m.Message.Dialog)
|
||||
assert.Equal(t, uint64(2054), m.Message.Dialog.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMgClient_MessageSendText(t *testing.T) {
|
||||
c := client()
|
||||
|
||||
|
@ -475,7 +660,7 @@ func TestMgClient_MessageSendText(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, data.MessageID)
|
||||
}
|
||||
|
||||
|
@ -513,7 +698,7 @@ func TestMgClient_MessageSendTextWithSuggestions(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, data.MessageID)
|
||||
}
|
||||
|
||||
|
@ -554,7 +739,7 @@ func TestMgClient_MessageSendProduct(t *testing.T) {
|
|||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
t.Logf("%v", msg)
|
||||
}
|
||||
|
||||
|
@ -614,7 +799,7 @@ func TestMgClient_MessageSendOrder(t *testing.T) {
|
|||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
t.Logf("%v", msg)
|
||||
}
|
||||
|
||||
|
@ -683,7 +868,7 @@ func TestMgClient_Info(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestMgClient_Commands(t *testing.T) {
|
||||
|
@ -703,7 +888,7 @@ func TestMgClient_Commands(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, data)
|
||||
|
||||
for _, command := range data {
|
||||
|
@ -731,7 +916,7 @@ func TestMgClient_CommandEditDelete(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, n.ID)
|
||||
|
||||
gock.New(mgURL).
|
||||
|
@ -744,10 +929,28 @@ func TestMgClient_CommandEditDelete(t *testing.T) {
|
|||
t.Errorf("%d %v", status, err)
|
||||
}
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
t.Logf("%v", d)
|
||||
}
|
||||
|
||||
func TestMgClient_WsMeta_With_Options(t *testing.T) {
|
||||
c := client()
|
||||
events := []string{"user_updated", "user_join_chat"}
|
||||
params := []WsParams{WsOptionIncludeMassCommunication}
|
||||
|
||||
url, headers, err := c.WsMeta(events, params...)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
resURL := "wss://api.example.com/api/bot/v1/ws?events=user_updated,user_join_chat&options=include_mass_communication"
|
||||
resToken := c.Token
|
||||
|
||||
assert.Equal(t, resURL, url)
|
||||
assert.Equal(t, resToken, headers["X-Bot-Token"][0])
|
||||
}
|
||||
|
||||
func TestMgClient_WsMeta(t *testing.T) {
|
||||
c := client()
|
||||
events := []string{"user_updated", "user_join_chat"}
|
||||
|
@ -757,23 +960,56 @@ func TestMgClient_WsMeta(t *testing.T) {
|
|||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
resUrl := fmt.Sprintf("%s%s%s%s", strings.Replace(c.URL, "https", "wss", 1), prefix, "/ws?events=", strings.Join(events[:], ","))
|
||||
resURL := fmt.Sprintf("%s%s%s%s", strings.Replace(c.URL, "https", "wss", 1), prefix, "/ws?events=", strings.Join(events, ","))
|
||||
resToken := c.Token
|
||||
|
||||
assert.Equal(t, resUrl, url)
|
||||
assert.Equal(t, resURL, url)
|
||||
assert.Equal(t, resToken, headers["X-Bot-Token"][0])
|
||||
}
|
||||
|
||||
func TestMgClient_UploadFile(t *testing.T) {
|
||||
c := client()
|
||||
|
||||
defer gock.Off()
|
||||
gock.New("https://via.placeholder.com").
|
||||
Get("/300").
|
||||
Reply(http.StatusOK).
|
||||
SetHeader("Content-Type", "image/jpeg").
|
||||
Body(func() io.Reader {
|
||||
res, err := base64.StdEncoding.DecodeString(`
|
||||
H4sIAAAAAAACA/t/4/8DBgEvN083BkZGBgZGIGT4f5vBmYGVmYWFhZkVSLCysrKx83CwAwE/Nzcn
|
||||
jyC/kJAgv6CgsJiMuLCIlKigoISihJSsrLy8vLC4koqSnIqMnLwcyBBGoFZ2NnY+Dg4+ORFBETmS
|
||||
wf8DDIIcDAoMCsyMSgxMgozMgoz/jzDIA93JyggGDFDAyMTMAnQlBycXN1DBVgEGJkZmZiag+4Ee
|
||||
AMrWAuUZWARZhRQNHdmEAxPZlQpFjBonLuRQdtp4UDTo4gcV46SiJk4uMXEJSSlVNXUNTS0TUzNz
|
||||
C0srZxdXN3cPT6/gkNCw8IjIqOSU1LT0jMys4pLSsvKKyqrmlta29o7OrkmTp0ydNn3GzFmLFi9Z
|
||||
umz5ipWrNm3esnXb9h07dx06fOToseMnTp66dPnK1WvXb9y89fDR4ydPnz1/8fLVx0+fv3z99v3H
|
||||
z18gfzEyMDPCAFZ/CQL9xQSMFhZ2kL8YmcpBCgRZWBUN2YQcA9kTC4WVjBo5RJwmLtx4kFPZOOiD
|
||||
aFLRRS4xFZOHqh9BXgP7jDiPNZHlM7jHEP66xcDDzAiMPGZBBnuGH/fuKWs3sItefBlWa7FqV+h8
|
||||
P+01l9b8KnQQ27Labk545NLIL49WZwLl1m322vzyKEPFu6npl7temwAlQ3O1zi8XvQaSXMBtBdcZ
|
||||
itDYYP//JgDowAia0AIAAA==`)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
t.FailNow()
|
||||
return nil
|
||||
}
|
||||
|
||||
unpacker, err := gzip.NewReader(bytes.NewReader(res))
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
t.FailNow()
|
||||
return nil
|
||||
}
|
||||
|
||||
return unpacker
|
||||
}())
|
||||
|
||||
resp, err := http.Get("https://via.placeholder.com/300")
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
defer gock.Off()
|
||||
|
||||
gock.New(mgURL).
|
||||
Post("/api/bot/v1/files/upload").
|
||||
|
@ -811,7 +1047,7 @@ func TestMgClient_UploadFileByUrl(t *testing.T) {
|
|||
|
||||
t.Logf("File %+v is upload", uploadFileResponse.ID)
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func RandStringBytesMaskImprSrc(n int) string {
|
||||
|
@ -851,11 +1087,110 @@ func TestMgClient_DebugWithLogger(t *testing.T) {
|
|||
var buf bytes.Buffer
|
||||
logger := log.New(&buf, "Custom log prefix ", 0)
|
||||
|
||||
c := client()
|
||||
c.Debug = true
|
||||
c.WithLogger(logger)
|
||||
c := client(OptionDebug(), OptionLogger(logger))
|
||||
|
||||
c.writeLog("Test log string")
|
||||
|
||||
assert.Contains(t, buf.String(), "Custom log prefix Test log string")
|
||||
}
|
||||
|
||||
func TestMgClient_SuccessChatsByCustomerId(t *testing.T) {
|
||||
defer gock.Off()
|
||||
customerID := uint64(191140)
|
||||
gock.New(mgURL).
|
||||
Path("/api/bot/v1/chats").
|
||||
MatchParam("customer_id", fmt.Sprintf("%d", customerID)).
|
||||
MatchHeader("X-Bot-Token", mgToken).
|
||||
Reply(http.StatusOK).
|
||||
JSON(getJSONResponseChats())
|
||||
|
||||
apiClient := client()
|
||||
chatsRequest := ChatsRequest{
|
||||
CustomerID: customerID,
|
||||
}
|
||||
|
||||
resp, statusCode, err := apiClient.Chats(chatsRequest)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, statusCode)
|
||||
assert.Len(t, resp, 1)
|
||||
assert.Equal(t, uint64(9000), resp[0].ID)
|
||||
assert.Equal(t, uint64(8000), resp[0].Channel.ID)
|
||||
assert.Equal(t, customerID, resp[0].Customer.ID)
|
||||
assert.Equal(t, "Имя Фамилия", resp[0].Customer.Name)
|
||||
assert.Equal(t, "Имя", resp[0].Customer.FirstName)
|
||||
assert.Equal(t, "Фамилия", resp[0].Customer.LastName)
|
||||
}
|
||||
|
||||
func getJSONResponseChats() string {
|
||||
return `[
|
||||
{
|
||||
"id": 9000,
|
||||
"channel": {
|
||||
"id": 8000,
|
||||
"avatar": "",
|
||||
"transport_id": 555,
|
||||
"type": "transport",
|
||||
"settings": {
|
||||
"status": {
|
||||
"delivered": "send"
|
||||
},
|
||||
"text": {
|
||||
"creating": "both",
|
||||
"editing": "both",
|
||||
"quoting": "both",
|
||||
"deleting": "receive",
|
||||
"max_chars_count": 4096
|
||||
},
|
||||
"product": {
|
||||
"creating": "receive",
|
||||
"editing": "receive"
|
||||
},
|
||||
"order": {
|
||||
"creating": "receive",
|
||||
"editing": "receive"
|
||||
},
|
||||
"image": {
|
||||
"creating": "both",
|
||||
"editing": "both",
|
||||
"quoting": "both",
|
||||
"deleting": "receive",
|
||||
"max_items_count": 10
|
||||
},
|
||||
"file": {
|
||||
"creating": "both",
|
||||
"editing": "both",
|
||||
"quoting": "both",
|
||||
"deleting": "receive",
|
||||
"max_items_count": 1
|
||||
},
|
||||
"audio": {
|
||||
"creating": "both",
|
||||
"quoting": "both",
|
||||
"deleting": "receive",
|
||||
"max_items_count": 1
|
||||
},
|
||||
"suggestions": {
|
||||
"text": "both",
|
||||
"email": "both",
|
||||
"phone": "both"
|
||||
}
|
||||
},
|
||||
"name": "@test_bot123",
|
||||
"is_active": false
|
||||
},
|
||||
"customer": {
|
||||
"id": 191140,
|
||||
"external_id": "",
|
||||
"type": "customer",
|
||||
"avatar": "",
|
||||
"name": "Имя Фамилия",
|
||||
"username": "Имя",
|
||||
"first_name": "Имя",
|
||||
"last_name": "Фамилия"
|
||||
},
|
||||
"last_activity": "2022-10-28T13:17:38+03:00",
|
||||
"created_at": "2022-10-07T14:00:24.795382Z",
|
||||
"updated_at": "2022-10-28T12:19:04.834592Z"
|
||||
}
|
||||
]`
|
||||
}
|
||||
|
|
294
v1/types.go
294
v1/types.go
|
@ -43,6 +43,8 @@ const (
|
|||
WsEventSettingsUpdated string = "settings_updated"
|
||||
WsEventChatsDeleted string = "chats_deleted"
|
||||
|
||||
WsOptionIncludeMassCommunication WsOption = "include_mass_communication"
|
||||
|
||||
ChannelFeatureNone string = "none"
|
||||
ChannelFeatureReceive string = "receive"
|
||||
ChannelFeatureSend string = "send"
|
||||
|
@ -50,6 +52,7 @@ const (
|
|||
|
||||
BotRoleDistributor string = "distributor"
|
||||
BotRoleResponsible string = "responsible"
|
||||
BotRoleHidden string = "hidden"
|
||||
|
||||
MsgTypeText string = "text"
|
||||
MsgTypeSystem string = "system"
|
||||
|
@ -76,6 +79,23 @@ const (
|
|||
SuggestionTypeText = "text"
|
||||
SuggestionTypeEmail = "email"
|
||||
SuggestionTypePhone = "phone"
|
||||
|
||||
ColorLightRed = "light-red"
|
||||
ColorLightBlue = "light-blue"
|
||||
ColorLightGreen = "light-green"
|
||||
ColorLightOrange = "light-orange"
|
||||
ColorLightGray = "light-gray"
|
||||
ColorLightGrayishBlue = "light-grayish-blue"
|
||||
ColorRed = "red"
|
||||
ColorBlue = "blue"
|
||||
ColorGreen = "green"
|
||||
ColorOrange = "orange"
|
||||
ColorGray = "gray"
|
||||
ColorGrayishBlue = "grayish-blue"
|
||||
|
||||
WaitingLevelNone = "none"
|
||||
WaitingLevelWarning = "warning"
|
||||
WaitingLevelDanger = "danger"
|
||||
)
|
||||
|
||||
// MgClient type
|
||||
|
@ -96,7 +116,7 @@ type (
|
|||
Role string `url:"role,omitempty"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"int,omitempty"`
|
||||
Limit int `url:"limit,omitempty"`
|
||||
}
|
||||
|
||||
ChannelsRequest struct {
|
||||
|
@ -105,7 +125,7 @@ type (
|
|||
Active uint8 `url:"active,omitempty"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"int,omitempty"`
|
||||
Limit int `url:"limit,omitempty"`
|
||||
}
|
||||
|
||||
UsersRequest struct {
|
||||
|
@ -115,24 +135,30 @@ type (
|
|||
Active uint8 `url:"active,omitempty"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"int,omitempty"`
|
||||
Limit int `url:"limit,omitempty"`
|
||||
}
|
||||
|
||||
CustomersRequest struct {
|
||||
ID uint64 `url:"id,omitempty"`
|
||||
ExternalID string `url:"external_id,omitempty" json:"external_id"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"int,omitempty"`
|
||||
}
|
||||
|
||||
ChatsRequest struct {
|
||||
ID uint64 `url:"id,omitempty"`
|
||||
ChannelID uint64 `url:"channel_id,omitempty" json:"channel_id"`
|
||||
ChannelType string `url:"channel_type,omitempty" json:"channel_type"`
|
||||
ExternalID string `url:"external_id,omitempty" json:"external_id"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"int,omitempty"`
|
||||
Limit int `url:"limit,omitempty"`
|
||||
}
|
||||
|
||||
ChatsRequest struct {
|
||||
ID uint64 `url:"id,omitempty"`
|
||||
ChannelID uint64 `url:"channel_id,omitempty" json:"channel_id"`
|
||||
ChannelType string `url:"channel_type,omitempty" json:"channel_type"`
|
||||
CustomerID uint64 `url:"customer_id,omitempty" json:"customer_id"`
|
||||
CustomerExternalID string `url:"customer_external_id,omitempty" json:"customer_external_id"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"limit,omitempty"`
|
||||
SinceID int `url:"since_id,omitempty"`
|
||||
IncludeMassCommunication uint8 `url:"include_mass_communication,omitempty"`
|
||||
}
|
||||
|
||||
MembersRequest struct {
|
||||
|
@ -141,19 +167,21 @@ type (
|
|||
State string `url:"state,omitempty"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"int,omitempty"`
|
||||
Limit int `url:"limit,omitempty"`
|
||||
}
|
||||
|
||||
DialogsRequest struct {
|
||||
ID uint64 `url:"id,omitempty"`
|
||||
ChatID string `url:"chat_id,omitempty" json:"chat_id"`
|
||||
UserID string `url:"user_id,omitempty" json:"user_id"`
|
||||
BotID string `url:"bot_id,omitempty" json:"bot_id"`
|
||||
Assign uint8 `url:"assign,omitempty"`
|
||||
Active uint8 `url:"active,omitempty"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"int,omitempty"`
|
||||
ID uint64 `url:"id,omitempty"`
|
||||
ChatID string `url:"chat_id,omitempty" json:"chat_id"`
|
||||
UserID string `url:"user_id,omitempty" json:"user_id"`
|
||||
BotID string `url:"bot_id,omitempty" json:"bot_id"`
|
||||
Assign uint8 `url:"assign,omitempty"`
|
||||
Active uint8 `url:"active,omitempty"`
|
||||
Since string `url:"since,omitempty"`
|
||||
SinceID int `url:"since_id,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"limit,omitempty"`
|
||||
IncludeMassCommunication uint8 `url:"include_mass_communication,omitempty"`
|
||||
}
|
||||
|
||||
DialogAssignRequest struct {
|
||||
|
@ -162,20 +190,40 @@ type (
|
|||
BotID uint64 `url:"bot_id,omitempty" json:"bot_id"`
|
||||
}
|
||||
|
||||
DialogTagsAddRequest struct {
|
||||
DialogID uint64 `url:"dialog_id,omitempty"`
|
||||
Tags []TagsAdd `json:"tags"`
|
||||
}
|
||||
|
||||
TagsAdd struct {
|
||||
Name string `json:"name"`
|
||||
ColorCode *string `json:"color_code"`
|
||||
}
|
||||
|
||||
DialogTagsDeleteRequest struct {
|
||||
DialogID uint64 `url:"dialog_id,omitempty"`
|
||||
Tags []TagsDelete `json:"tags"`
|
||||
}
|
||||
|
||||
TagsDelete struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
MessagesRequest struct {
|
||||
ID []int `url:"id,omitempty"`
|
||||
ChatID uint64 `url:"chat_id,omitempty" json:"chat_id"`
|
||||
DialogID uint64 `url:"dialog_id,omitempty" json:"dialog_id"`
|
||||
UserID uint64 `url:"user_id,omitempty" json:"user_id"`
|
||||
CustomerID uint64 `url:"customer_id,omitempty" json:"customer_id"`
|
||||
BotID uint64 `url:"bot_id,omitempty" json:"bot_id"`
|
||||
ChannelID uint64 `url:"channel_id,omitempty" json:"channel_id"`
|
||||
ChannelType string `url:"channel_type,omitempty" json:"channel_type"`
|
||||
Scope string `url:"scope,omitempty"`
|
||||
Type string `url:"type,omitempty"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"int,omitempty"`
|
||||
ID []int `url:"id,omitempty"`
|
||||
ChatID uint64 `url:"chat_id,omitempty" json:"chat_id"`
|
||||
DialogID uint64 `url:"dialog_id,omitempty" json:"dialog_id"`
|
||||
UserID uint64 `url:"user_id,omitempty" json:"user_id"`
|
||||
CustomerID uint64 `url:"customer_id,omitempty" json:"customer_id"`
|
||||
BotID uint64 `url:"bot_id,omitempty" json:"bot_id"`
|
||||
ChannelID uint64 `url:"channel_id,omitempty" json:"channel_id"`
|
||||
ChannelType string `url:"channel_type,omitempty" json:"channel_type"`
|
||||
Scope string `url:"scope,omitempty"`
|
||||
Type string `url:"type,omitempty"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"limit,omitempty"`
|
||||
IncludeMassCommunication uint8 `url:"include_mass_communication,omitempty"`
|
||||
}
|
||||
|
||||
MessageSendRequest struct {
|
||||
|
@ -215,7 +263,7 @@ type (
|
|||
Name string `url:"name,omitempty"`
|
||||
Since string `url:"since,omitempty"`
|
||||
Until string `url:"until,omitempty"`
|
||||
Limit int `url:"int,omitempty"`
|
||||
Limit int `url:"limit,omitempty"`
|
||||
}
|
||||
|
||||
CommandEditRequest struct {
|
||||
|
@ -226,6 +274,13 @@ type (
|
|||
UploadFileByUrlRequest struct {
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
UpdateFileMetadataRequest struct {
|
||||
ID string `json:"-"`
|
||||
Transcription string `json:"transcription,omitempty"`
|
||||
// Current status of transcription process. Available values: "in_progress", "ready", "error"
|
||||
TranscriptionStatus string `json:"transcription_status,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
// Response types
|
||||
|
@ -256,17 +311,20 @@ type (
|
|||
}
|
||||
|
||||
UsersResponseItem struct {
|
||||
ID uint64 `json:"id"`
|
||||
ExternalID string `json:"external_id,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
FirstName string `json:"first_name,omitempty"`
|
||||
LastName string `json:"last_name,omitempty"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at,omitempty"`
|
||||
RevokedAt string `json:"revoked_at,omitempty"`
|
||||
IsOnline bool `json:"is_online"`
|
||||
IsActive bool `json:"is_active"`
|
||||
Avatar string `json:"avatar_url,omitempty"`
|
||||
ID uint64 `json:"id"`
|
||||
ExternalID string `json:"external_id,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
FirstName string `json:"first_name,omitempty"`
|
||||
LastName string `json:"last_name,omitempty"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at,omitempty"`
|
||||
RevokedAt string `json:"revoked_at,omitempty"`
|
||||
Available bool `json:"available"`
|
||||
IsOnline bool `json:"is_online"`
|
||||
Connected bool `json:"connected"`
|
||||
IsActive bool `json:"is_active"`
|
||||
IsTechnicalAccount bool `json:"is_technical_account"`
|
||||
Avatar string `json:"avatar_url,omitempty"`
|
||||
}
|
||||
|
||||
CustomersResponseItem struct {
|
||||
|
@ -285,19 +343,22 @@ type (
|
|||
Language string `json:"language,omitempty"`
|
||||
Phone string `json:"phone,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
Utm *Utm `json:"utm,omitempty"`
|
||||
}
|
||||
|
||||
ChatResponseItem struct {
|
||||
ID uint64 `json:"id"`
|
||||
Avatar string `json:"avatar"`
|
||||
Name string `json:"name"`
|
||||
Channel Channel `json:"channel,omitempty"`
|
||||
Customer UserRef `json:"customer"`
|
||||
AuthorID uint64 `json:"author_id"`
|
||||
LastMessage Message `json:"last_message"`
|
||||
LastActivity string `json:"last_activity"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
ID uint64 `json:"id"`
|
||||
Avatar string `json:"avatar"`
|
||||
Name string `json:"name"`
|
||||
Channel Channel `json:"channel,omitempty"`
|
||||
Customer UserRef `json:"customer"`
|
||||
AuthorID uint64 `json:"author_id"`
|
||||
LastMessage Message `json:"last_message"`
|
||||
LastUserMessage MessageID `json:"last_user_message"`
|
||||
LastActivity string `json:"last_activity"`
|
||||
LastDialog Dialog `json:"last_dialog"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
}
|
||||
|
||||
MemberResponseItem struct {
|
||||
|
@ -322,6 +383,7 @@ type (
|
|||
IsAssigned bool `json:"is_assigned"`
|
||||
Responsible Responsible `json:"responsible,omitempty"`
|
||||
IsActive bool `json:"is_active"`
|
||||
Utm *Utm `json:"utm,omitempty"`
|
||||
}
|
||||
|
||||
DialogAssignResponse struct {
|
||||
|
@ -389,6 +451,11 @@ type (
|
|||
}
|
||||
)
|
||||
|
||||
// WS options.
|
||||
type (
|
||||
WsOption string
|
||||
)
|
||||
|
||||
// Single entity types
|
||||
type (
|
||||
Message struct {
|
||||
|
@ -404,11 +471,16 @@ type (
|
|||
From *UserRef `json:"from"`
|
||||
Product *MessageProduct `json:"product,omitempty"`
|
||||
Order *MessageOrder `json:"order,omitempty"`
|
||||
Dialog *MessageDialog `json:"dialog,omitempty"`
|
||||
*TextMessage
|
||||
*SystemMessage
|
||||
*AttachmentList
|
||||
}
|
||||
|
||||
MessageID struct {
|
||||
ID uint64 `json:"id"`
|
||||
}
|
||||
|
||||
TextMessage struct {
|
||||
Content string `json:"content"`
|
||||
Quote *QuoteMessage `json:"quote"`
|
||||
|
@ -416,16 +488,22 @@ type (
|
|||
}
|
||||
|
||||
SystemMessage struct {
|
||||
Action string `json:"action"`
|
||||
Action string `json:"action"`
|
||||
// Deprecated: Use Message.Dialog.ID instead.
|
||||
Dialog *SystemMessageDialog `json:"dialog,omitempty"`
|
||||
User *UserRef `json:"user,omitempty"`
|
||||
Responsible *UserRef `json:"responsible,omitempty"`
|
||||
}
|
||||
|
||||
// Deprecated: Use MessageDialog instead.
|
||||
SystemMessageDialog struct {
|
||||
ID uint64 `json:"id"`
|
||||
}
|
||||
|
||||
MessageDialog struct {
|
||||
ID uint64 `json:"id"`
|
||||
}
|
||||
|
||||
QuoteMessage struct {
|
||||
ID uint64 `json:"id"`
|
||||
Content string `json:"content"`
|
||||
|
@ -439,13 +517,21 @@ type (
|
|||
}
|
||||
|
||||
Attachment struct {
|
||||
ID string `json:"id"`
|
||||
Mime string `json:"type"`
|
||||
Caption string `json:"caption"`
|
||||
Size uint64 `json:"size"`
|
||||
PreviewURL *string `json:"preview_url,omitempty"`
|
||||
Height *uint64 `json:"height,omitempty"`
|
||||
Width *uint64 `json:"width,omitempty"`
|
||||
File
|
||||
|
||||
Caption string `json:"caption"`
|
||||
}
|
||||
|
||||
File struct {
|
||||
PreviewURL *string `json:"preview_url,omitempty"`
|
||||
Height *uint64 `json:"height,omitempty"`
|
||||
Width *uint64 `json:"width,omitempty"`
|
||||
Transcription string `json:"transcription,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Mime string `json:"type"`
|
||||
Type string `json:"kind"`
|
||||
Duration int `json:"duration,omitempty"`
|
||||
Size uint64 `json:"size"`
|
||||
}
|
||||
|
||||
MessageProduct struct {
|
||||
|
@ -511,17 +597,19 @@ type (
|
|||
}
|
||||
|
||||
UserRef struct {
|
||||
ID uint64 `json:"id"`
|
||||
ExternalID uint64 `json:"external_id"`
|
||||
Avatar string `json:"avatar"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
FirstName string `json:"first_name,omitempty"`
|
||||
LastName string `json:"last_name,omitempty"`
|
||||
Phone string `json:"phone,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
Available bool `json:"available"`
|
||||
ID uint64 `json:"id"`
|
||||
ExternalID string `json:"external_id"`
|
||||
Avatar string `json:"avatar"`
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
FirstName string `json:"first_name,omitempty"`
|
||||
LastName string `json:"last_name,omitempty"`
|
||||
Phone string `json:"phone,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
Available bool `json:"available"`
|
||||
IsTechnicalAccount bool `json:"is_technical_account"`
|
||||
IsSystem bool `json:"is_system"`
|
||||
}
|
||||
|
||||
Channel struct {
|
||||
|
@ -553,15 +641,22 @@ type (
|
|||
}
|
||||
|
||||
Chat struct {
|
||||
ID uint64 `json:"id"`
|
||||
Avatar string `json:"avatar"`
|
||||
Name string `json:"name"`
|
||||
Channel *Channel `json:"channel,omitempty"`
|
||||
Members []Member `json:"members"`
|
||||
Customer *UserRef `json:"customer"`
|
||||
AuthorID uint64 `json:"author_id"`
|
||||
LastMessage *Message `json:"last_message"`
|
||||
LastActivity string `json:"last_activity"`
|
||||
ID uint64 `json:"id"`
|
||||
Avatar string `json:"avatar"`
|
||||
Name string `json:"name"`
|
||||
Channel *Channel `json:"channel,omitempty"`
|
||||
Members []Member `json:"members"`
|
||||
Customer *UserRef `json:"customer"`
|
||||
AuthorID uint64 `json:"author_id"`
|
||||
LastMessage *Message `json:"last_message"`
|
||||
LastUserMessage *MessageID `json:"last_user_message"`
|
||||
LastActivity string `json:"last_activity"`
|
||||
}
|
||||
|
||||
WaitingChat struct {
|
||||
Chat
|
||||
|
||||
WaitingLevel string `json:"waiting_level"`
|
||||
}
|
||||
|
||||
Member struct {
|
||||
|
@ -578,6 +673,7 @@ type (
|
|||
Responsible *Responsible `json:"responsible"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
ClosedAt *string `json:"closed_at"`
|
||||
Utm *Utm `json:"utm,omitempty"`
|
||||
}
|
||||
|
||||
FileMeta struct {
|
||||
|
@ -589,6 +685,14 @@ type (
|
|||
ID string `json:"id"`
|
||||
Caption string `json:"caption"`
|
||||
}
|
||||
|
||||
Utm struct {
|
||||
Source string `json:"source"`
|
||||
Medium string `json:"medium"`
|
||||
Campaign string `json:"campaign"`
|
||||
Term string `json:"term"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
)
|
||||
|
||||
// Channel settings
|
||||
|
@ -674,10 +778,12 @@ type (
|
|||
Message *Message `json:"message"`
|
||||
}
|
||||
|
||||
// Deprecated: Use WsEventWaitingChatCreatedData instead.
|
||||
WsEventChatCreatedData struct {
|
||||
Chat *Chat `json:"chat"`
|
||||
}
|
||||
|
||||
// Deprecated: Use WsEventWaitingChatUpdatedData instead.
|
||||
WsEventChatUpdatedData struct {
|
||||
Chat *Chat `json:"chat"`
|
||||
}
|
||||
|
@ -702,6 +808,7 @@ type (
|
|||
|
||||
WsEventUserUpdatedData struct {
|
||||
*UserRef
|
||||
IsActive bool `json:"is_active"`
|
||||
}
|
||||
|
||||
WsEventCustomerUpdatedData struct {
|
||||
|
@ -723,11 +830,24 @@ type (
|
|||
}
|
||||
|
||||
WsEventUserOnlineUpdatedData struct {
|
||||
User *UserRef `json:"user"`
|
||||
Online bool `json:"online"`
|
||||
User *UserRef `json:"user"`
|
||||
Online bool `json:"online"`
|
||||
Connected bool `json:"connected"`
|
||||
}
|
||||
|
||||
WsEventChatsDeletedData struct {
|
||||
ChatIds []int64 `json:"chat_ids"`
|
||||
}
|
||||
|
||||
WsEventChannelUpdatedData struct {
|
||||
Channel *ChannelResponseItem `json:"channel"`
|
||||
}
|
||||
|
||||
WsEventWaitingChatCreatedData struct {
|
||||
Chat *WaitingChat `json:"chat"`
|
||||
}
|
||||
|
||||
WsEventWaitingChatUpdatedData struct {
|
||||
Chat *WaitingChat `json:"chat"`
|
||||
}
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue