.log

ドットログ。思いついた、調べたメモ。主にフロントエンド、たまに写真とか料理とか。

話しかけるとカラアゲの画像を返すSlackbotを作った

f:id:atsuco02:20160220125621p:plain 鳩に「からあげ」的なことを言うと、からあげの写真を拾ってきて返すクレイジーなbotを作ったのでメモ。

googleの画像検索でもよかったんだけど、SearchAPIの縛りがめんどくさいしスクレイピングする気力もなかったので拾ってくる元はFlickrにしました。

用意するもの

Botkitの用意をする

toach.click

こちらの記事を参考に、さくっとBotkitを導入します。
画像に鳩を設定して、名前をdove(野鳩)にしました。

Flickrのアクセストークンを取得する

www.flickr.com

Flickrのアカウント持ってる開発用のアクセストークンが発行できるので、もそっと作ります。
1アプリケーションにつき1トークンじゃないとだめだよ!とか言ってるので気をつけましょう。

ドキュメントページやらトークンの発行ぺーじやらがわかりにくいのでこちらを参考に。 syncer.jp

flickrAPIモジュールでもごもごする

ここからが本題。 flickrapinpm 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に変更したら事なきを得ました。 f:id:atsuco02:20160220145447p:plain

登録済みのアプリ→編集から変更できます。ページはわかりにくい。

最終的なコードはこちら

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);
        });
    });
});