-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Revert "Remove rocketchat as ticketer"
This reverts commit e67f87c.
- Loading branch information
1 parent
ee38a8c
commit 7268a1e
Showing
12 changed files
with
936 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package rocketchat | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"github.com/nyaruka/gocommon/httpx" | ||
"github.com/nyaruka/gocommon/jsonx" | ||
"github.com/pkg/errors" | ||
"io" | ||
"net/http" | ||
) | ||
|
||
// Client is a basic RocketChat app client | ||
type Client struct { | ||
httpClient *http.Client | ||
httpRetries *httpx.RetryConfig | ||
baseURL string | ||
secret string | ||
} | ||
|
||
// NewClient creates a new RocketChat app client | ||
func NewClient(httpClient *http.Client, httpRetries *httpx.RetryConfig, baseURL, secret string) *Client { | ||
return &Client{ | ||
httpClient: httpClient, | ||
httpRetries: httpRetries, | ||
baseURL: baseURL, | ||
secret: secret, | ||
} | ||
} | ||
|
||
type errorResponse struct { | ||
Error string `json:"error"` | ||
} | ||
|
||
func (c *Client) request(method, endpoint string, payload interface{}, response interface{}) (*httpx.Trace, error) { | ||
url := fmt.Sprintf("%s/%s", c.baseURL, endpoint) | ||
headers := map[string]string{ | ||
"Authorization": fmt.Sprintf("Token %s", c.secret), | ||
"Content-Type": "application/json", | ||
} | ||
var body io.Reader | ||
|
||
if payload != nil { | ||
data, err := jsonx.Marshal(payload) | ||
if err != nil { | ||
return nil, err | ||
} | ||
body = bytes.NewReader(data) | ||
} | ||
|
||
req, err := httpx.NewRequest(method, url, body, headers) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
trace, err := httpx.DoTrace(c.httpClient, req, c.httpRetries, nil, -1) | ||
if err != nil { | ||
return trace, err | ||
} | ||
|
||
if trace.Response.StatusCode >= 400 { | ||
response := &errorResponse{} | ||
err := jsonx.Unmarshal(trace.ResponseBody, response) | ||
if err != nil { | ||
return trace, err | ||
} | ||
return trace, errors.New(response.Error) | ||
} | ||
|
||
if response != nil { | ||
return trace, jsonx.Unmarshal(trace.ResponseBody, response) | ||
} | ||
return trace, nil | ||
} | ||
|
||
func (c *Client) get(endpoint string, payload interface{}, response interface{}) (*httpx.Trace, error) { | ||
return c.request("GET", endpoint, payload, response) | ||
} | ||
|
||
func (c *Client) post(endpoint string, payload interface{}, response interface{}) (*httpx.Trace, error) { | ||
return c.request("POST", endpoint, payload, response) | ||
} | ||
|
||
type Visitor struct { | ||
Token string `json:"token"` | ||
ContactUUID string `json:"contactUUID,omitempty"` | ||
Name string `json:"name,omitempty"` | ||
Email string `json:"email,omitempty"` | ||
Phone string `json:"phone,omitempty"` | ||
} | ||
|
||
type Room struct { | ||
Visitor Visitor `json:"visitor"` | ||
TicketID string `json:"ticketID"` | ||
} | ||
|
||
// CreateRoom creates a new room and returns the ID | ||
func (c *Client) CreateRoom(room *Room) (string, *httpx.Trace, error) { | ||
response := &struct { | ||
ID string `json:"id"` | ||
}{} | ||
|
||
trace, err := c.get("room", room, response) | ||
if err != nil { | ||
return "", trace, err | ||
} | ||
|
||
return response.ID, trace, nil | ||
} | ||
|
||
func (c *Client) CloseRoom(visitor *Visitor) (*httpx.Trace, error) { | ||
payload := struct { | ||
Visitor *Visitor `json:"visitor"` | ||
}{Visitor: visitor} | ||
|
||
trace, err := c.get("room.close", payload, nil) | ||
if err != nil { | ||
return trace, err | ||
} | ||
|
||
return trace, nil | ||
} | ||
|
||
type Attachment struct { | ||
Type string `json:"type"` | ||
URL string `json:"url"` | ||
} | ||
|
||
type VisitorMsg struct { | ||
Visitor Visitor `json:"visitor"` | ||
Text string `json:"text,omitempty"` | ||
Attachments []Attachment `json:"attachments,omitempty"` | ||
} | ||
|
||
func (c *Client) SendMessage(msg *VisitorMsg) (string, *httpx.Trace, error) { | ||
response := &struct { | ||
ID string `json:"id"` | ||
}{} | ||
|
||
trace, err := c.post("visitor-message", msg, response) | ||
if err != nil { | ||
return "", trace, err | ||
} | ||
|
||
return response.ID, trace, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
package rocketchat_test | ||
|
||
import ( | ||
"net/http" | ||
"testing" | ||
|
||
"github.com/nyaruka/gocommon/httpx" | ||
"github.com/nyaruka/mailroom/services/tickets/rocketchat" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
const ( | ||
baseURL = "https://my.rocket.chat/api/apps/public/684202ed-1461-4983-9ea7-fde74b15026c" | ||
secret = "123456789" | ||
) | ||
|
||
func TestCreateRoom(t *testing.T) { | ||
defer httpx.SetRequestor(httpx.DefaultRequestor) | ||
|
||
httpx.SetRequestor(httpx.NewMockRequestor(map[string][]*httpx.MockResponse{ | ||
baseURL + "/room": { | ||
httpx.MockConnectionError, | ||
httpx.NewMockResponse(400, nil, []byte(`{ "error": "There's no agents online" }`)), | ||
httpx.NewMockResponse(201, nil, []byte(`{ "id": "uiF7ybjsv7PSJGSw6" }`)), | ||
}, | ||
})) | ||
|
||
client := rocketchat.NewClient(http.DefaultClient, nil, baseURL, secret) | ||
room := &rocketchat.Room{ | ||
Visitor: rocketchat.Visitor{ | ||
Token: "1234", | ||
ContactUUID: "88ff1e41-c1f8-4637-af8e-d56acbde9171", | ||
Name: "Bob", | ||
Email: "bob@acme.com", | ||
Phone: "+16055741111", | ||
}, | ||
TicketID: "88ff1e41-c1f8-4637-af8e-d56acbde9171", | ||
} | ||
|
||
_, _, err := client.CreateRoom(room) | ||
assert.EqualError(t, err, "unable to connect to server") | ||
|
||
_, _, err = client.CreateRoom(room) | ||
assert.EqualError(t, err, "There's no agents online") | ||
|
||
id, trace, err := client.CreateRoom(room) | ||
assert.NoError(t, err) | ||
assert.Equal(t, id, "uiF7ybjsv7PSJGSw6") | ||
assert.Equal(t, "HTTP/1.0 201 Created\r\nContent-Length: 29\r\n\r\n", string(trace.ResponseTrace)) | ||
} | ||
|
||
func TestCloseRoom(t *testing.T) { | ||
defer httpx.SetRequestor(httpx.DefaultRequestor) | ||
|
||
httpx.SetRequestor(httpx.NewMockRequestor(map[string][]*httpx.MockResponse{ | ||
baseURL + "/room.close": { | ||
httpx.MockConnectionError, | ||
httpx.NewMockResponse(400, nil, []byte(`{ "error": "Could not find a room for visitor token: 1234" }`)), | ||
httpx.NewMockResponse(204, nil, nil), | ||
}, | ||
})) | ||
|
||
client := rocketchat.NewClient(http.DefaultClient, nil, baseURL, secret) | ||
visitor := &rocketchat.Visitor{Token: "1234"} | ||
|
||
_, err := client.CloseRoom(visitor) | ||
assert.EqualError(t, err, "unable to connect to server") | ||
|
||
_, err = client.CloseRoom(visitor) | ||
assert.EqualError(t, err, "Could not find a room for visitor token: 1234") | ||
|
||
trace, err := client.CloseRoom(visitor) | ||
assert.NoError(t, err) | ||
assert.Equal(t, "HTTP/1.0 204 No Content\r\n\r\n", string(trace.ResponseTrace)) | ||
} | ||
|
||
func TestSendMessage(t *testing.T) { | ||
defer httpx.SetRequestor(httpx.DefaultRequestor) | ||
|
||
httpx.SetRequestor(httpx.NewMockRequestor(map[string][]*httpx.MockResponse{ | ||
baseURL + "/visitor-message": { | ||
httpx.MockConnectionError, | ||
httpx.NewMockResponse(400, nil, []byte(`{ "error": "Could not find a room for visitor token: 1234" }`)), | ||
httpx.NewMockResponse(201, nil, []byte(`{ "id": "tyLrD97j8TFZmT3Y6" }`)), | ||
}, | ||
})) | ||
|
||
client := rocketchat.NewClient(http.DefaultClient, nil, baseURL, secret) | ||
msg := &rocketchat.VisitorMsg{ | ||
Visitor: rocketchat.Visitor{Token: "1234"}, | ||
Text: "Can you help me?", | ||
Attachments: []rocketchat.Attachment{ | ||
{Type: "image/jpg", URL: "https://link.to/image.jpg"}, | ||
{Type: "video/mp4", URL: "https://link.to/video.mp4"}, | ||
{Type: "audio/ogg", URL: "https://link.to/audio.ogg"}, | ||
}, | ||
} | ||
|
||
_, _, err := client.SendMessage(msg) | ||
assert.EqualError(t, err, "unable to connect to server") | ||
|
||
_, _, err = client.SendMessage(msg) | ||
assert.EqualError(t, err, "Could not find a room for visitor token: 1234") | ||
|
||
id, trace, err := client.SendMessage(msg) | ||
assert.NoError(t, err) | ||
assert.Equal(t, id, "tyLrD97j8TFZmT3Y6") | ||
assert.Equal(t, "HTTP/1.0 201 Created\r\nContent-Length: 29\r\n\r\n", string(trace.ResponseTrace)) | ||
} |
Oops, something went wrong.