diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e4b9d207..5b6f2486b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,6 +2,7 @@ name: CI on: [push, pull_request] env: go-version: '1.17.x' + redis-version: '3.2.4' jobs: test: name: Test @@ -16,7 +17,7 @@ jobs: - name: Install Redis uses: zhulik/redis-action@v1.0.0 with: - redis version: '5' + redis version: ${{ env.redis-version }} - name: Install PostgreSQL uses: harmon758/postgresql-action@v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index d8af3263b..bf834618c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +v7.1.0 +---------- + * Remove chatbase support + * Test with Redis 3.2.4 + * Add support for 'Expired' status in the AT handler + v7.0.0 ---------- * Tweak README diff --git a/WENI-CHANGELOG.md b/WENI-CHANGELOG.md index 9825439ec..ece45164b 100644 --- a/WENI-CHANGELOG.md +++ b/WENI-CHANGELOG.md @@ -1,3 +1,7 @@ +1.2.0-courier-7.1.0 +---------- + * Merge tag v7.1.0 from nyaruka into our 1.1.8-courier-7.0.0 + 1.1.8-courier-7.0.0 ---------- * Fix whatsapp handler to update the contact URN if the wa_id returned in the send message request is different from the current URN path, avoiding creating a new contact. diff --git a/backends/rapidpro/backend.go b/backends/rapidpro/backend.go index 3125bf374..da6df33c6 100644 --- a/backends/rapidpro/backend.go +++ b/backends/rapidpro/backend.go @@ -17,7 +17,6 @@ import ( "github.com/jmoiron/sqlx" "github.com/nyaruka/courier" "github.com/nyaruka/courier/batch" - "github.com/nyaruka/courier/chatbase" "github.com/nyaruka/courier/queue" "github.com/nyaruka/courier/utils" "github.com/nyaruka/gocommon/storage" @@ -33,11 +32,6 @@ const msgQueueName = "msgs" // the name of our set for tracking sends const sentSetName = "msgs_sent_%s" -// constants used in org configs for chatbase -const chatbaseAPIKey = "CHATBASE_API_KEY" -const chatbaseVersion = "CHATBASE_VERSION" -const chatbaseMessageType = "agent" - // our timeout for backend operations const backendTimeout = time.Second * 20 @@ -292,16 +286,6 @@ func (b *backend) MarkOutgoingMsgComplete(ctx context.Context, msg courier.Msg, } } } - - // if this org has chatbase connected, notify chatbase - chatKey, _ := msg.Channel().OrgConfigForKey(chatbaseAPIKey, "").(string) - if chatKey != "" { - chatVersion, _ := msg.Channel().OrgConfigForKey(chatbaseVersion, "").(string) - err := chatbase.SendChatbaseMessage(chatKey, chatVersion, chatbaseMessageType, dbMsg.ContactID_.String(), msg.Channel().Name(), msg.Text(), time.Now().UTC()) - if err != nil { - logrus.WithError(err).WithField("chatbase_api_key", chatKey).WithField("chatbase_version", chatVersion).WithField("msg_id", dbMsg.ID().String()).Error("unable to write chatbase message") - } - } } // WriteMsg writes the passed in message to our store diff --git a/chatbase/chatbase.go b/chatbase/chatbase.go deleted file mode 100644 index e5bca39c9..000000000 --- a/chatbase/chatbase.go +++ /dev/null @@ -1,50 +0,0 @@ -package chatbase - -import ( - "bytes" - "encoding/json" - "net/http" - "time" - - "github.com/nyaruka/courier/utils" -) - -// ChatbaseAPIURL is the URL chatbase API messages will be sent to -var chatbaseAPIURL = "https://chatbase.com/api/message" - -// chatbaseLog is the payload for a chatbase request -type chatbaseLog struct { - Type string `json:"type"` - UserID string `json:"user_id"` - Platform string `json:"platform"` - Message string `json:"message"` - TimeStamp int64 `json:"time_stamp"` - - APIKey string `json:"api_key"` - APIVersion string `json:"version,omitempty"` -} - -// SendChatbaseMessage sends a chatbase message with the passed in api key and message details -func SendChatbaseMessage(apiKey string, apiVersion string, messageType string, userID string, platform string, message string, timestamp time.Time) error { - body := chatbaseLog{ - Type: messageType, - UserID: userID, - Platform: platform, - Message: message, - TimeStamp: timestamp.UnixNano() / int64(time.Millisecond), - - APIKey: apiKey, - APIVersion: apiVersion, - } - - jsonBody, err := json.Marshal(body) - if err != nil { - return err - } - - req, _ := http.NewRequest(http.MethodPost, chatbaseAPIURL, bytes.NewReader(jsonBody)) - req.Header.Set("Content-Type", "application/json") - - _, err = utils.MakeHTTPRequest(req) - return err -} diff --git a/chatbase/chatbase_test.go b/chatbase/chatbase_test.go deleted file mode 100644 index 12ee9dbe7..000000000 --- a/chatbase/chatbase_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package chatbase - -import ( - "bytes" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" - "time" - - "github.com/buger/jsonparser" - "github.com/stretchr/testify/assert" -) - -func TestChatbase(t *testing.T) { - var testRequest *http.Request - var statusCode = 200 - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, _ := ioutil.ReadAll(r.Body) - testRequest = httptest.NewRequest(r.Method, r.URL.String(), bytes.NewBuffer(body)) - testRequest.Header = r.Header - w.WriteHeader(statusCode) - w.Write([]byte("ok")) - })) - defer server.Close() - - chatbaseAPIURL = server.URL - - now := time.Now() - err := SendChatbaseMessage("apiKey", "apiVersion", "messageType", "userID", "platform", "message", now) - assert.NoError(t, err) - - // parse our body - bytes, err := ioutil.ReadAll(testRequest.Body) - assert.NoError(t, err) - - // check our request body - str, err := jsonparser.GetString(bytes, "type") - assert.NoError(t, err) - assert.Equal(t, "messageType", str) - - str, err = jsonparser.GetString(bytes, "version") - assert.NoError(t, err) - assert.Equal(t, "apiVersion", str) - - ts, err := jsonparser.GetInt(bytes, "time_stamp") - assert.NoError(t, err) - assert.Equal(t, now.UnixNano()/int64(time.Millisecond), ts) - - // simulate an error - statusCode = 500 - err = SendChatbaseMessage("apiKey", "apiVersion", "messageType", "userID", "platform", "message", now) - assert.Error(t, err) - - // simulate error when messageType is invalid - statusCode = 400 - err = SendChatbaseMessage("apiKey", "apiVersion", "msg", "userID", "platform", "message", now) - assert.Error(t, err) - - bytes, err = ioutil.ReadAll(testRequest.Body) - str, err = jsonparser.GetString(bytes, "type") - assert.NoError(t, err) - assert.Equal(t, "msg", str) -} diff --git a/handlers/africastalking/africastalking.go b/handlers/africastalking/africastalking.go index b64553d59..e196212fb 100644 --- a/handlers/africastalking/africastalking.go +++ b/handlers/africastalking/africastalking.go @@ -91,6 +91,7 @@ var statusMapping = map[string]courier.MsgStatusValue{ "Buffered": courier.MsgSent, "Rejected": courier.MsgFailed, "Failed": courier.MsgFailed, + "Expired": courier.MsgFailed, } // receiveStatus is our HTTP handler function for status updates @@ -105,7 +106,7 @@ func (h *handler) receiveStatus(ctx context.Context, channel courier.Channel, w msgStatus, found := statusMapping[form.Status] if !found { return nil, handlers.WriteAndLogRequestError(ctx, h, channel, w, r, - fmt.Errorf("unknown status '%s', must be one of 'Success','Sent','Buffered','Rejected' or 'Failed'", form.Status)) + fmt.Errorf("unknown status '%s', must be one of 'Success','Sent','Buffered','Rejected', 'Failed', or 'Expired'", form.Status)) } // write our status diff --git a/handlers/africastalking/africastalking_test.go b/handlers/africastalking/africastalking_test.go index cc36711e3..c3941a58a 100644 --- a/handlers/africastalking/africastalking_test.go +++ b/handlers/africastalking/africastalking_test.go @@ -26,7 +26,8 @@ var ( missingStatus = "id=ATXid_dda018a640edfcc5d2ce455de3e4a6e7" invalidStatus = "id=ATXid_dda018a640edfcc5d2ce455de3e4a6e7&status=Borked" - validStatus = "id=ATXid_dda018a640edfcc5d2ce455de3e4a6e7&status=Success" + successStatus = "id=ATXid_dda018a640edfcc5d2ce455de3e4a6e7&status=Success" + expiredStatus = "id=ATXid_dda018a640edfcc5d2ce455de3e4a6e7&status=Expired" ) var testCases = []ChannelHandleTestCase{ @@ -42,7 +43,8 @@ var testCases = []ChannelHandleTestCase{ {Label: "Invalid Date", URL: receiveURL, Data: invalidDate, Status: 400, Response: "invalid date format"}, {Label: "Status Invalid", URL: statusURL, Status: 400, Data: invalidStatus, Response: "unknown status"}, {Label: "Status Missing", URL: statusURL, Status: 400, Data: missingStatus, Response: "field 'status' required"}, - {Label: "Status Valid", URL: statusURL, Status: 200, Data: validStatus, Response: `"status":"D"`}, + {Label: "Status Success", URL: statusURL, Status: 200, Data: successStatus, Response: `"status":"D"`}, + {Label: "Status Expired", URL: statusURL, Status: 200, Data: expiredStatus, Response: `"status":"F"`}, } func TestHandler(t *testing.T) {