悩める恋心を助けるためのLINE Botを作ってみた

#はじめに

TwitterやLINEを始めとするSNSの発達によって
誰でも気軽に発言できるようになり、情報量過多のこの時代。
必要な情報を探せなかったり、デマに流されたりすることも往々にしてあります。
私たちは膨大な情報の中から、真実を見極める力が求められていると言っても過言ではありません。

ときに、LINEやメールなどで気になっている人とやり取りをしていて、
これって脈あるの？ないの？と頭を悩ませることもあるはず。
そこで今回は相手に脈があるかどうかを判別する「脈アリ診断bot」を実装しました。


#概要

■使ったもの
・Node.js v12.3.1
・LINE Message API
・GCP Natural Language API

■フロー図
全体はNode.jsで制御し、LINEにメッセージが入力されたら、
Natural Language APIのsentiment分析で文章のスコアが返ってくるような仕組みです。

![スクリーンショット 2019-06-20 0.12.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248994/0a174c54-472a-0405-181d-b9e474510629.png)

■実装にあたり

こちらを参考にしました↓
・<a href="https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d">1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest</a>
・<a href="https://cloud.google.com/natural-language/?hl=ja">Natural Language API</a>

#使い方
①Botの対話画面で任意のテキストを送る
②テキストの内容によってスコアが返る。
　※スコアは -1.0（ネガティブ）～1.0（ポジティブ）のどれかが返ってきます。
③スコアによって脈アリ判定文が表示される

■使ってみた
![スクリーンショット 2019-06-19 23.19.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248994/96e49439-e787-1479-1e93-77d31f5302b1.png)

匂わせ系も判別していこう
![スクリーンショット 2019-06-20 1.15.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248994/c61feaec-0d49-5f09-735f-bb189424e01b.png)

■おまけ
メンヘラ風なやつ
![スクリーンショット 2019-06-20 0.38.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248994/adde99d6-b976-7664-ea5f-dcb65a43cf06.png)

#サンプルコード
```node.js：server.js
'use strict';

const language = require('@google-cloud/language');
const express = require('express');
const line = require('@line/bot-sdk');
const axios = require("axios");
require("dotenv").config();

const PORT = process.env.PORT || 3000;
const config = {
  channelAccessToken: process.env.YOURTOKEN,
  channelSecret: process.env.YOUR_SECRET,
};

const app = express();
const client_line = new line.Client(config);
const client_lang = new language.LanguageServiceClient();

let eva = 0;

// 応答処理
const Analyze = async (text,event,userId) => {
  let replyText = "";
  const document = {
    content: text,
    type: 'PLAIN_TEXT',
  };

  client_lang
  .analyzeSentiment({document: document})
  .then(results => {
    const sentiment = results[0].documentSentiment;
    pushText(`スコア: ${rounding(sentiment.score)}`,userId);
    evalResult(sentiment.score,userId)
  })
  .catch(err => {
    console.error('ERROR:', err);
  });
}

// 有効数字の処理
const rounding = (num) =>{
  return Math.floor(num * 10)/10;
}

// テキスト送信処理
const pushText = (mes,userId) => {
  client_line.pushMessage(userId,{
    type: "text",
    text: mes,
  })
}

// 判定内容送信。ここカスタマイズすればいろいろアレンジできます

const evalResult = (num,userId) => {
  let opinion = 1;
  if(num >= 0.8){
    opinion =  "脈アリ間違いなし！\u{100078}\u{100033}"
  }else if(num >= 0.4){
    opinion =  "希望はあるよ\u{10008F}";
  }else if(num >= 0){
    opinion =  "まだ様子見しよう\u{10002E}\u{100031}";
  }else if(num <= -0.6){
    opinion =  "これは脈ナシ…\u{10007D}";
  }else{
    opinion = "ちょっと怪しいかも\u{10007B}";
  }
  setTimeout(() => {
    client_line.pushMessage(userId,{
      type: "text",
      text: opinion,
    })
  },2000);
}

// メッセージ入力
const handleEvent = (event) => {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }
  const sentText = event.message.text;
  const userId = event.source.userId;
  let message = "";

  if(event.message.text !== ""){
    message = `「${sentText}」の脈を測ります`;
    Analyze(sentText,event,userId);
  }

  return client_line.replyMessage(event.replyToken, {
    type: 'text',
    text: message
  });
}

app.post('/webhook', line.middleware(config), (req, res) => {
  console.log(req.body.events);
  Promise
  .all(req.body.events.map(handleEvent))
  .then((result) => res.json(result));
});

app.listen(PORT);
console.log(`Server running at ${PORT}`);
```

#最後に
LINEbotはハンズオンの記事を見ながら作ったが、意外と簡単に作れて楽しかった。
GCPのNatural Language APIの認証周りで少し手こずったが、<a href="https://cloud.google.com/natural-language/docs/auth?hl=ja">このあたり</a>をみて解決。

あとは、意外と解析の精度が高いなという印象。
ある程度長くても問題なく数値が返ってきます。

同じようなAPIでAzureのtext analytics APIがあるが、
こちらは日本語対応していなかったので、GCPを使うことにした。
Azureの場合は一回翻訳API噛ませないとダメな気がする。

また他のLINEボット作ってみます。