AWS SAMでSlackにメッセージを投稿するアプリを作る

Slackにメッセージを送信する仕組みを使い回せるように作りたかったので、SAM触るついでにざっくりと組んでみました。 Slackのtoken取得 Slack APIから取得します。[Start Building]をクリ […]

広告ここから
広告ここまで

目次

    Slackにメッセージを送信する仕組みを使い回せるように作りたかったので、SAM触るついでにざっくりと組んでみました。

    Slackのtoken取得

    Slack APIから取得します。[Start Building]をクリックしましょう。

    ワークスペースとアプリ名を聞かれるので、入力します。ログインしてないワークスペースは表示されないので、ログインしてからリトライします。

    アプリの基本設定

    [Basic Information]で諸々設定画面でてきます。Add features and functionalityでは、[Permissions]を選択しましょう。すると[OAuth & Permissions]というページに移動します。[Scopes]でchat:write:botchat:write:userを追加しましょう。

    [Save Changes]をクリックすると、[Install App to Workspace]がアクティブになるので、有効化します。認証画面に遷移するので、内容を確認してAuthorizeしましょう。

    このあとOAuth Access Tokenが表示されているのを確認したら、事前準備は完了です。

    SAMでスタックを準備する

    続いてSlackへの投稿処理を実行するバックエンドを用意します。最低限必要なファイルは以下のようにして準備しておきます。

    $ mkdir slack-lambda && cd slack-lambda
    $ npm init -y
    $ touch index.js template.yml

    Slack SDK(Node.js)をインストール

    $ npm i -S @slack/client

    CloudFormationを書く

    SAMでリソースの定義を書きます。SlackのトークンとチャンネルをLambda内に環境変数で入れるようにして、使い回せるようにしておきましょう。

    AWSTemplateFormatVersion: '2010-09-09'
    Transform: AWS::Serverless-2016-10-31
    Description: 'Post message to Slack'
    Resources:
      HelloSAM:
        Type: AWS::Serverless::Function
        Properties:
          Handler: index.handler
          Runtime: nodejs6.10
          Environment:
            Variables:
              SLACK_TOKEN: !Ref SlackToken
              SLACK_CHANEL: !Ref SlackChanel
    Parameters:
      SlackToken:
        Type: String
      SlackChanel:
        Type: String

    Lambdaのソースを書く

    あとは実行する処理をまとめます。

    const { WebClient } = require('@slack/client')
    
    const handler = (event, context, callback) => {
      const { SLACK_TOKEN, SLACK_CHANEL } = process.env
      if (!SLACK_TOKEN || !SLACK_CHANEL) return callback(new Error('slack token or channel is undefined'))
      const { message, attachments } = event
      if (!message) return callback(new Error('Message is undefined.'))
    
      const web = new WebClient(SLACK_TOKEN)
      const param = {
        channel: SLACK_CHANEL,
        text: message
      }
      if (attachments) param.attachments = attachments
      web.chat.postMessage(param)
        .then((res) => {
          return callback(null, {
            event,
            result: res.ts
          })
        })
        .catch(error => {
          console.log(error)
          return callback(error)
        })
    }
    
    module.exports.handler = handler

    SAMでAWSにデプロイする

    以下の3ステップでデプロイします。(2回目からはaws s3 mbは不要)。3 つ目のコマンドで、はじめに取得したtokenと投稿を送るチャンネルを指定しましょう。

    # デプロイバケットの作成
    $ aws s3 mb s3://YOUR_ORIGINAL_BUCKET_NAME --region us-east-1
    
    # デプロイパッケージの作成
    $ aws cloudformation package --template-file ./template.yml --output-template-file template-output.yml --s3-bucket YOUR_ORIGINAL_BUCKET_NAME
    
    # デプロイ
    $ aws cloudformation deploy --template-file ./sam-output.yml --stack-name hello-sam --region us-east-1 \
     --parameter-overrides SlackToken='xoxa-xxxxxxxxxx' SlackChanel='#random'

    Lambdaを実行する

    あとは実行するだけです。

    # Lambdaのfunction名を探す
    $ aws lambda list-functions --region us-east-1 | jq '.Functions[].FunctionName' | grep sam
    "hello-sam-HelloSAM-XXXX"
    
    # Lambdaの実行
    $ aws --region us-east-1 lambda invoke --function-name "hello-sam-HelloSAM-XXXX" --payload '{"message": "hello"}' result.json && cat result.json | jq .
    {
        "StatusCode": 200
    }
    {
      "event": {
        "message": "hello"
      },
      "result": "1525754269.000138"
    }
    
    ## リッチな投稿版
    $ aws --region us-east-1 lambda invoke --function-name "hello-sam-HelloSAM-XXXXX"  --payload '{ "message": "hello slack",
       "attachments": [
         {                                                              
           "fallback": "Required plain-text summary of the attachment.",
           "color": "#36a64f",
           "author_name": "Bobby Tables",
           "author_link": "https://flickr.com/bobby/",
           "author_icon": "https://flickr.com/icons/bobby.jpg",
           "title": "Slack API Documentation",
           "title_link": "https://api.slack.com/",
           "text": "Optional text that appears within the attachment",
           "fields": [
             {                     
               "title": "Priority",
               "value": "High",
               "short": false
             }
           ],                                                     
           "image_url": "https://my-website.com/path/to/image.jpg",
           "thumb_url": "https://example.com/path/to/thumb.png",
           "footer": "Slack API",                                                            
           "footer_icon": "https://platform.slack-edge.com/img/default_application_icon.png",
           "ts": 123456789
         }
       ]
     }' result.json && cat result.json | jq .
    

    こんな感じで投稿されるようになります。

    今後とか

    自分でなにかSlackにメッセージ飛ばしたくなった時に「とりあえずこのLambdaければいいよ」というのがあれば楽かなというので作りました。

    SAMだとAWS Serverless Application Repositoryに登録して簡単にデプロイできるようにすることもできるみたいなので、時間があればそちらも試してみます。

    ソースコード

    GitHubにおいてます。

    https://github.com/hideokamoto/lambda-to-slack

    SAM詳しい人とか、フィードバックくださいm(_ _)m

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark