Slackのメッセージショートカットからgithub issueを作成するアプリ

#Slack Message APIを使ってmessage-shortcut からissue作成

###今回は自分が前回作成した[Slack message APIを用いたGithub issue作成ショートカット](https://qiita.com/takaya787/items/931d7f2531c95ab70f48 "previous-article")のコード内容について書いていきます。
基本的部分はslackのmessage APIの[Slack チュートリアル](https://api.slack.com/lang/ja-jp/actions "message-API")から引用しています。
**全コードはこちらのGlitchから確認ください。** https://glitch.com/edit/#!/slack-create-issue-pub 
**Glitchからremixをすることで、簡単に実装することが可能です。**
**実装の手順はこちらのページに書いています　**
[Slack message APIを用いたGithub issue作成ショートカット](https://qiita.com/takaya787/items/931d7f2531c95ab70f48 "previous-article")
**開発環境:　node.js: v10.15.3, javascript**
**使用ツール: Glitch**

今回のメインのファイルは`index.js`,`confirmation.js`,`gitissue.js`,`verifySignature.js`,`.env`の以上5つのファイルで、他のファイルは環境構築用です。
`verifySignature.js`については一切 [Slack チュートリアル](https://api.slack.com/lang/ja-jp/actions "message-API") と変わらないので、割愛します。
`index.js`ファイルには、slack APIからactionを受け取り、そのactionのtypeによって行動を選択して実行しています。
今回のshortcut用のformを作成して、shortcut ボタンが押されたら、それが表示されるように設定します。

```js:index.js
const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
const qs = require('qs');
const app = express();

const apiUrl = 'https://slack.com/api';
const rawBodyBuffer = (req, res, buf, encoding) => {
  if (buf && buf.length) {
    req.rawBody = buf.toString(encoding || 'utf8');
  }
};

app.use(bodyParser.urlencoded({verify: rawBodyBuffer, extended: true }));
app.use(bodyParser.json({ verify: rawBodyBuffer }));

/*
/* Endpoint to receive an action and a dialog submission from Slack.
/* To use actions and dialogs, enable the Interactive Components in your dev portal.
/* Scope: `command` to enable actions
 */
/* ここでshortcuｔ用のmodalを送信しています。*/
app.post('/actions', (req, res) => { 

  const payload = JSON.parse(req.body.payload);
  const { type, user, view } = payload;  
  
  console.log(JSON.parse(req.body.payload));
  


  // Message action triggered
  if(type === 'message_action') {
 
    // Open a modal with the selected message pre-populated
    openModal(payload).then((result) => {
      if(result.data.error) {
        console.log(result.data);
        res.sendStatus(500);
      } else {
        res.sendStatus(200);
      }
    }).catch((err) => {
      res.sendStatus(500);
    });
  }  else if(type === 'view_submission') {
     //ここにformを提出後の処理を書き足します。 
  }   
});
/* 表示されるフォームをここで定義します */

const openModal = async(payload) => {
  
  const viewData = {
    token: process.env.SLACK_ACCESS_TOKEN,
    trigger_id: payload.trigger_id,
    view: JSON.stringify({
      type: 'modal',
      title: {
        type: 'plain_text',
        text: 'Create a github issue'
      },
      callback_id: 'create-issue',//登録したアプリのcall back IDを入力
      submit: {
        type: 'plain_text',
        text: 'Create'
      },
      //blockにinputする内容を決定　今回はGithub issue作成に必要なtitleとbody
      blocks: [
        {
          block_id: 'title',
          type: 'input',
          element: {
            action_id: 'title_id',
            type: 'plain_text_input',
            multiline: true,
            initial_value: ""
          },
          label: {
            type: 'plain_text',
            text: 'Issue Title'
          }
        },
        {
          block_id: 'body',
          type: 'input',
          element: {
            action_id: 'body_id',
            type: 'plain_text_input',
            multiline: true,
            /*Slack APIがMessage shortcutを通して、送られてきたmessageデータを
              payloadから取り出しinitial_valueに設定します。　*/
            initial_value: payload.message.text
          },
          label: {
            type: 'plain_text',
            text: 'Issue Body'
          }
        }
      ]
    })
    await axios.post(`${apiUrl}/views.open`, qs.stringify(viewData));
    //console.log(result.data);
};
const server = app.listen(process.env.PORT || 5000, () => {
  console.log('Express server listening on port %d in %s mode', server.address().port, app.settings.env);
});
```
###次はform提出に関する実行をします###

次にformをsubmitした後の処理をそれぞれ定義します。
この処理は大きく２つになります。

+ 確認用のmessageをbotから送信(`confirmation.js`)
+ formのtitle,bodyの情報でgithub APIからissueを作成する(`gitissue.js`)

それぞれの処理は各ファイルで定義して、`index.js`にimportする形にしています。
**確認用のmessageをbotから送信(`confirmation.js`)**

``` js:confirmation.js
// slackへのform送信はaxiosとqsを用いて行います。
const axios = require('axios');
const qs = require('qs');

const apiUrl = 'https://slack.com/api';
/*送信用formatを用意し、(userId,view）を引数に設定しています。　
 slackではsubmit後にviewにtextデータを追加して送信してくれるので、それをそのまま引数に設定しています。*/

const sendConfirmation = (userId, view) => {
  let values = view.state.values;

  let blocks = [
    {
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: 'issue was created successfully!\n\n'
      }
    },
    {
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: `*title*\n${values.title.title_id.value}`
      }
    },
    {
      type: 'section',
      text: {
        type: 'mrkdwn',
        text: `*Message*\n${values.body.body_id.value}`
      }
    },
  ];

  let message = {
    token: process.env.SLACK_ACCESS_TOKEN,
    channel: userId,
    blocks: JSON.stringify(blocks)
  };

  axios.post(`${apiUrl}/chat.postMessage`, qs.stringify(message))
  .then((result => {
    console.log(result.data);
  }))
  .catch((err) => {
    console.log(err);
  });
}
module.exports = { sendConfirmation };
 ```
###次にgithub APIを用いてissueを作成します###
**formのtitle,bodyの情報でgithub APIからissueを作成します。(`gitissue.js`)**

```js:gitissue.js
//今回はissue作成でRESTfull APIでのissue作成を簡略化してくれる　octokitを使用します
const { Octokit } = require("@octokit/rest");
const GITHUB_ACCESS_TOKEN = process.env.GITHUB_ACCESS_TOKEN;
// octokitインストールにPersonal_Access_Tokenを代入することでOAuth2認証を行えます。
const octokit = new Octokit({
  auth: GITHUB_ACCESS_TOKEN
});

const sendOctokit = (view) => {
  let values = view.state.values;
//viewデータで送られてきた情報を取得します
  let initialdatas = {
    title: values.title.title_id.value,
    body: values.body.body_id.value ,
  };
  //octokintでのissue作成
  octokit.issues.create({
    owner: 'git-owner',//ここにowner名　git-owner
    repo: 'git-repo',//ここにrepo名　git-repo
    title: initialdatas.title,
    body: initialdatas.body,
  }).then(({data}) => {
    console.log(data);
  }).catch(error => {
    console.log(error);
  }); 
}

module.exports = { sendOctokit };
```
以上でsubmit後の処理のコードは完成です
後はこれらを`index.js`にimportして、formを提出後の処理を記入する場所に追加します。

```js:index.js
const confirmation = require('./confirmation'); //confirmation.js利用のため
const gitissue = require('./gitissue'); // gitissue.js利用のため

if(type === 'message_action') {
  //......
} else if(type === 'view_submission') {
  //form提出後の処理を書く
  res.send(''); // Make sure to respond immediately to the Slack server to avoid an error
  gitissue.sendOctokit(view);// gitissue.jsからimport
  // DM the user a confirmation message
  confirmation.sendConfirmation(user.id, view);// confirmation.jsからimport
}
```
以上でアプリのcode部分は完成です。