11
1

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.

Fringe81Advent Calendar 2018

Day 11

Runkit で作るお手軽サーバレス Slack App

Posted at

いまさらですが Runkit で Slack の投票アプリを作ってみました。なんとサーバレス&DBレスです。
Selection_092.png
この記事ではこの投票アプリの作り方を紹介します。
(Runkit を知らない人は Runkit で作るお手軽サーバレス Web API からどうぞ)

実装コード

Runkit で雑に Notebook を作って以下のコードをコピペしましょう

const express = require("@runkit/runkit/express-endpoint/1.0.0");
const bodyParser = require("body-parser");
const { createMessageAdapter } = require("@slack/interactive-messages")

const SLACK_TOKEN = 'xxxxx';

const app = express(exports);
const slackInteractions = createMessageAdapter(SLACK_TOKEN);

//
// Interactive Message の内容
// 
const interactiveButtons = (text, userName) => ({
  text: `A new polling incoming :raised_hand: by @${userName}`,
  response_type: 'in_channel',
  attachments: [
    {
      text,
      color: '#3AA3E3',
      callback_id: 'yesno_polling',
      actions: [{
        name: 'yesno_polling',
        text: 'Yes! :ok_woman:',
        value: 'yes',
        type: 'button',
        style: 'primary',
      }, {
        name: 'yesno_polling',
        text: 'No :woman-gesturing-no:',
        value: 'no',
        type: 'button',
        style: 'danger',
      }]
    }, {
      color: '#32cd32',
      title: ':ok_woman:',
      callback_id: 'yes_users',
      text: '',
    }, {
      color: '#ff0000',
      title: ':woman-gesturing-no:',
      callback_id: 'no_users',
      text: '',
    }
  ]
});

//
// *上の Interactive Message に対応するハンドラ*
// 
// 投票が被ってしまわないよう自分の既存の選択を一度リセットしたうえで再び該当する選択肢にアサインする
//
slackInteractions.action('yesno_polling', (payload, respond) => {
  const originalMessage = payload.original_message;
  const resetOwnVoting = (text, userName) => (text || '').replace(`@${userName}`, '');
  
  const yesUsers = 
    originalMessage.attachments[1].text =
    resetOwnVoting(originalMessage.attachments[1].text, payload.user.name);
    
  const noUsers = 
    originalMessage.attachments[2].text =
    resetOwnVoting(originalMessage.attachments[2].text, payload.user.name);
  
  switch (payload.actions[0].value) {
    case 'yes':
      originalMessage.attachments[1].text = (yesUsers + ` @${payload.user.name}`);
      break;
    case 'no':
      originalMessage.attachments[2].text = (noUsers + ` @${payload.user.name}`);
      break;
  }

  return originalMessage;
});

//
// Slash Command のリクエストハンドラ
//
const SLACK_ACTION_PATH = '/slack/actions'
const SLACK_COMMANDS_PATH = '/slack/commands'

app.use(bodyParser.urlencoded({ extended: false }));
app.use(SLACK_ACTION_PATH, slackInteractions.expressMiddleware());
app.post(SLACK_COMMANDS_PATH, (req, res, next) => {
  const pollingText = req.body.text;
  const userName = req.body.user_name;
  
  if (pollingText) {
    res.send(interactiveButtons(pollingText, userName));
  } else {
    res.send('_No polling text. That\'s required_');
  }
});

DBレスと書きましたが、実際には投票結果の文字列をデータソース代わりに無理やり使っているだけのマヤカシです:tired_face:

Interactive message buttons の詳しい使い方はここで説明すると大変なのでしません。

ただ、とりあえず実装には slackapi/node-slack-interactive-messages を使っておくのが良いと思います。今回も使いましたが、めちゃ簡単に作れました。

あとは Endpoint から、この Notebook をAPIとして利用するためのURLを取得して、どこかにメモっておきましょう。
Selection_093.png

アプリの作成

Slack App の登録ページから、新しく自分の Slack App を作成しましょう。
まずは App Name に好きな名前を指定してください。
Selection_094.png

Interactive Components

Interactivity を有効化して、その下にある Request URL に Notebook から取得した API の URL に /slack/actions のパスを付加したものを指定しましょう。
Selection_095.png

Slash Commands

僕らのアプリはスラッシュコマンドで起動できるようにしましょう。
まずは Create New Command から新しいスラッシュコマンドを作成します。
Selection_096.png

Command にはスラッシュコマンドとして指定したい文字列を指定します。
Request URL には Interactive Components でやったように Notebook から取得した URL の末尾に /slack/commands を付加したものを指定しましょう。
Selection_097.png

ベリフィケーション・トークンの設定

Basic Information のページから、ベリフィケーション・トークンというのものをコピーして、上で出てきた実装コードの中にある SLACK_TOKEN に代入するよう書き換えて下さい。
Selection_098.png
ちなみにこれは秘密のものなので、もし誰かにバレてしまったら Regenerate から再生成しましょう。僕はここでおっぴろげに公開してしまったので、たったいま再生成しました:ok_hand:

アプリ情報の設定

ベリフィケーション・トークンを取得する画面をもうちょっと下にいくと、アプリ情報を指定できるところがありますね。
ここからアイコンを設定すると、もっとカッコよくできます。僕はとりあえず手元にあったプーマのかっこいいスニーカーをアイコンに指定してみました。カッコいいですね。
Selection_100.png

ワークスペースへのインストール

ここまででほぼ準備は終わりです!!
さっそくワークスペースにインストールしましょう
Selection_099.png

使ってみる

mypoll コマンドで投票アプリくんに投票をつくってもらうことができます。
Peek 2018-12-11 00-10.gif
これでいつでも二択の決選投票を楽しめますね。

問題点

使っていると、わりと頻繁に Runkit 側から Timeout was reached というメッセージを受け取ります。実用的とは言えなさそうですね。

11
1
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
11
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?