話しかけるとカラアゲの画像を返すSlackbotを作った
鳩に「からあげ」的なことを言うと、からあげの写真を拾ってきて返すクレイジーなbotを作ったのでメモ。
googleの画像検索でもよかったんだけど、SearchAPIの縛りがめんどくさいしスクレイピングする気力もなかったので拾ってくる元はFlickrにしました。
用意するもの
- Node.js
- Botkit
- NodeのflickrAPIモジュール
- Flickrのアカウント
- Slackのアカウント
- 鳩の画像
Botkitの用意をする
こちらの記事を参考に、さくっとBotkitを導入します。
画像に鳩を設定して、名前をdove(野鳩)にしました。
Flickrのアクセストークンを取得する
Flickrのアカウント持ってる開発用のアクセストークンが発行できるので、もそっと作ります。
1アプリケーションにつき1トークンじゃないとだめだよ!とか言ってるので気をつけましょう。
ドキュメントページやらトークンの発行ぺーじやらがわかりにくいのでこちらを参考に。 syncer.jp
flickrAPIモジュールでもごもごする
ここからが本題。
flickrapiをnpm install
して使います。
Botkitのbot.jsにいろいろ追記。
controller.hears(['からあげ', '唐揚げ', 'カラアゲ', 'から揚げ'], 'direct_mention', function(bot, message) { var Flickr = require("flickrapi"); var flickrOptions = { api_key: "APIキーを入れる", secret: "シークレットキーを入れる" }; Flickr.tokenOnly(flickrOptions, function(error, flickr) { flickr.photos.search({ text: 'からあげ', color_codes: 1, media: 'photos', per_page: 100, safe_search: 1, extras: 'url_z' }, function(err, result) { var photos = result.photos.photo; var r = Math.floor(Math.random() * photos.length); bot.reply(message, 'クルッポー' + photos[r].url_z); }); }); });
「からあげ」的な発言の入ったmentionに反応します。
どうやらAPIにアクセスする方法が2種類あるっぽいのですが、今回は写真の取得ができればいいのでtokenOnly
で使います。
検索のオプションをいろいろ設定すると、JSのオブジェクトで返ってきます。
ランダムで1件取得、とかは出来ないので100件取ってきて1件抽出します。
最終的に鳩にテキスト(クルッポー)と画像URLをreplyさせて完成。
で、ただ喋らせるのもつまらないので、呼び出し元の発言にから揚げのアクションを付けます。
bot.api.reactions.add({ timestamp: message.ts, channel: message.channel, name: 'poultry_leg', },function(err, res) { if (err) { bot.botkit.log('Failed to add emoji reaction :(',err); } });
※から揚げがなかったので骨付き肉になりました。
Flickrにアクセスするたびに認証をさせられる件
で、コード自体は動くのですがいちいち謎の認証をさせられるようになりました、うざい。
ちょっとよくわからないんですが、Flickrのアクセストークンの種類をWeb ApplicationからDesktop Applicationに変更したら事なきを得ました。
登録済みのアプリ→編集から変更できます。ページはわかりにくい。
最終的なコードはこちら
controller.hears(['からあげ', '唐揚げ', 'カラアゲ', 'から揚げ'], 'direct_mention', function(bot, message) { var Flickr = require("flickrapi"); var flickrOptions = { api_key: "APIキーを入れる", secret: "シークレットキーを入れる" }; Flickr.tokenOnly(flickrOptions, function(error, flickr) { flickr.photos.search({ text: 'からあげ', color_codes: 1, media: 'photos', per_page: 100, safe_search: 1, extras: 'url_z' }, function(err, result) { var photos = result.photos.photo; var r = Math.floor(Math.random() * photos.length); bot.api.reactions.add({ timestamp: message.ts, channel: message.channel, name: 'poultry_leg', },function(err, res) { if (err) { bot.botkit.log('Failed to add emoji reaction :(',err); } }); bot.reply(message, 'クルッポー' + photos[r].url_z); }); }); });