LoginSignup
26
20

More than 3 years have passed since last update.

Boltを使ったSlack BotをTypescriptで開発する方法

Last updated at Posted at 2020-01-25

はじめに

今までslack用のbotを開発するのにhubotやerrbotを利用してきたのですが、昨年slackがリリースしたBoltフレームワークのチュートリアルをいくつかやってみて簡単にbot実装ができそうだなと思ったので、それをTypeScriptで実装する場合の方法を紹介します。

Bolt開発時に参考にしたサイト

Boltを使ったslack botアプリの作成方法や実装サンプルなどは、下記を参考にさせて頂きました。

開発環境

主に下記の開発環境で実装及び動作確認をしました。

Glitchは、ウェブ上で動くIDEを持っているのですが、ローカルでVSCodeを使うことでコード補完やESLintなども使えるようになるのでローカル環境でVSCodeを利用して実装します。

プロジェクトの作成

Bolt入門ガイドに記載のある通り、下記を実行しプロジェクトを作成します。

$ mkdir first-bolt-app
$ cd first-bolt-app
$ npm init -y
$ npm install @slack/bolt

typescript実装のために必要なパッケージをインストールします。

$ npm install -D typescript @types/node

その他ローカルで開発する上で利用するパッケージをインストールします。

$ npm install dotenv # .envファイルを読み込ませる為に追加
$ npm install -D eslint eslint-config-prettier eslint-plugin-prettier prettier @types/eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser

各種設定ファイルの作成

slackアプリのbot tokenとsigning secretを記載した.envファイルを作成します。

.env
SLACK_SIGNING_SECRET=<your-signing-secret>
SLACK_BOT_TOKEN=xoxb-<your-bot-token>

Typescriptプロジェクトをコンパイルするのに必要なコンパイラのオプションを指定するtsconfig.jsonファイルを作成します。

tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "target": "es6",
        "noImplicitAny": true,
        "moduleResolution": "node",
        "sourceMap": true,
        "outDir": "dist",
        "baseUrl": ".",
        "paths": {
            "*": [
                "node_modules/*",
                "src/types/*"
            ]
        }
    },
    "include": [
        "src/**/*"
    ]
}

ESLintの設定ファイル.eslintrc.eslintignoreを作成します。

.eslintrc
{
  "parser": "@typescript-eslint/parser",
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:prettier/recommended",
    "prettier/@typescript-eslint"
  ],
  "parserOptions": {
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "rules": {
    "semi": [
      "error",
      "always"
    ],
    "quotes": [
      "error",
      "double"
    ],
    "@typescript-eslint/explicit-function-return-type": "off",
    "@typescript-eslint/no-explicit-any": 1,
    "@typescript-eslint/no-inferrable-types": [
      "warn",
      {
        "ignoreParameters": true
      }
    ],
    "@typescript-eslint/no-unused-vars": "warn"
  }
}
.eslintignore
# /node_modules/* in the project root is ignored by default
# build artefacts
dist/*
coverage/*
# data definition files
**/*.d.ts
# 3rd party libs
/src/public/
# custom definition files
/src/types/

tscコンパイルやbot実行の為に、package.jsonを下記の通りに変更します。

package.json
{
〜省略〜
  "scripts": {
    "start": "npm run build && npm run serve",
    "build": "npx tsc",
    "serve": "node --require dotenv/config dist/app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
〜省略〜
}

コード作成と実行

ソースコードはsrc/以下に作成します。
下記はBolt入門ガイドの「メッセージのリスニングと応答」にあるコードをTypescriptコードにしたものです。
ファイル拡張子が.jsから.tsに変わったのとrequireをimport文に変えただけですね(笑)
もう少し複雑なサンプルコードを持ってくるとTypescriptの型エラーが発生し、適宜修正が必要になってきます。

src/app.ts
import { App } from "@slack/bolt";

const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET
});

// Listens to incoming messages that contain "hello"
app.message("hello", ({ message, say }) => {
  // say() sends a message to the channel where the event was triggered
  say(`Hey there <@${message.user}>!`);
});

(async () => {
  // Start your app
  await app.start(process.env.PORT || 3000);

  console.log("⚡️ Bolt app is running!");
})();

Typescriptのコードをコンパイルします。

$ npm run build

> first-bolt-app@1.0.0 build /Users/xxxx/first-bolt-app
> npx tsc

Javascriptに変換されたdist/app.jsが作成されます。

dist/app.js
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const bolt_1 = require("@slack/bolt");
const app = new bolt_1.App({
    token: process.env.SLACK_BOT_TOKEN,
    signingSecret: process.env.SLACK_SIGNING_SECRET
});
// Listens to incoming messages that contain "hello"
app.message("hello", ({ message, say }) => {
    // say() sends a message to the channel where the event was triggered
    say(`Hey there <@${message.user}>!`);
});
(() => __awaiter(void 0, void 0, void 0, function* () {
    // Start your app
    yield app.start(process.env.PORT || 3000);
    console.log("⚡️ Bolt app is running!");
}))();
//# sourceMappingURL=app.js.map

botを実行します。⚡️ Bolt app is running!が出力されれば成功です!

$ npm run serve

> first-bolt-app@1.0.0 serve /Users/xxxx/first-bolt-app
> node --require dotenv/config dist/app.js

⚡️ Bolt app is running!

コンパイルと実行を同時に行う場合は、npm run startを実行します。

$ npm run start

> first-bolt-app@1.0.0 start /Users/xxxx/first-bolt-app
> npm run build && npm run serve

> first-bolt-app@1.0.0 build /Users/xxxx/first-bolt-app
> npx tsc

> first-bolt-app@1.0.0 serve /Users/xxxx/first-bolt-app
> node --require dotenv/config dist/app.js

⚡️ Bolt app is running!

ここまで動作確認ができたらGlitchに作成したファイルアップすることでローカルマシンまでのトンネルするアプリの公開URLを用意できないと確認ができないslackからのevent受信などの確認もできるようになります。

アップするファイル一覧
first-bolt-app/
├── .env
├── package.json
├── src
│   └── app.ts
└── tsconfig.json

Glitch上でbotが起動するときは、npm run startが実行されるのでコンパイル済みのdist/app.jsはアップしなくても動作します。

おまけ

Bolt フレームワークを使って Slack Bot を作ろうの「Learn More」の「もうちょっと複雑な Glitch サンプル」をTypescript実装したソースコードは下記においてますので参考になれば、幸いです。

26
20
1

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
26
20