WeChatとは、主に中国を中心に利用されているメッセージングアプリです。
Wikipediaからの引用ですが、
2015年2月の同社発表によると登録ユーザー数は11億2,000万人(以降、テンセントは登録ユーザー数を公表していない)。また、20以上の言語版があり、200の国と地域をカバー、70を超える国と地域でナンバーワンのソーシャルアプリであるという[7]。2016年第1四半期における月間アクティブユーザー数が7億6,200万人に到達し、前期比29%増であると発表された[8]。
https://ja.wikipedia.org/wiki/%E5%BE%AE%E4%BF%A1
とあり、とても多くのユーザーに利用されています。
こんなWeChatのbot作成を試してみました。
🖥 利用したもの
WeChat botには色んなプログラミング言語のライブラリがありますが、今回はNode.jsで作成しました。
- Node.js : v10.14.1
- yarn : v1.12.3
- ngrok : v2.2.8
yarnはnpmの代わりに利用できるライブラリマネージャーツールです。
コマンドが違うだけで、どちらも同じように利用できるので、npmをご利用の方はコマンドを置き換えて使用してください。
Ngrokはローカル環境で起動したサーバーを簡単に外部公開できるサービスで、こちらのブログで詳しく書いています。
本番用にbotを起動させておく場合は、Herokuなどのサービスを利用するか、クラウド環境などにおいてしまうのがいいかと思います。
syobochim.hatenablog.com
✏️ botの作り方
Node.js初心者なので、違うぞと言うところは教えていただけると嬉しいです。
✏️ ディレクトリを初期化する
yarnコマンドを利用してディレクトリを初期化します。
対話形式で回答していくと、パッケージ管理のためのpackage.jsonが出来上がります。
適当にこんな感じで入力しました。
$ yarn init yarn init v1.12.3 question name (wechat-bot): question version (1.0.0): question description: question entry point (index.js): question repository url: question author: syobochim question license (MIT): question private: success Saved package.json ✨ Done in 39.71s.
✏️ パッケージのインストール
WeChat連携用のライブラリにはこちらを利用しました。
GitHub - node-webot/wechat: 微信公共平台消息接口服务中间件
開くとREADMEが中国語で書かれていてびっくりしますが、ちゃんと英語のドキュメントもあります!
wechat/README.en.md at master · node-webot/wechat · GitHub
また、Node.jsのWebフレームワークであるexpressも使います。
Express - Node.js Web アプリケーション・フレームワーク
$ yarn add wechat $ yarn add express
出来上がったpackage.jsonに起動用のscriptを記載しておきましょう。
こんなファイルになるかと思います。
{ "name": "wechat-bot", "version": "1.0.0", "main": "index.js", "author": "syobochim", "license": "MIT", "dependencies": { "express": "^4.16.4", "wechat": "^2.1.0" }, "scripts": { "start": "node ." } }
✏️ index.jsを作ろう
では、チャットボットを作成していきます。
最小のサンプルはこんな感じ。
どんなことを話しかけても「Hello」と返すbotが出来上がります。
appidとtokenは書き換えてください。設定する値については後述します。
const express = require('express'); const wechat = require('wechat'); const port = 3000 const app = express(); const config = { token: 'token', // tokenを書き換える appid: 'appid' // appidを書き換える } app.use(express.query()); app.use('/wechat', wechat(config, function (req, res, next) { var message = req.weixin; // チャットボットに話しかけた内容を受け取る console.log(message); res.reply('Hello'); // チャットボットの返答内容を取得する })); app.listen(port, () => console.log(`listening on port ${port}!`));
appidとtokenを書き換えよう
appidはWeChatのbotアカウントページに表示されているので、それを利用してください。
また、tokenは自分で任意の値をWebのアカウントページを設定し、それをindex.jsにも記載します。
アカウントページについてはこちらのブログに書いています。
7億人以上に利用されているWeChatのbotを作る〜テスト用アカウント編〜 - そこに仁義はあるのか(仮)
✏️ サーバーを起動しよう
package.jsonに起動コマンドを書いておいたので、起動はこのコマンドでOKです。
これを実行すると、3000番ポートでアクセスできるチャットアプリがローカル環境で起動します。
$ yarn start
しかし、このままでは外の環境からアクセスできません。
なので、ngrokを利用して外部からアクセスできるようにしましょう。
ngrokのインストール方法についてはこちらに書きました。
ローカルで起動したサーバーを簡単に外部公開できるngrokと活用方法 - そこに仁義はあるのか(仮)
$ ngrok http 3000
起動に成功すると、こんな感じで表示されます。
Forwardingに表示されているのが外部からアクセスできるURLです。
✏️ チャットボットを設定しよう
最後にアカウントページにngrokで表示されたURLを設定すれば、チャットボットの完成です。
✏️ テスト用のアカウントをWeChatアプリから呼び出そう
サイトを下にスクロールするとQRコードが表示されています。
このQRコードを、テスト用アカウントのサイトにログインした時と同じ手順でWeChatアプリからQRコードスキャンします。
そうすると、テスト用のアカウントが友達としてWeChatアプリに登録され、ボットとコミュニケーションを取ることができます!
✏️ botをカスタマイズしよう
全ての発言に対して「Hello」と返すだけでは、チャットボットとしては不十分ですね。
index.jsの「var message = req.weixin;」で、messageを以下のように受け取ります。
Contentには、ユーザーから入力された文字列が、MsgTypeにはメッセージ形式が、FromUserNameにはユーザーを示す一意の英数字が表示されているので、
会話の内容に応じてチャットボットをカスタマイズできます。
{ ToUserName: 'xxxxxx', FromUserName: 'yyyyyyyyyyyyy', CreateTime: '1545811781', MsgType: 'text', Content: 'Hi', MsgId: '6639211045614684453' }
チャットに話しかけられた内容を利用する場合はmessageを取得した後にContentを取得すればOKです。
var message = req.weixin; var content = message.Content;
会話内容を取得できれば、内容に応じたカスタマイズができますね!
例えば、郵便番号を入力して住所を返すチャットボットを作成する場合はこんな感じ。(汚い…)
パッケージに'request'と'xml2js'を追加してindex.jsをこんな感じに変更する。
...(略)... const request = require('request'); const parseString = require('xml2js').parseString; ...(略)... app.use(express.query()); app.use('/wechat', wechat(config, function (req, res, next) { var message = req.weixin; var zipcode = message.Content; // チャットに話しかけられたメッセージ内容をzipCodeとして取得する const options = { url: 'http://zip.cgis.biz/xml/zip.php', qs: { zn : zipcode } }; request.get(options, function(error, response, body){ parseString(body, function (err, result) { try { var state = result['ZIP_result']['ADDRESS_value'][0].value[4]['$'].state; var city = result['ZIP_result']['ADDRESS_value'][0].value[5]['$'].city; res.reply(state + city); } catch (e){ res.reply('よくわかりません'); } }); }); }));
完成するとこんな感じになります。