こんにちは!BPaaSプロダクト部の片岡です。
この記事はkubell Advent Calendar 2024(シリーズ 2)の16日目の記事です。
本投稿はAmazon EventBridge Pipesを使ってChatworkにメッセージを送れることを確認した内容となっています。
Chatwork APIでメッセージを投稿する場合、APIの利用回数制限がありリトライ処理が必要です。
AWS環境化においてはLambdaで実装することが多いのではないかと思います。
EventBridge PipesのAPI Destinationsはコードを書かずともAPI呼び出しおよびリトライ処理まで行ってくれますのでかなり楽ができるのではないかと思い、以下の構成を試してみました。
SQSキューをソースとしたEventBridge PipesでターゲットをAPI Destinationsとしていますす。
これでSQSにメッセージを送信すればChatwork APIでメッセージが送信されるはず。メッセージは下記のJSON形式とします。
{ "roomId" : 123456789, "message" : "こんにちは" }
次はメッセージのroomId
とmessage
をAPI Destinationsにパラメータとして渡します。
Chatwork APIのメッセージ投稿はURLでroom_id
を指定することになっています。
この場合はAPI Destinationsのパスパラメータを使用します。
パスパラメータを使用する場合、API送信先のエンドポイントのパラメータとする部分に *
を指定します。
Chatwork APIのメッセージ投稿のエンドポイントURLは https://api.chatwork.com/v2/rooms/{room_id}/messages
なので
API送信先のエンドポイントには、 https://api.chatwork.com/v2/rooms/*/messages
を設定します。
続けてパスパラメータを上図のように $.body.roomId
と設定します。($.body
はSQSメッセージの構造です)
message
については入力トランスフォーマーで $.body.message
を body=message
というに出力に変換します。
以上で、SQSに投稿先のルームIDと投稿するメッセージを送信するだけでメッセージを投稿できます。
ノーコードで実現できました!
なお、API Destinationsはリトライ機構を持っていて設定により適切にリトライさせることが可能です。
リトライに失敗した場合は設定によりデッドレターキューに送ることもでき、後で再処理することも可能です。
CDK Construct
CDK Constructのコードを載せておきますのでご利用ください。Chatwork APIキーはSecretsに保存されている前提です。
RateLimitについては指定していませんので、必要に応じてChatworkNotificationProps
に追加してください。
import * as cdk from 'aws-cdk-lib'; import * as events from 'aws-cdk-lib/aws-events'; import * as iam from 'aws-cdk-lib/aws-iam'; import * as logs from 'aws-cdk-lib/aws-logs'; import * as pipes from 'aws-cdk-lib/aws-pipes'; import { Secret } from 'aws-cdk-lib/aws-secretsmanager'; import * as sqs from 'aws-cdk-lib/aws-sqs'; import { Construct } from 'constructs'; type ChatworkNotificationProps = { secretName: string; secretKey: string; }; export class ChatworkNotification extends Construct { public readonly queue: sqs.Queue; constructor(scope: Construct, id: string, props: ChatworkNotificationProps) { super(scope, id); const { secretName, secretKey } = props; this.queue = new sqs.Queue(this, 'ChatworkApiQueue', { visibilityTimeout: cdk.Duration.seconds(30), receiveMessageWaitTime: cdk.Duration.seconds(20), }); const connection = new events.Connection(this, 'ChatworkApiConnection', { authorization: events.Authorization.apiKey( 'X-ChatworkToken', Secret.fromSecretNameV2( this, 'ChatworkApiSecret', secretName, ).secretValueFromJson(secretKey), ), description: 'Connection to Chatwork API', }); const apiDestination = new events.ApiDestination( this, 'ChatworkApiDestination', { connection, endpoint: 'https://api.chatwork.com/v2/rooms/*/messages', }, ); const eventBridgePipesRole = new iam.Role(this, 'EventBridgePipesRole', { assumedBy: new iam.ServicePrincipal('pipes.amazonaws.com'), inlinePolicies: { ApiDestinationPolicy: new iam.PolicyDocument({ statements: [ new iam.PolicyStatement({ actions: ['events:InvokeApiDestination'], resources: [apiDestination.apiDestinationArn], }), ], }), }, }); this.queue.grantConsumeMessages(eventBridgePipesRole); // eslint-disable-next-line no-new new pipes.CfnPipe(this, 'SqsToApiDestination', { name: 'SqsToApiDestination', roleArn: eventBridgePipesRole.roleArn, source: this.queue.queueArn, sourceParameters: { sqsQueueParameters: { batchSize: 1, }, }, targetParameters: { httpParameters: { pathParameterValues: ['$.body.roomId'], }, inputTemplate: 'body=<$.body.message>', }, target: apiDestination.apiDestinationArn, logConfiguration: { cloudwatchLogsLogDestination: { logGroupArn: new logs.LogGroup(this, 'SqsToApiDestinationLogGroup', { retention: logs.RetentionDays.ONE_MONTH, }).logGroupArn, }, level: 'ERROR', }, }); } }
AWS Amplify Gen 2
BPaaSプロダクト開発ではAWS Amplify Gen 2を採用しています。我々がAWS Amplify Gen 2を選択した理由については下記の記事をご覧ください。
Amplify Gen 2はCustom resourcesやCloud sandboxという便利な仕組みを持っています。
先述のCDK ConstructをCustom resourcesとして定義してCloud sandboxを作成すれば簡単にデプロイできるのでオススメです。
Amplify BackendからChatworkへメッセージを投稿することもできるはずですが、未検証です。
まとめ
EventBridge Pipesを使ってノーコードでChatworkの任意のルームにメッセージを投稿することができました。 APIの利用回数制限があるため大量の通知を即時に投稿できるわけではないのでその点だけご留意ください。
記事は以上です。読んでいただきありがとうございました!