Skip to content

Commit

Permalink
Add support for new keyboard rows
Browse files Browse the repository at this point in the history
  • Loading branch information
Robi9 committed Jan 4, 2022
1 parent 2055330 commit 220295b
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 74 deletions.
41 changes: 41 additions & 0 deletions handlers/vk/keyboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package vk

import (
"github.com/nyaruka/courier/utils"
"github.com/nyaruka/gocommon/jsonx"
)

type Keyboard struct {
One_Time bool `json:"one_time"`
Buttons [][]ButtonPayload `json:"buttons"`
Inline bool `json:"inline"`
}

type ButtonPayload struct {
Action ButtonAction `json:"action"`
Color string `json:"color"`
}

type ButtonAction struct {
Type string `json:"type"`
Label string `json:"label"`
Payload string `json:"payload"`
}

// NewKeyboardFromReplies creates a keyboard from the given quick replies
func NewKeyboardFromReplies(replies []string) *Keyboard {
rows := utils.StringsToRows(replies, 10, 30, 2)
buttons := make([][]ButtonPayload, len(rows))

for i := range rows {
buttons[i] = make([]ButtonPayload, len(rows[i]))
for j := range rows[i] {
buttons[i][j].Action.Label = rows[i][j]
buttons[i][j].Action.Type = "text"
buttons[i][j].Action.Payload = string(jsonx.MustMarshal(rows[i][j]))
buttons[i][j].Color = "primary"
}
}

return &Keyboard{One_Time: true, Buttons: buttons, Inline: false}
}
98 changes: 98 additions & 0 deletions handlers/vk/keyboard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package vk_test

import (
"testing"

"github.com/nyaruka/courier/handlers/vk"
"github.com/stretchr/testify/assert"
)

func TestKeyboardFromReplies(t *testing.T) {
tcs := []struct {
replies []string
expected *vk.Keyboard
}{
{

[]string{"OK"},
&vk.Keyboard{
true,
[][]vk.ButtonPayload{
{
{vk.ButtonAction{Type: "text", Label: "OK", Payload: "\"OK\""}, "primary"},
},
},
false,
},
},
{
[]string{"Yes", "No", "Maybe"},
&vk.Keyboard{
true,
[][]vk.ButtonPayload{
{
{vk.ButtonAction{Type: "text", Label: "Yes", Payload: "\"Yes\""}, "primary"},
{vk.ButtonAction{Type: "text", Label: "No", Payload: "\"No\""}, "primary"},
{vk.ButtonAction{Type: "text", Label: "Maybe", Payload: "\"Maybe\""}, "primary"},
},
},
false,
},
},
{
[]string{"Vanilla", "Chocolate", "Mint", "Lemon Sorbet", "Papaya", "Strawberry"},
&vk.Keyboard{
true,
[][]vk.ButtonPayload{

{{vk.ButtonAction{Type: "text", Label: "Vanilla", Payload: "\"Vanilla\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "Chocolate", Payload: "\"Chocolate\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "Mint", Payload: "\"Mint\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "Lemon Sorbet", Payload: "\"Lemon Sorbet\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "Papaya", Payload: "\"Papaya\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "Strawberry", Payload: "\"Strawberry\""}, "primary"}},
},
false,
},
},
{
[]string{"A", "B", "C", "D", "Chicken", "Fish", "Peanut Butter Pickle"},
&vk.Keyboard{
true,
[][]vk.ButtonPayload{

{{vk.ButtonAction{Type: "text", Label: "A", Payload: "\"A\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "B", Payload: "\"B\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "C", Payload: "\"C\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "D", Payload: "\"D\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "Chicken", Payload: "\"Chicken\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "Fish", Payload: "\"Fish\""}, "primary"}},
{{vk.ButtonAction{Type: "text", Label: "Peanut Butter Pickle", Payload: "\"Peanut Butter Pickle\""}, "primary"}},
},
false,
},
},
{
[]string{"A", "B", "C", "D", "E"},
&vk.Keyboard{
true,
[][]vk.ButtonPayload{

{
{vk.ButtonAction{Type: "text", Label: "A", Payload: "\"A\""}, "primary"},
{vk.ButtonAction{Type: "text", Label: "B", Payload: "\"B\""}, "primary"},
{vk.ButtonAction{Type: "text", Label: "C", Payload: "\"C\""}, "primary"},
{vk.ButtonAction{Type: "text", Label: "D", Payload: "\"D\""}, "primary"},
{vk.ButtonAction{Type: "text", Label: "E", Payload: "\"E\""}, "primary"},
},
},
false,
},
},
}

for _, tc := range tcs {
kb := vk.NewKeyboardFromReplies(tc.replies)
assert.Equal(t, tc.expected, kb, "keyboard mismatch for replies %v", tc.replies)
}
}
76 changes: 4 additions & 72 deletions handlers/vk/vk.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/nyaruka/courier"
"github.com/nyaruka/courier/handlers"
"github.com/nyaruka/courier/utils"
"github.com/nyaruka/gocommon/jsonx"
"github.com/nyaruka/gocommon/urns"
)

Expand Down Expand Up @@ -191,23 +192,6 @@ type mediaUploadInfoPayload struct {
OwnerId int64 `json:"owner_id"`
}

type Keyboard struct {
One_Time bool `json:"one_time"`
Buttons [][]buttonPayload `json:"buttons"`
Inline bool `json:"inline"`
}

type buttonPayload struct {
Action buttonAction `json:"action"`
Color string `json:"color"`
}

type buttonAction struct {
Type string `json:"type"`
Label string `json:"label"`
Payload string `json:"payload"`
}

// receiveEvent handles request event type
func (h *handler) receiveEvent(ctx context.Context, channel courier.Channel, w http.ResponseWriter, r *http.Request) ([]courier.Event, error) {
// read request body
Expand Down Expand Up @@ -413,10 +397,10 @@ func (h *handler) SendMsg(ctx context.Context, msg courier.Msg) (courier.MsgStat
params.Set(paramAttachments, attachments)

if len(msg.QuickReplies()) != 0 {
keyboard := buildQuickRepliesParams(msg)
keyboardString := ToJSON(keyboard)
qrs := msg.QuickReplies()
keyboard := NewKeyboardFromReplies(qrs)

params.Set(paramKeyboard, keyboardString)
params.Set(paramKeyboard, string(jsonx.MustMarshal(keyboard)))
}

req, err := http.NewRequest(http.MethodPost, apiBaseURL+actionSendMessage, nil)
Expand Down Expand Up @@ -445,58 +429,6 @@ func (h *handler) SendMsg(ctx context.Context, msg courier.Msg) (courier.MsgStat
return status, nil
}

// ToJSON returns the JSON encoding of Keyboard.
func ToJSON(keyboard Keyboard) string {
b, _ := json.Marshal(keyboard)
return string(b)
}

//keyboard
func buildQuickRepliesParams(msg courier.Msg) Keyboard {

var keyboard Keyboard
keyboard = AddRowKeyboard(keyboard)

for _, qr := range msg.QuickReplies() {
keyboard = AddTextButton(qr, qr, "secondary", keyboard)
}
return keyboard
}

func AddRowKeyboard(keyboard Keyboard) Keyboard {
if len(keyboard.Buttons) == 0 {
keyboard.Buttons = make([][]buttonPayload, 1)
} else {
row := make([]buttonPayload, 0)
keyboard.Buttons = append(keyboard.Buttons, row)

}
keyboard.One_Time = true

return keyboard
}

func AddTextButton(label string, payload interface{}, color string, keyboard Keyboard) Keyboard {
b, err := json.Marshal(payload)
if err != nil {
panic(err)
}

button := buttonPayload{
Action: buttonAction{
Type: "text",
Label: label,
Payload: string(b),
},
Color: color,
}

lastRow := len(keyboard.Buttons) - 1
keyboard.Buttons[lastRow] = append(keyboard.Buttons[lastRow], button)

return keyboard
}

// buildTextAndAttachmentParams builds msg text with attachment links (if needed) and attachments list param, also returns the errors that occurred
func buildTextAndAttachmentParams(msg courier.Msg, status courier.MsgStatus) (string, string) {
var msgAttachments []string
Expand Down
4 changes: 2 additions & 2 deletions handlers/vk/vk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ const msgKeyboard = `{
"secret": "abc123xyz"
}`

const keyboardJson = `{"one_time":true,"buttons":[[{"action":{"type":"text","label":"Yes","payload":"\"Yes\""},"color":"secondary"}]],"inline":false}`
const keyboardJson = `{"one_time":true,"buttons":[[{"action":{"type":"text","label":"A","payload":"\"A\""},"color":"primary"},{"action":{"type":"text","label":"B","payload":"\"B\""},"color":"primary"},{"action":{"type":"text","label":"C","payload":"\"C\""},"color":"primary"},{"action":{"type":"text","label":"D","payload":"\"D\""},"color":"primary"},{"action":{"type":"text","label":"E","payload":"\"E\""},"color":"primary"}]],"inline":false}`

var testCases = []ChannelHandleTestCase{
{
Expand Down Expand Up @@ -476,7 +476,7 @@ var sendTestCases = []ChannelSendTestCase{
Label: "Send keyboard",
Text: "Send keyboard",
URN: "vk:123456789",
QuickReplies: []string{"Yes"},
QuickReplies: []string{"A", "B", "C", "D", "E"},
Status: "S",
SendPrep: setSendURL,
ExternalID: "1",
Expand Down

0 comments on commit 220295b

Please sign in to comment.