NuxtとNode.jsサーバーでSlack通知実装


設計

  • NuxtベースアプリケーションからSlackに通知する機能を実装したい。
  • 定期的な自動再送機能もほしい。
  • トークンをNuxt側に置くのはちょっと...

そんな要件を満たすためには、Nuxtからサーバーを経由するのもありかなという感じで作成。

必要なもの

  1. Nuxtアプリケーション
  2. Node.js (当方Version 13.2.0)
  3. 設定済みSlack API (トークンとBot Token Scopesにてchat:write権限が必要。#generalに参加済み)

Nuxtでの実装

求められるものは
1. メッセージ入力
2. 宛先入力
3. 再送間隔 or 再送しないの入力
4. 設定内容のPOST

とりあえず上記の4つを実装すれば最低限機能は満たせそうなので書いていく。
見た目はこの際捨て置く。

またquerystringを使っているので未インストールなら

npm install --save querystring

以下、コード。

<template>
  <div class="create-post">
    <input type="text" v-model="message" id="message">
    <input type="text" v-model="channel" id="channel">
    <input type="text" v-model="schedule" id="schedule">
    <button v-on:click="send">
      送信
    </button>
  </div>
</template>

<script>
  import querystring from "querystring"
  export default {
    data() {
      return {
        message: '',
        channel: '',
        schedule: 'none'
      }
    },
    methods : {
      async send(){
        let json_data = {
          message: this.$data.message,
          channel: this.$data.channel,
          schedule: this.$data.schedule
        };
        const response = await this.$axios.$post('/test/rest', querystring.stringify(json_data));
      }
    }
  }
</script>

<style scoped>
  .create-post{
    width: 30%;
    height: 200px;
    padding-left: 200px;
  }
  #message{
    margin-top: 10%;
  }
  #channel{
    margin-top: 10%;
  }
  #schedule{
    margin-top: 10%;
  }
</style>

そうするとこのようなページが出来上がる

今回、NuxtからサーバーにPOSTするために@nuxtjs/axiosを使用している。
詳しくはご自分で調べてほしいのだが、使用する際、nuxt.confing.jsにて以下の文を編集・追加している。

  modules: [
    '@nuxtjs/axios',
  ],
  axios: {
    proxy: true
  },
  proxy: {
    '/test/': {
      target: 'http://0.0.0.0:3000/',
      pathRewrite: {'^/test/': ''}
    }
  },

このように設定することでCORSを簡単に解決することができる。
クロスオリジンリソースを共有するには?

サーバーの用意

サーバーでは次のような処理を行いたい。
1. HTTP Requestを受けとる
2. 中身のデータからメッセージとあて先、定期再送情報を取り出す
3. それに合わせてSlackに通知する

それではコードを書いていく。
これにあたって、以下の記事やサイトを参考にさせていただいた。
Nodejs HTTP/HTTPS サーバーとクライアントのコーディングパターン
【Node.js】Slack APIを使用してメッセージを送信する
Node.jsで定期実行メモ
node-cron npm
node-fetch npm

const http = require('http');
const fetch = require('node-fetch');
const cron = require('node-cron');
const queryString = require("querystring");
const StringDecoder = require("string_decoder").StringDecoder;
const Decoder = new StringDecoder('utf8');

let server = http.createServer();

async function postToSlack(token, msg, channel) {
    const { WebClient } = require('@slack/web-api');
    const client = new WebClient(token);
    const params = {
        channel: channel,
        text: msg
    };

    await client.chat.postMessage(params);
}

let tasks = [];
server.on('request', function (req, res) {
    req.on('data', async function(chunk) {
        let json = JSON.parse(JSON.stringify(queryString.parse(Decoder.write(chunk))));

        if (json.schedule === 'none') { //スケジュール指定がない場合
            await postToSlack('your token here', json.message, json.channel);
        } else { //ある場合
            let task = cron.schedule(json.schedule, async () => {await postToSlack('your token here', json.message, json.channel);});
            tasks.push(['start', task]);
        }

        let return_json = {
            state: true,
        };

        res.writeHead(200, {'Content-Type': 'application/json'});
        let replyData = queryString.stringify(return_json);
        res.write(replyData);
        res.end();
    });
});

server.listen(3000);

実際に試す

Nuxtのページで文章とあて先を入力して送信。

そしてSlackに通知が来た。

定期実行も確認


以上、実装完了とす。

感想

エラー処理を全く実装していないので怖い。
APIが用意されていると楽。
あとはSlackに限らず通知できるように拡張できそう。

おわりに

お読みいただきありがとうございました。なにか間違いがございましたらコメントへよろしくお願いします。