Skip to content

Commit

Permalink
Merge pull request #699 from nyaruka/m-sends
Browse files Browse the repository at this point in the history
Update M* handlers to use new send
  • Loading branch information
rowanseymour authored Feb 23, 2024
2 parents 47a550d + d15ff31 commit c6ea483
Show file tree
Hide file tree
Showing 18 changed files with 1,338 additions and 1,101 deletions.
28 changes: 8 additions & 20 deletions handlers/m3tech/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,19 +69,10 @@ func (h *handler) WriteMsgSuccessResponse(ctx context.Context, w http.ResponseWr
}

func (h *handler) Send(ctx context.Context, msg courier.MsgOut, res *courier.SendResult, clog *courier.ChannelLog) error {
// TODO convert functionality from legacy method below
return nil
}

func (h *handler) SendLegacy(ctx context.Context, msg courier.MsgOut, clog *courier.ChannelLog) (courier.StatusUpdate, error) {
username := msg.Channel().StringConfigForKey(courier.ConfigUsername, "")
if username == "" {
return nil, fmt.Errorf("no username set for M3 channel")
}

password := msg.Channel().StringConfigForKey(courier.ConfigPassword, "")
if password == "" {
return nil, fmt.Errorf("no password set for M3 channel")
if username == "" || password == "" {
return courier.ErrChannelConfig
}

// figure out if we need to send as unicode (encoding 7)
Expand All @@ -91,8 +82,6 @@ func (h *handler) SendLegacy(ctx context.Context, msg courier.MsgOut, clog *cour
encoding = "7"
}

// send our message
status := h.Backend().NewStatusUpdate(msg.Channel(), msg.ID(), courier.MsgStatusErrored, clog)
for _, part := range handlers.SplitMsgByChannel(msg.Channel(), text, maxMsgLength) {
// build our request
params := url.Values{
Expand All @@ -114,17 +103,16 @@ func (h *handler) SendLegacy(ctx context.Context, msg courier.MsgOut, clog *cour
msgURL.RawQuery = params.Encode()
req, err := http.NewRequest(http.MethodGet, msgURL.String(), nil)
if err != nil {
return nil, err
return err
}

resp, _, err := h.RequestHTTP(req, clog)
if err != nil || resp.StatusCode/100 != 2 {
break
if err != nil || resp.StatusCode/100 == 5 {
return courier.ErrConnectionFailed
} else if resp.StatusCode/100 != 2 {
return courier.ErrResponseStatus
}

// all went well, set ourselves to wired
status.SetStatus(courier.MsgStatusWired)
}

return status, nil
return nil
}
143 changes: 103 additions & 40 deletions handlers/m3tech/handler_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package m3tech

import (
"net/http/httptest"
"net/url"
"testing"

"github.com/nyaruka/courier"
. "github.com/nyaruka/courier/handlers"
"github.com/nyaruka/courier/test"
"github.com/nyaruka/gocommon/httpx"
)

var testChannels = []courier.Channel{
Expand Down Expand Up @@ -47,52 +48,114 @@ func BenchmarkHandler(b *testing.B) {
RunChannelBenchmarks(b, testChannels, newHandler(), handleTestCases)
}

// setSendURL takes care of setting the send_url to our test server host
func setSendURL(s *httptest.Server, h courier.ChannelHandler, c courier.Channel, m courier.MsgOut) {
sendURL = s.URL
}

var defaultSendTestCases = []OutgoingTestCase{
{Label: "Plain Send",
MsgText: "Simple Message", MsgURN: "tel:+250788383383",
ExpectedMsgStatus: "W",
MockResponseBody: `[{"Response": "0"}]`, MockResponseStatus: 200,
ExpectedURLParams: map[string]string{
"MobileNo": "250788383383",
"SMS": "Simple Message",
"SMSChannel": "0",
"AuthKey": "m3-Tech",
"HandsetPort": "0",
"MsgHeader": "2020",
"Telco": "0",
"SMSType": "0",
"UserId": "Username",
"Password": "Password",
MsgText: "Simple Message",
MsgURN: "tel:+250788383383",
MockResponses: map[string][]*httpx.MockResponse{
"https://secure.m3techservice.com/GenericServiceRestAPI/api/SendSMS*": {
httpx.NewMockResponse(200, nil, []byte(`[{"Response": "0"}]`)),
},
},
SendPrep: setSendURL},
ExpectedRequests: []ExpectedRequest{{
Params: url.Values{
"MobileNo": {"250788383383"},
"SMS": {"Simple Message"},
"SMSChannel": {"0"},
"AuthKey": {"m3-Tech"},
"HandsetPort": {"0"},
"MsgHeader": {"2020"},
"MsgId": {"10"},
"Telco": {"0"},
"SMSType": {"0"},
"UserId": {"Username"},
"Password": {"Password"},
},
}},
},
{Label: "Unicode Send",
MsgText: "☺", MsgURN: "tel:+250788383383",
ExpectedMsgStatus: "W",
MockResponseBody: `[{"Response": "0"}]`, MockResponseStatus: 200,
ExpectedURLParams: map[string]string{"SMS": "☺", "SMSType": "7"},
SendPrep: setSendURL},
MsgText: "☺",
MsgURN: "tel:+250788383383",
MockResponses: map[string][]*httpx.MockResponse{
"https://secure.m3techservice.com/GenericServiceRestAPI/api/SendSMS*": {
httpx.NewMockResponse(200, nil, []byte(`[{"Response": "0"}]`)),
},
},
ExpectedRequests: []ExpectedRequest{{
Params: url.Values{
"SMS": {"☺"},
"MobileNo": {"250788383383"},
"SMSChannel": {"0"},
"AuthKey": {"m3-Tech"},
"HandsetPort": {"0"},
"MsgHeader": {"2020"},
"MsgId": {"10"},
"Telco": {"0"},
"SMSType": {"7"},
"UserId": {"Username"},
"Password": {"Password"},
},
}},
},
{Label: "Smart Encoding",
MsgText: "Fancy “Smart” Quotes", MsgURN: "tel:+250788383383",
ExpectedMsgStatus: "W",
MockResponseBody: `[{"Response": "0"}]`, MockResponseStatus: 200,
ExpectedURLParams: map[string]string{"SMS": `Fancy "Smart" Quotes`, "SMSType": "0"},
SendPrep: setSendURL},
MsgText: "Fancy “Smart” Quotes",
MsgURN: "tel:+250788383383",
MockResponses: map[string][]*httpx.MockResponse{
"https://secure.m3techservice.com/GenericServiceRestAPI/api/SendSMS*": {
httpx.NewMockResponse(200, nil, []byte(`[{"Response": "0"}]`)),
},
},
ExpectedRequests: []ExpectedRequest{{
Params: url.Values{
"SMS": {`Fancy "Smart" Quotes`},
"MobileNo": {"250788383383"},
"SMSChannel": {"0"},
"AuthKey": {"m3-Tech"},
"HandsetPort": {"0"},
"MsgHeader": {"2020"},
"MsgId": {"10"},
"Telco": {"0"},
"SMSType": {"0"},
"UserId": {"Username"},
"Password": {"Password"},
},
}},
},
{Label: "Send Attachment",
MsgText: "My pic!", MsgURN: "tel:+250788383383", MsgAttachments: []string{"image/jpeg:https://foo.bar/image.jpg"},
ExpectedMsgStatus: "W",
MockResponseBody: `[{"Response": "0"}]`, MockResponseStatus: 200,
ExpectedURLParams: map[string]string{"SMS": "My pic!\nhttps://foo.bar/image.jpg", "SMSType": "0"},
SendPrep: setSendURL},
MsgText: "My pic!",
MsgURN: "tel:+250788383383",
MsgAttachments: []string{"image/jpeg:https://foo.bar/image.jpg"},
MockResponses: map[string][]*httpx.MockResponse{
"https://secure.m3techservice.com/GenericServiceRestAPI/api/SendSMS*": {
httpx.NewMockResponse(200, nil, []byte(`[{"Response": "0"}]`)),
},
},
ExpectedRequests: []ExpectedRequest{{
Params: url.Values{
"SMS": {"My pic!\nhttps://foo.bar/image.jpg"},
"MobileNo": {"250788383383"},
"SMSChannel": {"0"},
"AuthKey": {"m3-Tech"},
"HandsetPort": {"0"},
"MsgHeader": {"2020"},
"MsgId": {"10"},
"Telco": {"0"},
"SMSType": {"0"},
"UserId": {"Username"},
"Password": {"Password"},
},
}},
},
{Label: "Error Sending",
MsgText: "Error Sending", MsgURN: "tel:+250788383383",
ExpectedMsgStatus: "E",
MockResponseBody: `[{"Response": "101"}]`, MockResponseStatus: 403,
SendPrep: setSendURL},
MsgText: "Error Sending",
MsgURN: "tel:+250788383383",
MockResponses: map[string][]*httpx.MockResponse{
"https://secure.m3techservice.com/GenericServiceRestAPI/api/SendSMS*": {
httpx.NewMockResponse(403, nil, []byte(`[{"Response": "101"}]`)),
},
},
ExpectedError: courier.ErrResponseStatus,
},
}

func TestOutgoing(t *testing.T) {
Expand Down
30 changes: 11 additions & 19 deletions handlers/macrokiosk/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,17 +150,12 @@ type mtPayload struct {
}

func (h *handler) Send(ctx context.Context, msg courier.MsgOut, res *courier.SendResult, clog *courier.ChannelLog) error {
// TODO convert functionality from legacy method below
return nil
}

func (h *handler) SendLegacy(ctx context.Context, msg courier.MsgOut, clog *courier.ChannelLog) (courier.StatusUpdate, error) {
username := msg.Channel().StringConfigForKey(courier.ConfigUsername, "")
password := msg.Channel().StringConfigForKey(courier.ConfigPassword, "")
servID := msg.Channel().StringConfigForKey(configMacrokioskServiceID, "")
senderID := msg.Channel().StringConfigForKey(configMacrokioskSenderID, "")
if username == "" || password == "" || servID == "" || senderID == "" {
return nil, fmt.Errorf("missing username, password, serviceID or senderID for MK channel")
return courier.ErrChannelConfig
}

// figure out if we need to send as unicode (encoding 5)
Expand All @@ -170,9 +165,8 @@ func (h *handler) SendLegacy(ctx context.Context, msg courier.MsgOut, clog *cour
encoding = "5"
}

status := h.Backend().NewStatusUpdate(msg.Channel(), msg.ID(), courier.MsgStatusErrored, clog)
parts := handlers.SplitMsgByChannel(msg.Channel(), text, maxMsgLength)
for i, part := range parts {
for _, part := range parts {
payload := &mtPayload{
From: senderID,
ServID: servID,
Expand All @@ -188,26 +182,24 @@ func (h *handler) SendLegacy(ctx context.Context, msg courier.MsgOut, clog *cour
// build our request
req, err := http.NewRequest(http.MethodPost, sendURL, requestBody)
if err != nil {
return nil, err
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")

resp, respBody, err := h.RequestHTTP(req, clog)
if err != nil || resp.StatusCode/100 != 2 {
return status, nil
if err != nil || resp.StatusCode/100 == 5 {
return courier.ErrConnectionFailed
} else if resp.StatusCode/100 != 2 {
return courier.ErrResponseStatus
}

externalID, err := jsonparser.GetString(respBody, "MsgID")
if err != nil {
return status, fmt.Errorf("unable to parse response body from Macrokiosk")
}

// set the external id if this is our first part
if i == 0 {
status.SetExternalID(externalID)
clog.Error(courier.ErrorResponseValueMissing("MsgID"))
} else {
res.AddExternalID(externalID)
}
}
status.SetStatus(courier.MsgStatusWired)
return status, nil
return nil
}
Loading

0 comments on commit c6ea483

Please sign in to comment.