initial client structure

This commit is contained in:
Alex Lushpai 2018-08-03 18:11:37 +03:00
parent 3ccbbb8bd7
commit 663c1f999c
6 changed files with 816 additions and 0 deletions

29
.gitignore vendored Normal file
View File

@ -0,0 +1,29 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
# IDE's files
.idea
*.iml
# Project ignores

9
.travis.yml Normal file
View File

@ -0,0 +1,9 @@
language: go
go:
- '1.8'
- '1.9'
- '1.10'
before_install:
- go get -v github.com/google/go-querystring/query
- go get -v github.com/h2non/gock
script: go test -v ./...

381
v1/client.go Normal file
View File

@ -0,0 +1,381 @@
package v1
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"time"
"github.com/google/go-querystring/query"
)
// New initialize client
func New(url string, token string) *MgClient {
return &MgClient{
URL: url,
Token: token,
httpClient: &http.Client{Timeout: 20 * time.Second},
}
}
func (c *MgClient) Bots(request BotsRequest) (BotsResponse, int, error) {
var resp BotsResponse
var b []byte
outgoing, _ := query.Values(request)
data, status, err := c.GetRequest(fmt.Sprintf("/bots?%s", outgoing.Encode()), b)
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) Channels(request ChannelsRequest) (ChannelsResponse, int, error) {
var resp ChannelsResponse
var b []byte
outgoing, _ := query.Values(request)
data, status, err := c.GetRequest(fmt.Sprintf("/channels?%s", outgoing.Encode()), b)
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) Managers(request ManagersRequest) (ManagersResponse, int, error) {
var resp ManagersResponse
var b []byte
outgoing, _ := query.Values(request)
data, status, err := c.GetRequest(fmt.Sprintf("/managers?%s", outgoing.Encode()), b)
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) Customers(request CustomersRequest) (CustomersResponse, int, error) {
var resp CustomersResponse
var b []byte
outgoing, _ := query.Values(request)
data, status, err := c.GetRequest(fmt.Sprintf("/customers?%s", outgoing.Encode()), b)
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) Chats(request ChatsRequest) (ChatsResponse, int, error) {
var resp ChatsResponse
var b []byte
outgoing, _ := query.Values(request)
data, status, err := c.GetRequest(fmt.Sprintf("/chats?%s", outgoing.Encode()), b)
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) Members(request MembersRequest) (MembersResponse, int, error) {
var resp MembersResponse
var b []byte
outgoing, _ := query.Values(request)
data, status, err := c.GetRequest(fmt.Sprintf("/members?%s", outgoing.Encode()), b)
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) Dialogs(request DialogsRequest) (DialogsResponse, int, error) {
var resp DialogsResponse
var b []byte
outgoing, _ := query.Values(request)
data, status, err := c.GetRequest(fmt.Sprintf("/dialogs?%s", outgoing.Encode()), b)
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) DialogAssign(request DialogAssignRequest) (DialogAssignResponse, int, error) {
var resp DialogAssignResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.PostRequest(fmt.Sprintf("/dialogs/%s/assign", request.ID), []byte(outgoing))
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) DialogClose(request DialogCloseRequest) (DialogCloseResponse, int, error) {
var resp DialogCloseResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.PostRequest(fmt.Sprintf("/dialogs/%s/close", request.ID), []byte(outgoing))
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) Messages(request MessagesRequest) (MessagesResponse, int, error) {
var resp MessagesResponse
var b []byte
outgoing, _ := query.Values(request)
data, status, err := c.GetRequest(fmt.Sprintf("/messages?%s", outgoing.Encode()), b)
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) MessageSend(request MessageSendRequest) (MessageResponse, int, error) {
var resp MessageResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.PostRequest("/messages", []byte(outgoing))
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) MessageEdit(request MessageEditRequest) (MessageResponse, int, error) {
var resp MessageResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.PatchRequest(fmt.Sprintf("/messages/%s", request.ID), []byte(outgoing))
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) MessageDelete(request MessageDeleteRequest) (MessageResponse, int, error) {
var resp MessageResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.DeleteRequest(fmt.Sprintf("/messages/%s", request.ID), []byte(outgoing))
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) Info(request InfoRequest) (InfoResponse, int, error) {
var resp InfoResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.PatchRequest("/messages/info", []byte(outgoing))
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) Commands(request CommandsRequest) (CommandsResponse, int, error) {
var resp CommandsResponse
var b []byte
outgoing, _ := query.Values(request)
data, status, err := c.GetRequest(fmt.Sprintf("/my/commands?%s", outgoing.Encode()), b)
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) CommandEdit(request CommandEditRequest) (CommandEditResponse, int, error) {
var resp CommandEditResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.PutRequest(fmt.Sprintf("/my/commands/%s", request.Name), []byte(outgoing))
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) CommandDelete(request CommandDeleteRequest) (CommandDeleteResponse, int, error) {
var resp CommandDeleteResponse
outgoing, _ := json.Marshal(&request)
data, status, err := c.DeleteRequest(fmt.Sprintf("/my/commands/%s", request.Name), []byte(outgoing))
if err != nil {
return resp, status, err
}
if err := json.Unmarshal(data, &resp); err != nil {
return resp, status, err
}
if status > http.StatusCreated || status < http.StatusOK {
return resp, status, c.Error(data)
}
return resp, status, err
}
func (c *MgClient) Error(info []byte) error {
var data map[string]interface{}
if err := json.Unmarshal(info, &data); err != nil {
return err
}
values := data["errors"].([]interface{})
return errors.New(values[0].(string))
}

14
v1/client_test.go Normal file
View File

@ -0,0 +1,14 @@
package v1
import (
"os"
)
var (
mgURL = os.Getenv("MG_URL")
mgToken = os.Getenv("MG_TOKEN")
)
func client() *MgClient {
return New(mgURL, mgToken)
}

108
v1/request.go Normal file
View File

@ -0,0 +1,108 @@
package v1
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
)
var prefix = "/api/v1"
// GetRequest implements GET Request
func (c *MgClient) GetRequest(url string, parameters []byte) ([]byte, int, error) {
return makeRequest(
"GET",
fmt.Sprintf("%s%s%s", c.URL, prefix, url),
bytes.NewBuffer(parameters),
c,
)
}
// PostRequest implements POST Request
func (c *MgClient) PostRequest(url string, parameters []byte) ([]byte, int, error) {
return makeRequest(
"POST",
fmt.Sprintf("%s%s%s", c.URL, prefix, url),
bytes.NewBuffer(parameters),
c,
)
}
// PatchRequest implements PATCH Request
func (c *MgClient) PatchRequest(url string, parameters []byte) ([]byte, int, error) {
return makeRequest(
"PATCH",
fmt.Sprintf("%s%s%s", c.URL, prefix, url),
bytes.NewBuffer(parameters),
c,
)
}
// PutRequest implements PUT Request
func (c *MgClient) PutRequest(url string, parameters []byte) ([]byte, int, error) {
return makeRequest(
"PUT",
fmt.Sprintf("%s%s%s", c.URL, prefix, url),
bytes.NewBuffer(parameters),
c,
)
}
// DeleteRequest implements DELETE Request
func (c *MgClient) DeleteRequest(url string, parameters []byte) ([]byte, int, error) {
return makeRequest(
"DELETE",
fmt.Sprintf("%s%s%s", c.URL, prefix, url),
bytes.NewBuffer(parameters),
c,
)
}
func makeRequest(reqType, url string, buf *bytes.Buffer, c *MgClient) ([]byte, int, error) {
var res []byte
req, err := http.NewRequest(reqType, url, buf)
if err != nil {
return res, 0, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Bot-Token", c.Token)
if c.Debug {
log.Printf("MG BOT API Request: %s %s %s %s", reqType, url, c.Token, buf.String())
}
resp, err := c.httpClient.Do(req)
if err != nil {
return res, 0, err
}
if resp.StatusCode >= http.StatusInternalServerError {
err = fmt.Errorf("http request error. Status code: %d", resp.StatusCode)
return res, resp.StatusCode, err
}
res, err = buildRawResponse(resp)
if err != nil {
return res, 0, err
}
if c.Debug {
log.Printf("MG BOT API Response: %s", res)
}
return res, resp.StatusCode, err
}
func buildRawResponse(resp *http.Response) ([]byte, error) {
defer resp.Body.Close()
res, err := ioutil.ReadAll(resp.Body)
if err != nil {
return res, err
}
return res, nil
}

275
v1/types.go Normal file
View File

@ -0,0 +1,275 @@
package v1
import (
"net/http"
)
// MgClient type
type MgClient struct {
URL string `json:"url"`
Token string `json:"token"`
Debug bool `json:"debug"`
httpClient *http.Client
}
type BotsRequest struct {
ID uint64
Self string
Active string
Since string
Until string
}
type ChannelsRequest struct {
ID uint64
Types string
Active string
Since string
Until string
}
type ManagersRequest struct {
ID uint64
ExternalID string `json:"external_id"`
Online string
Active string
Since string
Until string
}
type CustomersRequest struct {
ID uint64
ExternalID string `json:"external_id"`
Since string
Until string
}
type ChatsRequest struct {
ID uint64
ChannelID string `json:"channel_id"`
ChannelType string `json:"channel_type"`
Since string
Until string
}
type MembersRequest struct {
ChatID string `json:"chat_id"`
ManagerID string `json:"manager_id"`
CustomerID string `json:"customer_id"`
Status string
Since string
Until string
}
type DialogsRequest struct {
ID uint64
ChatID string `json:"chat_id"`
ManagerID string `json:"manager_id"`
BotID string `json:"bot_id"`
Active string
Assigned string
Since string
Until string
}
type MessagesRequest struct {
ID uint64
ChatID string `json:"chat_id"`
DialogID string `json:"dialog_id"`
ManagerID string `json:"manager_id"`
CustomerID string `json:"customer_id"`
BotID string `json:"bot_id"`
ChannelID string `json:"channel_id"`
ChannelType string `json:"channel_type"`
Scope string
Since string
Until string
}
type MessageSendRequest struct {
Content string `json:"content"`
Scope uint8 `json:"scope"`
ChatID uint64 `json:"chat_id"`
QuoteMessageId uint64 `json:"omitempty,quote_message_id"`
}
type MessageEditRequest struct {
ID uint64
Content string `json:"content"`
}
type CommandsRequest struct {
ID string
Name string
Since string
Until string
}
type BotsResponse struct {
Bots []BotListItem
}
type BotListItem struct {
ID uint64 `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Events []string `json:"events,omitempty,brackets"`
ClientID string `json:"client_id"`
AvatarUrl string `json:"avatar_url"`
CreatedAt string `json:"created_at"`
UpdatedAt *string `json:"updated_at"`
DeactivatedAt *string `json:"deactivated_at"`
IsActive bool `json:"is_active"`
IsSelf bool `json:"is_self"`
}
type ChannelsResponse struct {
Channels []ChannelListItem
}
type ChannelListItem struct {
ID uint64 `json:"id"`
Type string `json:"type"`
Events []string `json:"events,omitempty,brackets"`
CreatedAt string `json:"created_at"`
UpdatedAt *string `json:"updated_at"`
ActivatedAt string `json:"activated_at"`
DeactivatedAt *string `json:"deactivated_at"`
IsActive bool `json:"is_active"`
}
type ManagersResponse struct {
Managers []ManagersListItem
}
type ManagersListItem 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"`
}
type CustomersResponse struct {
Customers []CustomersListItem
}
type CustomersListItem struct {
ID uint64 `json:"id"`
ExternalID *string `json:"external_id,omitempty"`
ChannelId *uint64 `json:"channel_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"`
Avatar *string `json:"avatar_url,omitempty"`
ProfileURL *string `json:"profile_url,omitempty"`
Country *string `json:"country,omitempty"`
Language *string `json:"language,omitempty"`
Phone *string `json:"phone,omitempty"`
}
type ChatsResponse struct {
Chats []ChatListItem
}
type ChatListItem struct {
ID uint64 `json:"id"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
Channel *string `json:"channel,omitempty"`
ChannelId *uint64 `json:"channel_id,omitempty"`
}
type MembersResponse struct {
Members []MemberListItem
}
type MemberListItem struct {
ID uint64 `json:"id"`
CreatedAt string `json:"created_at"`
UpdatedAt *string `json:"updated_at,omitempty"`
IsAuthor bool `json:"is_author"`
State string `json:"state"`
ChatID uint64 `json:"chat_id"`
UserID uint64 `json:"user_id"`
}
type DialogsResponse struct {
Dialogs []DialogListItem
}
type DialogListItem struct {
ID uint64 `json:"id"`
ChatID uint64 `json:"chat_id"`
BotID *uint64 `json:"bot_id,omitempty"`
BeginMessageID *uint64 `json:"begin_message_id,omitempty"`
EndingMessageID *uint64 `json:"ending_message_id,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt *string `json:"updated_at,omitempty"`
ClosedAt *string `json:"closed_at,omitempty"`
IsAssign bool `json:"is_assign"`
Responsible *Responsible `json:"responsible,omitempty"`
IsActive bool `json:"is_active"`
}
type MessagesResponse struct {
Messages []MessagesListItem
}
type MessagesListItem struct {
ID uint64 `json:"id"`
Content string `json:"content"`
CreatedAt string `json:"created_at"`
UpdatedAt *string `json:"updated_at"`
Scope uint8 `json:"scope"`
ChatID uint64 `json:"chat_id"`
Sender Sender `json:"sender"`
ChannelID *uint64 `json:"channel_id,omitempty"`
ChannelSentAt *string `json:"channel_sent_at,omitempty"`
QuoteMessageId *uint64 `json:"quote_message_id,omitempty"`
EditedAt *string `json:"edited_at,omitempty"`
DeletedAt *string `json:"deleted_at,omitempty"`
}
type MessageResponse struct {
ID uint64 `json:"id"`
Time string `json:"content"`
}
type UpdateBotRequest struct {
Name string `json:"name,omitempty"`
Avatar *string `json:"avatar_url"`
Events []string `json:"events,omitempty,brackets"`
}
type Responsible struct {
Type string `json:"type"`
ID int64 `json:"id"`
AssignAt string `json:"assign_at"`
}
type DialogResponsibleRequest struct {
ManagerID int64 `json:"manager_id"`
BotID int64 `json:"bot_id"`
}
type AssignResponse struct {
Responsible Responsible `json:"responsible"`
IsReAssign bool `json:"is_reassign"`
PreviousResponsible *Responsible `json:"previous_responsible,omitempty"`
LeftManagerID *uint64 `json:"left_manager_id,omitempty"`
}
type Sender struct {
ID int64
Type string
}