Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

いまさらですが 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 というメッセージを受け取ります。実用的とは言えなさそうですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away