Skip to content

Add Chime Bot event #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions events/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ This package provides input types for Lambda functions that process AWS events.

[CloudFormation Events](../cfn/README.md)

[Chime Bot Events](README_Chime_Bots.md)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be "Chime Bot Event" (without the trailing "s")

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an EventType field, plural makes sense to me :)


[Code Commit Events](README_CodeCommit.md)

[Cognito Events](README_Cognito.md)
Expand Down
67 changes: 67 additions & 0 deletions events/README_Chime_Bots.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Sample Function

The following is a sample class and Lambda function that receives a Amazon Chime Bot event and handles the various event types accordingly.

```go

package main

import (
"fmt"
"context"
"net/http"
"bytes"
"encoding/json"
"errors"
"strconv"

"github.com/aws/aws-lambda-go/events"
)

func handler(_ context.Context, chimeBotEvent events.ChimeBotEvent) error {
switch chimeBotEvent.EventType {
case "Invite":
if err := message(chimeBotEvent.InboundHTTPSEndpoint.URL, "Thanks for inviting me to this room " + chimeBotEvent.Sender.SenderID); err != nil {
return fmt.Errorf("failed to send webhook message: %v", err)
}
return nil
case "Mention":
if err := message(chimeBotEvent.InboundHTTPSEndpoint.URL, "Thanks for mentioning me " + chimeBotEvent.Sender.SenderID); err != nil {
return fmt.Errorf("failed to send webhook message: %v", err)
}
return nil
case "Remove":
fmt.Printf("I have been removed from %q by %q", chimeBotEvent.Discussion.DiscussionType, chimeBotEvent.Sender.SenderID)
return nil
default:
return fmt.Errorf("event type %q is unsupported", chimeBotEvent.EventType)
}
}

func message(url, content string) (error) {
input := &bytes.Buffer{}
if err := json.NewEncoder(input).Encode(webhookInput{Content:content}); err != nil {
return errors.New("failed to marshal request: " + err.Error())
}

resp, err := http.Post("POST", url, input)
if err != nil {
return errors.New("failed to execute post http request: " + err.Error())
}

if resp != nil && resp.Body != nil {
defer resp.Body.Close()
}

if resp.StatusCode != http.StatusOK {
return errors.New("bad response: status code not is " + strconv.Itoa(http.StatusOK) + " not " + strconv.Itoa(resp.StatusCode))
}

return nil
}

type webhookInput struct {
Content string `json:"Content"`
}

```
31 changes: 31 additions & 0 deletions events/chime_bot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.

package events

import (
"time"
)

type ChimeBotEvent struct {
Sender ChimeBotEventSender `json:"Sender"`
Discussion ChimeBotEventDiscussion `json:"Discussion"`
EventType string `json:"EventType"`
InboundHTTPSEndpoint *ChimeBotEventInboundHTTPSEndpoint `json:"InboundHttpsEndpoint,omitempty"`
EventTimestamp time.Time `json:"EventTimestamp"`
Message string `json:"Message,omitempty"`
}

type ChimeBotEventSender struct {
SenderID string `json:"SenderId"`
SenderIDType string `json:"SenderIdType"`
}

type ChimeBotEventDiscussion struct {
DiscussionID string `json:"DiscussionId"`
DiscussionType string `json:"DiscussionType"`
}

type ChimeBotEventInboundHTTPSEndpoint struct {
EndpointType string `json:"EndpointType"`
URL string `json:"Url"`
}
138 changes: 138 additions & 0 deletions events/chime_bot_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
package events

import (
"encoding/json"
"testing"

"github.com/aws/aws-lambda-go/events/test"
"github.com/stretchr/testify/assert"
"time"
)

func TestChimeBotEventMarshaling(t *testing.T) {
// From https://docs.aws.amazon.com/chime/latest/ag/manage-chat-bots.html
tests := map[string]struct {
inputJSON string
expectedEvent ChimeBotEvent
}{
"Example Invite Event": {
inputJSON: ` {
"Sender": {
"SenderId": "[email protected]",
"SenderIdType": "EmailId"
},
"Discussion": {
"DiscussionId": "abcdef12-g34h-56i7-j8kl-mn9opqr012st",
"DiscussionType": "Room"
},
"EventType": "Invite",
"InboundHttpsEndpoint": {
"EndpointType": "Persistent",
"Url": "https://hooks.a.chime.aws/incomingwebhooks/a1b2c34d-5678-90e1-f23g-h45i67j8901k?token=ABCDefGHiJK1LMnoP2Q3RST4uvwxYZAbC56DeFghIJkLM7N8OP9QRsTuV0WXYZABcdefgHiJ"
},
"EventTimestamp": "2019-04-04T21:27:52.736Z"
}`,
expectedEvent: ChimeBotEvent{
Sender: ChimeBotEventSender{
SenderID: "[email protected]",
SenderIDType: "EmailId",
},
Discussion: ChimeBotEventDiscussion{
DiscussionID: "abcdef12-g34h-56i7-j8kl-mn9opqr012st",
DiscussionType: "Room",
},
EventType: "Invite",
InboundHTTPSEndpoint: &ChimeBotEventInboundHTTPSEndpoint{
EndpointType: "Persistent",
URL: "https://hooks.a.chime.aws/incomingwebhooks/a1b2c34d-5678-90e1-f23g-h45i67j8901k?token=ABCDefGHiJK1LMnoP2Q3RST4uvwxYZAbC56DeFghIJkLM7N8OP9QRsTuV0WXYZABcdefgHiJ",
},
EventTimestamp: time.Date(2019, 04, 04, 21, 27, 52, 736000000, time.UTC),
Message: "",
},
},
"Example Mention Event": {
inputJSON: `{
"Sender": {
"SenderId": "[email protected]",
"SenderIdType": "EmailId"
},
"Discussion": {
"DiscussionId": "abcdef12-g34h-56i7-j8kl-mn9opqr012st",
"DiscussionType": "Room"
},
"EventType": "Mention",
"InboundHttpsEndpoint": {
"EndpointType": "ShortLived",
"Url": "https://hooks.a.chime.aws/incomingwebhooks/a1b2c34d-5678-90e1-f23g-h45i67j8901k?token=ABCDefGHiJK1LMnoP2Q3RST4uvwxYZAbC56DeFghIJkLM7N8OP9QRsTuV0WXYZABcdefgHiJ"
},
"EventTimestamp": "2019-04-04T21:30:43.181Z",
"Message": "@[email protected] Hello Chatbot"
}`,
expectedEvent: ChimeBotEvent{
Sender: ChimeBotEventSender{
SenderID: "[email protected]",
SenderIDType: "EmailId",
},
Discussion: ChimeBotEventDiscussion{
DiscussionID: "abcdef12-g34h-56i7-j8kl-mn9opqr012st",
DiscussionType: "Room",
},
EventType: "Mention",
InboundHTTPSEndpoint: &ChimeBotEventInboundHTTPSEndpoint{
EndpointType: "ShortLived",
URL: "https://hooks.a.chime.aws/incomingwebhooks/a1b2c34d-5678-90e1-f23g-h45i67j8901k?token=ABCDefGHiJK1LMnoP2Q3RST4uvwxYZAbC56DeFghIJkLM7N8OP9QRsTuV0WXYZABcdefgHiJ",
},
EventTimestamp: time.Date(2019, 04, 04, 21, 30, 43, 181000000, time.UTC),
Message: "@[email protected] Hello Chatbot",
},
},
"Example Remove Event": {
inputJSON: `{
"Sender": {
"SenderId": "[email protected]",
"SenderIdType": "EmailId"
},
"Discussion": {
"DiscussionId": "abcdef12-g34h-56i7-j8kl-mn9opqr012st",
"DiscussionType": "Room"
},
"EventType": "Remove",
"EventTimestamp": "2019-04-04T21:27:29.626Z"
}`,
expectedEvent: ChimeBotEvent{
Sender: ChimeBotEventSender{
SenderID: "[email protected]",
SenderIDType: "EmailId",
},
Discussion: ChimeBotEventDiscussion{
DiscussionID: "abcdef12-g34h-56i7-j8kl-mn9opqr012st",
DiscussionType: "Room",
},
EventType: "Remove",
EventTimestamp: time.Date(2019, 04, 04, 21, 27, 29, 626000000, time.UTC),
},
},
}

for name, test := range tests {
t.Run(name, func(t *testing.T) {
var testEvent ChimeBotEvent
if err := json.Unmarshal([]byte(test.inputJSON), &testEvent); err != nil {
t.Errorf("could not unmarshal event. details: %v", err)
}

assert.Equal(t, testEvent, test.expectedEvent)

outputJSON, err := json.Marshal(testEvent)
if err != nil {
t.Errorf("could not marshal event. details: %v", err)
}
assert.JSONEq(t, test.inputJSON, string(outputJSON))
})
}
}

func TestChimeBotMarshalingMalformedJSON(t *testing.T) {
test.TestMalformedJson(t, ChimeBotEvent{})
}