Compare commits

...

20 commits

Author SHA1 Message Date
9e5fb7afec
Merge pull request #85 from vragovR/add-dialog-utm
Add `Utm` field to the `DialogResponseItem` struct
2025-04-10 11:42:28 +03:00
Vragov Roman
3b56a36b3b Add Utm field to the DialogResponseItem struct 2025-04-07 13:25:47 +03:00
1ba7024ccc
Merge pull request #83 from vragovR/add-message-utm
Add `Utm` field to the `Dialog` struct
2025-03-06 15:20:40 +03:00
Vragov Roman
fe5c8e9676 Add Utm field to the Dialog struct 2025-03-06 15:05:48 +03:00
e2205fb4d9
fix UploadFile dependency on external URL 2025-03-06 14:59:25 +03:00
223e63b268 update linter (2) 2025-03-06 14:58:13 +03:00
7cec2bb237 update linter 2025-03-06 14:46:36 +03:00
c338d2e19e ci update 2025-03-06 14:42:46 +03:00
a101bd502a fix UploadFile dependency on external URL 2025-03-06 14:40:01 +03:00
021568afd8
Merge pull request #79 from ilyavlasoff/add_transcription_status_field
Added transcription status field
2024-11-15 14:39:28 +03:00
f7e352a622
Merge pull request #80 from opheugene/add_from_is_system
Added IsSystem flag to UserRef struct
2024-11-15 14:39:09 +03:00
5466d2d1ad
Merge pull request #82 from ilyavlasoff/added_message_dialog_field
Added Message.Dialog field for all types of messages
2024-11-15 14:38:50 +03:00
0e970386ce
Merge pull request #81 from kifril-ltd/bot-role-hidden
Add new bot role `hidden`
2024-11-15 14:38:21 +03:00
Vlasov
8b0193186b Added Message.Dialog field for all types of messages 2024-11-15 12:02:57 +03:00
Kirill Sukhorukov
c7b7f73c4f Add new bot role hidden 2024-11-08 13:33:19 +03:00
Opheugene
22d56ef2dc -mod 2024-11-06 20:06:49 +01:00
Opheugene
f6affa2063 mod 2024-11-06 19:59:49 +01:00
Opheugene
d5aa1a0794 Added Last Dialog to Chat struct 2024-11-06 19:32:35 +01:00
Opheugene
bc9702741e Added IsSystem flag to UserRef struct 2024-11-06 19:05:27 +01:00
Vlasov
46a262a5dc Added transcription status field 2024-10-21 12:27:34 +03:00
5 changed files with 189 additions and 85 deletions

View file

@ -19,33 +19,33 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out code into the Go module directory - name: Check out code into the Go module directory
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Set up latest Go 1.x version - name: Set up Go 1.24
uses: actions/setup-go@v2 uses: actions/setup-go@v5
with: with:
go-version: '1.17' go-version: '1.24'
- name: Get dependencies - name: Get dependencies
run: | run: |
go mod tidy go mod tidy
cp .env.dist .env cp .env.dist .env
- name: Lint code with golangci-lint - name: Lint code with golangci-lint
uses: golangci/golangci-lint-action@v3 uses: golangci/golangci-lint-action@v6
with: with:
version: v1.50.1 version: v1.62.2
only-new-issues: true only-new-issues: true
tests: tests:
name: Tests name: Tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: 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: steps:
- name: Set up Go ${{ matrix.go-version }} - name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v2 uses: actions/setup-go@v5
with: with:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go-version }}
- name: Check out code into the Go module directory - name: Check out code into the Go module directory
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: Get dependencies - name: Get dependencies
run: | run: |
go mod tidy go mod tidy

View file

@ -1,31 +1,15 @@
run: run:
skip-dirs-use-default: true
allow-parallel-runners: true allow-parallel-runners: true
modules-download-mode: readonly
output: output:
format: colored-line-number formats:
- format: colored-line-number
sort-results: true sort-results: true
# Linters below do not support go1.18 yet because of generics.
# See https://github.com/golangci/golangci-lint/issues/2649
# - bodyclose
# - sqlclosecheck
linters: linters:
disable-all: true disable-all: true
enable: enable:
- paralleltest
- tparallel
- asciicheck
- asasalint
- varnamelen
- reassign
- nilnil
- nilerr
- nakedret
- goprintffuncname
- typecheck
- errchkjson
- errcheck - errcheck
- gosimple - gosimple
- govet - govet
@ -33,11 +17,12 @@ linters:
- staticcheck - staticcheck
- unused - unused
- unparam - unparam
- bodyclose
- dogsled - dogsled
- dupl - dupl
- errorlint - errorlint
- exhaustive - exhaustive
- exportloopref - copyloopvar
- funlen - funlen
- gocognit - gocognit
- goconst - goconst
@ -46,6 +31,7 @@ linters:
- godot - godot
- goimports - goimports
- revive - revive
- mnd
- gosec - gosec
- lll - lll
- makezero - makezero
@ -53,22 +39,21 @@ linters:
- nestif - nestif
- prealloc - prealloc
- predeclared - predeclared
- exportloopref - sqlclosecheck
- unconvert - unconvert
- whitespace - whitespace
- unused
- testifylint
linters-settings: linters-settings:
govet: govet:
check-shadowing: false
disable-all: true disable-all: true
enable: enable:
- assign - assign
- atomic - atomic
- atomicalign
- bools - bools
- buildtag - buildtag
- copylocks - copylocks
- fieldalignment
- httpresponse - httpresponse
- loopclosure - loopclosure
- lostcancel - lostcancel
@ -128,8 +113,6 @@ linters-settings:
- log.Printf - log.Printf
- log.Println - log.Println
- runtime/trace.Logf - runtime/trace.Logf
unused:
check-exported: false
unparam: unparam:
check-exported: false check-exported: false
dogsled: dogsled:
@ -138,8 +121,8 @@ linters-settings:
threshold: 200 threshold: 200
errorlint: errorlint:
errorf: true errorf: true
asserts: false asserts: true
comparison: false comparison: true
exhaustive: exhaustive:
check-generated: false check-generated: false
default-signifies-exhaustive: false default-signifies-exhaustive: false
@ -161,25 +144,23 @@ linters-settings:
whitespace: whitespace:
multi-if: false multi-if: false
multi-func: false multi-func: false
varnamelen:
max-distance: 10
ignore-map-index-ok: true
ignore-type-assert-ok: true
ignore-chan-recv-ok: true
ignore-decls:
- t *testing.T
- e error
- i int
issues: issues:
exclude-rules: exclude-rules:
- path: _test\.go - path: _test\.go
linters: linters:
- dupl
- mnd
- lll - lll
- bodyclose
- errcheck - errcheck
- sqlclosecheck
- misspell - misspell
- ineffassign - ineffassign
- whitespace - whitespace
- makezero - makezero
- maligned
- ifshort
- errcheck - errcheck
- funlen - funlen
- goconst - goconst
@ -187,8 +168,6 @@ issues:
- gocyclo - gocyclo
- godot - godot
- unused - unused
- errchkjson
- varnamelen
exclude-use-default: true exclude-use-default: true
exclude-case-sensitive: false exclude-case-sensitive: false
max-issues-per-linter: 0 max-issues-per-linter: 0
@ -197,7 +176,4 @@ issues:
severity: severity:
default-severity: error default-severity: error
case-sensitive: false case-sensitive: false
service:
golangci-lint-version: 1.50.x

View file

@ -16,21 +16,21 @@ import (
type Option func(*MgClient) type Option func(*MgClient)
// OptionHTTPClient set custom http.Client for MgClient // OptionHTTPClient set custom http.Client for MgClient.
func OptionHTTPClient(client *http.Client) func(*MgClient) { func OptionHTTPClient(client *http.Client) func(*MgClient) {
return func(c *MgClient) { return func(c *MgClient) {
c.httpClient = client c.httpClient = client
} }
} }
// OptionLogger sets the provided logger instance into the MgClient // OptionLogger sets the provided logger instance into the MgClient.
func OptionLogger(logger BasicLogger) func(*MgClient) { func OptionLogger(logger BasicLogger) func(*MgClient) {
return func(c *MgClient) { return func(c *MgClient) {
c.logger = logger c.logger = logger
} }
} }
// OptionDebug enables debug mode for MgClient // OptionDebug enables debug mode for MgClient.
func OptionDebug() func(*MgClient) { func OptionDebug() func(*MgClient) {
return func(c *MgClient) { return func(c *MgClient) {
c.Debug = true c.Debug = true
@ -53,7 +53,7 @@ func New(url string, token string, opts ...Option) *MgClient {
} }
// WithLogger sets the provided logger instance into the Client. // WithLogger sets the provided logger instance into the Client.
// Deprecated: Use functional option OptionLogger instead // Deprecated: Use functional option OptionLogger instead.
func (c *MgClient) WithLogger(logger BasicLogger) *MgClient { func (c *MgClient) WithLogger(logger BasicLogger) *MgClient {
c.logger = logger c.logger = logger
return c return c

View file

@ -2,8 +2,12 @@ package v1
import ( import (
"bytes" "bytes"
"compress/gzip"
"encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/stretchr/testify/require"
"io"
"log" "log"
"math/rand" "math/rand"
"net/http" "net/http"
@ -69,7 +73,7 @@ func TestMgClient_Bots(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
assert.NotEmpty(t, data) assert.NotEmpty(t, data)
for _, bot := range data { for _, bot := range data {
@ -148,7 +152,7 @@ func TestMgClient_Channels(t *testing.T) {
]`) ]`)
channels, status, err := c.Channels(ChannelsRequest{Active: 1}) channels, status, err := c.Channels(ChannelsRequest{Active: 1})
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, 200, status) assert.Equal(t, 200, status)
assert.Len(t, channels, 1) assert.Len(t, channels, 1)
@ -221,7 +225,7 @@ func TestMgClient_Users(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
assert.NotEmpty(t, data) assert.NotEmpty(t, data)
for _, user := range data { for _, user := range data {
@ -231,9 +235,9 @@ func TestMgClient_Users(t *testing.T) {
assert.Equal(t, "Test", user.FirstName) assert.Equal(t, "Test", user.FirstName)
assert.Equal(t, "Test", user.LastName) assert.Equal(t, "Test", user.LastName)
assert.Equal(t, "2018-01-01T00:00:00.000000Z", user.CreatedAt) assert.Equal(t, "2018-01-01T00:00:00.000000Z", user.CreatedAt)
assert.Equal(t, true, user.IsActive) assert.True(t, user.IsActive)
assert.Equal(t, true, user.IsOnline) assert.True(t, user.IsOnline)
assert.Equal(t, true, user.IsTechnicalAccount) assert.True(t, user.IsTechnicalAccount)
} }
} }
@ -288,7 +292,7 @@ func TestMgClient_Customers(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
assert.NotEmpty(t, data) assert.NotEmpty(t, data)
for _, customer := range data { for _, customer := range data {
@ -324,7 +328,7 @@ func TestMgClient_Chats(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
assert.NotEmpty(t, data) assert.NotEmpty(t, data)
for _, chat := range data { for _, chat := range data {
@ -349,7 +353,7 @@ func TestMgClient_Members(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
for _, member := range data { for _, member := range data {
assert.NotEmpty(t, member.ChatID) assert.NotEmpty(t, member.ChatID)
@ -373,7 +377,7 @@ func TestMgClient_Dialogs(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
assert.NotEmpty(t, data) assert.NotEmpty(t, data)
for _, dialog := range data { for _, dialog := range data {
@ -415,7 +419,7 @@ func TestMgClient_DialogUnassign(t *testing.T) {
resp, status, err := c.DialogUnassign(777) resp, status, err := c.DialogUnassign(777)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, http.StatusOK, status) assert.Equal(t, http.StatusOK, status)
assert.Equal(t, int64(111), resp.PreviousResponsible.ID) assert.Equal(t, int64(111), resp.PreviousResponsible.ID)
@ -500,7 +504,7 @@ func TestMgClient_DialogsTagsAdd(t *testing.T) {
status, err := c.DialogsTagsAdd(req) status, err := c.DialogsTagsAdd(req)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, http.StatusOK, status) assert.Equal(t, http.StatusOK, status)
} }
@ -526,7 +530,7 @@ func TestMgClient_DialogsTagsDelete(t *testing.T) {
status, err := c.DialogTagsDelete(req) status, err := c.DialogTagsDelete(req)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, http.StatusOK, status) assert.Equal(t, http.StatusOK, status)
} }
@ -547,7 +551,7 @@ func TestMgClient_Messages(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
assert.NotEmpty(t, data) assert.NotEmpty(t, data)
for _, message := range data { for _, message := range data {
@ -555,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) { func TestMgClient_MessageSendText(t *testing.T) {
c := client() c := client()
@ -579,7 +660,7 @@ func TestMgClient_MessageSendText(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
assert.NotEmpty(t, data.MessageID) assert.NotEmpty(t, data.MessageID)
} }
@ -617,7 +698,7 @@ func TestMgClient_MessageSendTextWithSuggestions(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
assert.NotEmpty(t, data.MessageID) assert.NotEmpty(t, data.MessageID)
} }
@ -658,7 +739,7 @@ func TestMgClient_MessageSendProduct(t *testing.T) {
t.Errorf("%v", err) t.Errorf("%v", err)
} }
assert.NoError(t, err) require.NoError(t, err)
t.Logf("%v", msg) t.Logf("%v", msg)
} }
@ -718,7 +799,7 @@ func TestMgClient_MessageSendOrder(t *testing.T) {
t.Errorf("%v", err) t.Errorf("%v", err)
} }
assert.NoError(t, err) require.NoError(t, err)
t.Logf("%v", msg) t.Logf("%v", msg)
} }
@ -787,7 +868,7 @@ func TestMgClient_Info(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
} }
func TestMgClient_Commands(t *testing.T) { func TestMgClient_Commands(t *testing.T) {
@ -807,7 +888,7 @@ func TestMgClient_Commands(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
assert.NotEmpty(t, data) assert.NotEmpty(t, data)
for _, command := range data { for _, command := range data {
@ -835,7 +916,7 @@ func TestMgClient_CommandEditDelete(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
assert.NotEmpty(t, n.ID) assert.NotEmpty(t, n.ID)
gock.New(mgURL). gock.New(mgURL).
@ -848,7 +929,7 @@ func TestMgClient_CommandEditDelete(t *testing.T) {
t.Errorf("%d %v", status, err) t.Errorf("%d %v", status, err)
} }
assert.NoError(t, err) require.NoError(t, err)
t.Logf("%v", d) t.Logf("%v", d)
} }
@ -879,7 +960,7 @@ func TestMgClient_WsMeta(t *testing.T) {
t.Errorf("%v", err) 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 resToken := c.Token
assert.Equal(t, resURL, url) assert.Equal(t, resURL, url)
@ -889,13 +970,46 @@ func TestMgClient_WsMeta(t *testing.T) {
func TestMgClient_UploadFile(t *testing.T) { func TestMgClient_UploadFile(t *testing.T) {
c := client() 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") resp, err := http.Get("https://via.placeholder.com/300")
if err != nil { if err != nil {
t.Errorf("%v", err) t.Errorf("%v", err)
t.FailNow()
} }
defer resp.Body.Close() defer resp.Body.Close()
defer gock.Off()
gock.New(mgURL). gock.New(mgURL).
Post("/api/bot/v1/files/upload"). Post("/api/bot/v1/files/upload").
@ -933,7 +1047,7 @@ func TestMgClient_UploadFileByUrl(t *testing.T) {
t.Logf("File %+v is upload", uploadFileResponse.ID) t.Logf("File %+v is upload", uploadFileResponse.ID)
assert.NoError(t, err) require.NoError(t, err)
} }
func RandStringBytesMaskImprSrc(n int) string { func RandStringBytesMaskImprSrc(n int) string {
@ -996,9 +1110,9 @@ func TestMgClient_SuccessChatsByCustomerId(t *testing.T) {
} }
resp, statusCode, err := apiClient.Chats(chatsRequest) resp, statusCode, err := apiClient.Chats(chatsRequest)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, http.StatusOK, statusCode) assert.Equal(t, http.StatusOK, statusCode)
assert.Equal(t, 1, len(resp)) assert.Len(t, resp, 1)
assert.Equal(t, uint64(9000), resp[0].ID) assert.Equal(t, uint64(9000), resp[0].ID)
assert.Equal(t, uint64(8000), resp[0].Channel.ID) assert.Equal(t, uint64(8000), resp[0].Channel.ID)
assert.Equal(t, customerID, resp[0].Customer.ID) assert.Equal(t, customerID, resp[0].Customer.ID)

View file

@ -52,6 +52,7 @@ const (
BotRoleDistributor string = "distributor" BotRoleDistributor string = "distributor"
BotRoleResponsible string = "responsible" BotRoleResponsible string = "responsible"
BotRoleHidden string = "hidden"
MsgTypeText string = "text" MsgTypeText string = "text"
MsgTypeSystem string = "system" MsgTypeSystem string = "system"
@ -277,6 +278,8 @@ type (
UpdateFileMetadataRequest struct { UpdateFileMetadataRequest struct {
ID string `json:"-"` ID string `json:"-"`
Transcription string `json:"transcription,omitempty"` Transcription string `json:"transcription,omitempty"`
// Current status of transcription process. Available values: "in_progress", "ready", "error"
TranscriptionStatus string `json:"transcription_status,omitempty"`
} }
) )
@ -353,6 +356,7 @@ type (
LastMessage Message `json:"last_message"` LastMessage Message `json:"last_message"`
LastUserMessage MessageID `json:"last_user_message"` LastUserMessage MessageID `json:"last_user_message"`
LastActivity string `json:"last_activity"` LastActivity string `json:"last_activity"`
LastDialog Dialog `json:"last_dialog"`
CreatedAt string `json:"created_at"` CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"` UpdatedAt string `json:"updated_at"`
} }
@ -379,6 +383,7 @@ type (
IsAssigned bool `json:"is_assigned"` IsAssigned bool `json:"is_assigned"`
Responsible Responsible `json:"responsible,omitempty"` Responsible Responsible `json:"responsible,omitempty"`
IsActive bool `json:"is_active"` IsActive bool `json:"is_active"`
Utm *Utm `json:"utm,omitempty"`
} }
DialogAssignResponse struct { DialogAssignResponse struct {
@ -446,7 +451,7 @@ type (
} }
) )
// WS options // WS options.
type ( type (
WsOption string WsOption string
) )
@ -466,6 +471,7 @@ type (
From *UserRef `json:"from"` From *UserRef `json:"from"`
Product *MessageProduct `json:"product,omitempty"` Product *MessageProduct `json:"product,omitempty"`
Order *MessageOrder `json:"order,omitempty"` Order *MessageOrder `json:"order,omitempty"`
Dialog *MessageDialog `json:"dialog,omitempty"`
*TextMessage *TextMessage
*SystemMessage *SystemMessage
*AttachmentList *AttachmentList
@ -482,16 +488,22 @@ type (
} }
SystemMessage struct { SystemMessage struct {
Action string `json:"action"` Action string `json:"action"`
// Deprecated: Use Message.Dialog.ID instead.
Dialog *SystemMessageDialog `json:"dialog,omitempty"` Dialog *SystemMessageDialog `json:"dialog,omitempty"`
User *UserRef `json:"user,omitempty"` User *UserRef `json:"user,omitempty"`
Responsible *UserRef `json:"responsible,omitempty"` Responsible *UserRef `json:"responsible,omitempty"`
} }
// Deprecated: Use MessageDialog instead.
SystemMessageDialog struct { SystemMessageDialog struct {
ID uint64 `json:"id"` ID uint64 `json:"id"`
} }
MessageDialog struct {
ID uint64 `json:"id"`
}
QuoteMessage struct { QuoteMessage struct {
ID uint64 `json:"id"` ID uint64 `json:"id"`
Content string `json:"content"` Content string `json:"content"`
@ -597,6 +609,7 @@ type (
IsAdmin bool `json:"is_admin"` IsAdmin bool `json:"is_admin"`
Available bool `json:"available"` Available bool `json:"available"`
IsTechnicalAccount bool `json:"is_technical_account"` IsTechnicalAccount bool `json:"is_technical_account"`
IsSystem bool `json:"is_system"`
} }
Channel struct { Channel struct {
@ -660,6 +673,7 @@ type (
Responsible *Responsible `json:"responsible"` Responsible *Responsible `json:"responsible"`
CreatedAt string `json:"created_at"` CreatedAt string `json:"created_at"`
ClosedAt *string `json:"closed_at"` ClosedAt *string `json:"closed_at"`
Utm *Utm `json:"utm,omitempty"`
} }
FileMeta struct { FileMeta struct {