8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ノムリッシュ翻訳してくれるSlack bot(AWS lambda + APIGateway)

Last updated at Posted at 2019-02-28

はじめに

ノムリッシュ翻訳とは日本語の文章を野村ファイナルファンタジー風用語(意識高い系)に変換してくれるWebサービスです。
ノムリッシュ翻訳 -ファビュラ・ノヴァ・ノムリッシュ

例えば、

私の好きな食べ物はお寿司です。

をノムリッシュ翻訳すると、

私の好きな食べ物は指揮官専用機として開発したウォ・スシです。
そしてその手には それぞれクリスタルが握られていた・・・

のように面白おかしく変換してくれます。

また、こちらの機能がnpmモジュールとして公開されているので、こちらを使ってSlackでノムリッシュ翻訳してくれるSlack botを作ろうと思い、実際に作ってみました。
npm nomlish
ノムリッシュ翻訳ライブラリをnpmに公開しました

完成イメージ

"nomlish 文章"と投稿すると、文章を翻訳してくれます。
Slack_bot_img.png

構成

lambda + APIGatewayを使用して、APIを作成し、Slackから作成したAPIをコールしレスポンスを受け取ります。
Slack_bot_architecture.png

準備

  • Slack アカウント
  • AWSアカウント
  • Node.js(npmコマンド) が動作する環境

構築手順

コード

lambdaで実行させるコードを準備します。

  1. npm initコマンドで、Node.jsプロジェクトを作成
  2. 先ほど紹介したノムリッシュモジュールをnpm i nomlishコマンドでインストール
  3. プロジェクト直下にindex.jsを作成(下記参照)
  4. index.jsとnode_modulesフォルダをまとめてZip化
index.js

var nomlish = require("nomlish");
exports.handler = (event, context, callback) => {
  console.log(event.text);
  var planeText = event.text.replace("nomlish ", "");
  var beforeText = planeText.replace(/\r?\n/g, '');
  var res = {};
  res.username = "ノムリッシュ";
  nomlish.translate(beforeText, 3).then(function(nomlishText) {
    res.text = JSON.stringify(nomlishText);
    callback(null, res);
  })
};

こちらはリクエストから渡ってくる文章を成形し、nomlish.translate()で翻訳し、結果をJSONに直してレスポンスを返す処理になります。

lambda

準備したコードを動作させる環境を作成します。AWS lambdaは関数単位で実行できるサーバレスのフルマネージドサービスです。

  1. AWSコンソールにアクセスしてLambdaサービスを開く
  2. 一から関数を作成(デフォルトのまま特に細かい設定は必要ありません)
  3. 作成完了後、関数コード内、コードエントリタイプ「.zipファイルをアップロード」を選択し、先ほど作成したzipファイルをアップロード
    image.png

これでlambdaの準備が完了です。

APIGateway

先ほど作成したlambdaとAPIGatewayを使って、SlackからコールされるAPIを作成します。Amazon API GatewayはAPIの作成、管理ができるフルマネージドなサービスです。

  1. AWSコンソールにアクセスしてAPI Gatewayサービスを開く
  2. APIの作成(デフォルトのまま特に細かい設定は必要ありません)
    image.png
  3. 「アクション」>「メソッドの作成」を選択し、プルダウンから「POST」を選択する
    image.png
  4. -POST-セットアップの画面で、先ほど作成したLambda関数名を入力する
    image.png
  5. 「統合リクエスト」を選択し、マッピングテンプレートを開き、「リクエストの Content-Type ヘッダーに一致するテンプレートがない場合」を選択する。さらに、Content-Typeに「application/x-www-form-urlencoded」を入力し、下記コードを追加する
    image.png
## convert HTML POST data or HTTP GET query string to JSON

## get the raw post data from the AWS built-in variable and give it a nicer name
#if ($context.httpMethod == "POST")
 #set($rawAPIData = $input.path('$'))
#elseif ($context.httpMethod == "GET")
 #set($rawAPIData = $input.params().querystring)
 #set($rawAPIData = $rawAPIData.toString())
 #set($rawAPIDataLength = $rawAPIData.length() - 1)
 #set($rawAPIData = $rawAPIData.substring(1, $rawAPIDataLength))
 #set($rawAPIData = $rawAPIData.replace(", ", "&"))
#else
 #set($rawAPIData = "")
#end

## first we get the number of "&" in the string, this tells us if there is more than one key value pair
#set($countAmpersands = $rawAPIData.length() - $rawAPIData.replace("&", "").length())

## if there are no "&" at all then we have only one key value pair.
## we append an ampersand to the string so that we can tokenise it the same way as multiple kv pairs.
## the "empty" kv pair to the right of the ampersand will be ignored anyway.
#if ($countAmpersands == 0)
 #set($rawPostData = $rawAPIData + "&")
#end

## now we tokenise using the ampersand(s)
#set($tokenisedAmpersand = $rawAPIData.split("&"))

## we set up a variable to hold the valid key value pairs
#set($tokenisedEquals = [])

## now we set up a loop to find the valid key value pairs, which must contain only one "="
#foreach( $kvPair in $tokenisedAmpersand )
 #set($countEquals = $kvPair.length() - $kvPair.replace("=", "").length())
 #if ($countEquals == 1)
  #set($kvTokenised = $kvPair.split("="))
  #if ($kvTokenised[0].length() > 0)
   ## we found a valid key value pair. add it to the list.
   #set($devNull = $tokenisedEquals.add($kvPair))
  #end
 #end
#end

## next we set up our loop inside the output structure "{" and "}"
{
#foreach( $kvPair in $tokenisedEquals )
  ## finally we output the JSON for this pair and append a comma if this isn't the last pair
  #set($kvTokenised = $kvPair.split("="))
 "$util.urlDecode($kvTokenised[0])" : #if($kvTokenised[1].length() > 0)"$util.urlDecode($kvTokenised[1])"#{else}""#end#if( $foreach.hasNext ),#end
#end
}

設定が完了したら、APIをデプロイします。
6. 「アクション」>「APIのデプロイ」を選択し、「デプロイされるステージ」に[新たなステージ]を選択する
7. 「ステージ名」に適当な名前を入力し、「デプロイ」ボタンを押下する
image.png
8. デプロイが完了し、ステージエディター内にURLが表示される
image.png

以上でAPIGatewayの設定は完了です。

Slack

作成したAPIをSlackからコールする設定を行います。Outgoing Webhooksを使用するのですが、こちらは設定した言葉がトリガーとなって、SlackからPOSTのメソッドを送信し、指定した形式でJSONが返されると投稿してくれるものになります。

  1. サイドバーの「Apps」を押下、App Directory画面内の検索窓に「Outgoing WebHooks」と入力しOutgoing WebHooksの設定画面を開く
    image.png
  2. 「Add Configuration」を押して、今回作成する設定を追加する
  3. 各種設定する(今回使用するもののみ説明)
    image.png
    image.png
    Chanel:適用するチャンネルの選択
    Trigger Words(s):トリガーとなる言葉の設定、今回はnomulishを指定
    URL(s):API URLの設定、先ほどAPIGatewayで作成したURLを指定
    Customize Name:botが投稿する際の名前、ただし今回はAPIのレスポンスで名前を指定
    Customeize Icon:アイコンの指定
  4. 以上設定出来たら、「Save Settings」を押下、完成です!

雑談

実は当初、API部をGASで作成する予定でした。が、ノムリッシュのモジュールをバンドルするのに苦労して、今回の構成で作成することを決めました。こちらを応用すれば、天気を教えてくれるbotなども作れちゃいます!

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?