Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

設計

  • 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>

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

スクリーンショット 2020-02-25 17.23.36.png

今回、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のページで文章とあて先を入力して送信。

スクリーンショット 2020-02-25 18.23.34.png

そしてSlackに通知が来た。

スクリーンショット 2020-02-25 18.26.59.png

定期実行も確認

スクリーンショット 2020-02-25 18.30.11.png
スクリーンショット 2020-02-25 18.31.28.png

以上、実装完了とす。

感想

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

おわりに

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

Nive1928
rhems-japan
株式会社RHEMS JapanのR&Dを担い、IoTとサービス相互接続にフォーカス
https://labs.rhems-japan.co.jp/
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