Slack の ボット で 2FA(Two-Factor Authentication / 2要素認証) 未設定ユーザ を 監視する - API 確認編

Slack には Free Plan でも 2FA の 機能が用意されています. アカウントの安全性から 2FA は 設定しておくべきですが、2FA の 必須化は 有料 の Standard Plan からになります. 目の届く範囲での利用でしたら、声がけしていくことで全員に設定してもらうことはできそうですが、ある程度の規模になると難しくなってきます. そんな時こそ、有料プラン! と 行きたいところですが、この手の話は往々にして時間がかかるもの. その間 ボットに 2FA の 状態を監視、レポートしてもらいたいと思います.

作業環境

  • Slack
  • Node.js 6.11.0 LTS
  • Botkit 0.5.2

まずは 2FA 設定状況 の 確認

管理者権限のユーザで https://my.slack.com/admin へ アクセスすると、チーム・メンバーの一覧 と 2FA の 設定状況を確認することができます.
下図の例では [Team Admin] は 2FA が 設定されているため、2FA アイコンがついています. 一方で [You] は アイコンがついていないので、2FA が 設定されていません. 2FA を 設定するよう指導が必要です!って、自分ですが…
なお、2FA の 設定方法は こちら 2要素認証を設定する – Slack に ヘルプがあります.

毎度ウェブから確認するのは手間なので、2FA を 必須化したいところです. Slack には 2FA 必須化オプションが 有料 の Standard Plan から用意されているので、こちらを使うことで 2FA の 設定を強制することができます. 価格情報は https://my.slack.com/pricing から参照でき、2017年6月現在 “850円/月/アクティブ・ユーザー” です.

お金の話になると途端に進捗が悪くなる、なんてことは よくある話でして、何とかボットでうまく警告したいところで、ボットでチェックする方法を考えていきます.

API で ユーザー情報 の 取得

まずは API で ユーザー情報を取得し、どのような情報があるのか確認してみます. ユーザー情報取得 の API は users.listusers.info が あります.

それぞれのデータを確認するために、ボットを起動した際に API 呼び出しを行ってみます.
※ 11行目 の U01CAXXXX は 調べたいユーザ の ID に なります. bot.api.users.list() の データ出力を確認してから、表示したいユーザ の ID を 設定します.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const Botkit = require('botkit');
const controller = Botkit.slackbot();
controller.spawn({
token: process.env.bot_access_token
}).startRTM((err, bot, payload) => {
bot.api.users.list({}, (err, response) => {
console.log(response)
});
bot.api.users.info({ user: 'U01CAXXXX' }, (err, response) => {
console.log(response)
});
});

実行すると、以下のような情報がコンソールに出力されます. (順不同、整形済み、name: ‘username’ のみ抽出)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
info: ** API CALL: https://slack.com/api/users.list
{ ok: true,
members:
[ { id: 'U01CACXXXX',
team_id: 'T10ADAXXXX',
name: 'username',
deleted: false,
color: '9f69e7',
real_name: '',
tz: 'Asia/Tokyo',
tz_label: 'Japan Standard Time',
tz_offset: 32400,
profile: [Object],
is_admin: false,
is_owner: false,
is_primary_owner: false,
is_restricted: false,
is_ultra_restricted: false,
is_bot: false,
updated: 1487291465 } ],
cache_ts: 1497847517 }
info: ** API CALL: https://slack.com/api/users.info
{ ok: true,
user:
{ id: 'U01CACXXXX',
team_id: 'T10ADAXXXX',
name: 'username',
deleted: false,
color: '9f69e7',
real_name: '',
tz: 'Asia/Tokyo',
tz_label: 'Japan Standard Time',
tz_offset: 32400,
profile: [Object],
is_admin: false,
is_owner: false,
is_primary_owner: false,
is_restricted: false,
is_ultra_restricted: false,
is_bot: false,
updated: 1487291465 } }

残念ながら 2FA に 関する情報は取得できないようです…

OAuth で 取得した トークン を 使う

ところで API リファレンス を よく見ると、引数 token の Description は “Authentication token. Requires scope: users:read“ と なっています. 先ほどのプログラムでは token を 渡していないので、ボット の トークン で アクセスしていたことになります.
では OAuth で users:read を 取得しているトークン を API 呼び出しに使ってみます. Slack の API 呼び出し関数 の 引数 に 環境変数で渡されたトークンを token: process.env.access_token として渡します. (以下、API 呼び出し部分を抜粋)

1
2
3
4
5
6
bot.api.users.list({ token: process.env.access_token }, (err, response) => {
console.log(response)
});
bot.api.users.info({ token: process.env.bot_access_token, user: 'U01CAXXXX' }, (err, response) => {
console.log(response)
});

実行結果を確認します. (順不同、整形済み、name: ‘username’ のみ抽出)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
info: ** API CALL: https://slack.com/api/users.list
{ ok: true,
members:
[ { id: 'U01CACXXXX',
team_id: 'T10ADAXXXX',
name: 'username',
deleted: false,
color: '9f69e7',
real_name: '',
tz: 'Asia/Tokyo',
tz_label: 'Japan Standard Time',
tz_offset: 32400,
profile: [Object],
is_admin: false,
is_owner: false,
is_primary_owner: false,
is_restricted: false,
is_ultra_restricted: false,
is_bot: false,
updated: 1487291465,
has_2fa: false } ],
cache_ts: 1497850133 }
info: ** API CALL: https://slack.com/api/users.info
{ ok: true,
user:
{ id: 'U01CACXXXX',
team_id: 'T10ADAXXXX',
name: 'username',
deleted: false,
color: '9f69e7',
real_name: '',
tz: 'Asia/Tokyo',
tz_label: 'Japan Standard Time',
tz_offset: 32400,
profile: [Object],
is_admin: false,
is_owner: false,
is_primary_owner: false,
is_restricted: false,
is_ultra_restricted: false,
is_bot: false,
updated: 1487291465 } }

21行目に has_2fa: false が あります! users.list では has_2fa が あり、users.info には無いようですが、ユーザーを一覧で取得できる users.list に あるのは助かります. これを使えば、2FA を 設定していないユーザーを抽出し、連絡することができそうです.


とりあえず、2FA 設定の有無が API から取得できることが確認できました. ここまでくれば ボット実装は、これまでの組み合わせなので簡単にできそうですね. 使いやすい API が あるってことは、偉大だ.

Hexo に 関連する記事のリストを追加する

WordPress などでよく見る「関連記事」の リンク、設置してみたいです. Hexo は 静的サイト・ジェネレーターなので、あらかじめサイトが作られていて訪問いただいた際にデータを蓄積して、それを活用するような仕組みは作れません. JavaScript で 制御できる範囲までです. と、あきらめていたら素晴らしいプラグインを作ってくださっている方がいらっしゃりました! ということで、さっそく設置してみます.

作業環境

  • Windows 10
  • Hexo 3.3
  • Hexo Theme Landscape
  • hexo-related-popular-posts

その素晴らしいプラグインは hexo-related-popular-posts! 関連する記事だけでなく、人気の切りリストも作れてしまう優れものです. 素敵なプラグインをありがとうございます!

設置方法については、作者さん の 記事 ブログで関連記事や人気記事を生成するプラグインを作った(node.js製hexo) | TPB が すべてを語ってくださっているので、このまま! という感じですが、機能がたくさんあるので、まずは関連する記事のリストだけに絞って設置しましたので、その記録.

npm で インストールを実行するだけになります.

1
2
3
4
C:\Develop\repos\[username].github.io> npm install hexo-related-popular-posts --save
`-- hexo-related-popular-posts@2.0.0
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules\chokidar\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.1.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

Hexo Theme Landscape に 関連する記事 の リスト を 表示

Hexo の デフォルト・テーマ Landscape を カスタマイズします.
テーマ の レイアウト・ファイル /themes/landscape/layout/_partial/article.ejs の 表示したい場所に popular_posts() を 追加します.
今回は記事の後の [NEWER/OLDER ナビゲーション] と [コメント欄] の 間に配置するため、以下のようにしました.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
</article>
<nav id="related-posts" class="article-inner" style="font-size: smaller">
<div class="article-entry">
<h2>関連記事</h2>
<%-
popular_posts({ PPMixingRate: 0.0 })
%>
</div>
</nav>
<% if (!index && post.comments && config.disqus_shortname){ %>
<section id="comments">
<div id="disqus_thread">
<noscript>Please enable JavaScript to view the <a href="//disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
</div>
</section>
<% } %>

4行目 ~ 11行目 の <nav> タグで 囲まれている部分が追加したものになります.
popular_posts() は、関連する記事を <ul><li> の HTML で 出力してくれます. 「関連記事」のようなタイトルは自前で記述する必要があります.

今回は記事やコメントの枠と合わせたかったので、<nav class="article-inner"><div class="article-entry"> で 囲むようにしました. この辺はお好みで自由にできるのがいいですね.

続いて 本体の popular_posts({ PPMixingRate: 0.0 })PPMixingRate: 0.0 ですが、関連記事のみを表示するオプションになります.
hexo-related-popular-posts は 関連記事 と 人気記事 の 両方が扱えます. すごい! この混合具合を指定することができ、0.0 が 関連記事のみ、1.0 が 人気記事のみ と なります.
人気記事の機能を使うには、Google Analytics API の 設定が必要とのことで、今回は関連記事のみとしました. いずれちゃんと設定して、人気記事を表示するか、ブレンドするようにしてみたいと思います.

そのほかのオプションについては、ヘルパータグの表示オプション に 詳細が書かれています.

いざ確認!

hexo generate して ローカルサーバで動作確認すると、<head> に Google Analytics のためのコードが追加されています.


無事、関連記事が表示されるようになりました. Slack ボット の 記事などは、ボットを いろいろなパターンで作っていたりするので、ご紹介できたらなぁと思っていたので、とても助かります.

静的サイト・ジェネレーターを使っているので関連記事などは難しいかなぁと思っていましたが、素晴らしいプラグインのおかげでつけられました. 作者さま ありがとうございます!

Slack の ボット で ランダムなカスタム絵文字リアクション を する

Slack の ボット に OAuth で 権限を与えられたので、その権限を使って Slack API を 実行するボットを作成してみます.
今回は emoji:read の 権限を使い、チームに追加されているカスタム絵文字をランダムで選択してリアクションするボットにしたいと思います.

作業環境

  • Slack
  • Node.js 6.10.2 LTS
  • Botkit 0.5.2

ボット で 絵文字リアクション を 使う

例によって Basic Usage をもとにカスタマイズしたいと思います. Basic Usage そのままに、hello と DM や メンションされたら、返事をした後に 元のメッセージに raised_hand の リアクションをつけるようにします.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const Botkit = require('botkit');
const controller = Botkit.slackbot();
controller.spawn({
token: process.env.bot_access_token
}).startRTM();
controller.hears('hello', [ 'direct_message', 'direct_mention', 'mention' ], (bot, message) => {
bot.reply(message, 'Hello yourself.');
bot.api.reactions.add({
name: 'raised_hand',
channel: message.channel,
timestamp: message.ts
});
});

起動する際に、環境変数 bot_access_tokenaccess_token に、それぞれ ボットのトークン と OAuth で 権限取得したトークンを設定しておくことを忘れないように注意します.

Slack の リアクション は API 呼び出しになります. bot.api 以下に Slack API に 対応したメソッドiが用意されています. 今回は reactions.add の API を 呼び出したいので、bot.api.reactions.add() に なります.

reactions.add の Slack API リファレンス を 参考に、引数 を オブジェクトで渡します.
token は Botkit の 起動時に渡しているので不要で、name が 必須です. ここでは raised_hand を 設定しました. 文章中に絵文字として使う場合は :raised_hand:: で 囲みますが、リアクション API で 指定する場合は : なしで指定します.
channeltimestamp は オプションなのですが、これはファイルへのリアクションとメッセージへのリアクションで引数が異なるだけで、メッセージへのリアクションは channeltimestamp が 必要となります.
message が 元のメッセージのオブジェクトなので、message.channelmessage.ts で リアクションをつける元のメッセージ指定ができます.
また、第2引数で コールバック関数 を 渡して API の 戻りを受けられますが、今回は特に処理がないので省略しました. たいしたリアクションではないのでエラー処理も省略していますが、重要な場合はエラー・ハンドルしておいたほうがよいいでしょう.

あとはボットを起動して “@BOTNAME hello” と メンションすれば、自分のメッセージにリアクションを付けてくれ、”Hello yourself.” と 返事をしてくれます.

カスタム絵文字でも、設定したカスタム絵文字の名前を : 無しで指定することで利用できます.

利用できる カスタム絵文字 の 一覧 を 取得する

ここまでは API 呼び出しはしたものの、OAuth で 取得した権限とトークンは必要ありませんでした. ここからが本題 “カスタム絵文字をランダムで選択してリアクションするボット” を 作ります.

ランダムで選択するということは、ランダムで選ぶための候補が必要となります. そのために、まずは 利用できるカスタム絵文字 の 一覧 を 取得したいと思います.

カスタム絵文字の一覧取得は emoji.list の Slack API に なります. リファレンス の Description に “Authentication token. Requires scope: emoji:read” と あるように、emoji:read の 権限が必要となります.

とりあえず実験で、先のリアクション・プログラムに以下を追加します. 特別な引数はないので空オブジェクトを渡し、第2引数 で API の 戻りを受けてコンソールへ出力しています.

1
2
3
4
bot.api.emoji.list({}, (err, response) => {
console.log(err);
console.log(response);
});

hello メンションをすると、以下のようなログが返ってくるかと思います. 権限がないと言われています.

1
2
3
4
5
6
info: ** API CALL: https://slack.com/api/emoji.list
missing_scope
{ ok: false,
error: 'missing_scope',
needed: 'emoji:read',
provided: 'identify,bot:basic' }

プログラムを修正し、bot.api.emoji.list() の 第1引数 の オブジェクト に token: process.env.access_token を 与えます. これまでは token を 与えていなかったので、Botkit が 内部的に、起動時の controller.spawn() で 渡されていた process.env.bot_access_token を 使ってくれていました. これはボット用のトークンなので、identify,bot:basic の 権限しかありません. 今回は、それに代わって token: process.env.bot_access_token と 明示的に利用するトークンを指定することで、OAuth で 与えられた権限を利用できるようにします.

1
2
3
4
5
6
bot.api.emoji.list({
token: process.env.access_token
}, (err, response) => {
console.log(err);
console.log(response);
});

起動しなおして、hello メンションすると、以下のように errnullresponse に 値が入ってきます.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
info: ** API CALL: https://slack.com/api/emoji.list
null
{ ok: true,
emoji:
{ bowtie: 'https://emoji.slack-edge.com/T13A2XXXX/bowtie/f3ec6f2bb0.png',
squirrel: 'https://emoji.slack-edge.com/T13A2XXXX/squirrel/465f40c0e0.png',
glitch_crab: 'https://emoji.slack-edge.com/T13A2XXXX/glitch_crab/db049f1f9c.png',
piggy: 'https://emoji.slack-edge.com/T13A2XXXX/piggy/b7762ee8cd.png',
cubimal_chick: 'https://emoji.slack-edge.com/T13A2XXXX/cubimal_chick/85961c43d7.png',
dusty_stick: 'https://emoji.slack-edge.com/T13A2XXXX/dusty_stick/6177a62312.png',
slack: 'https://emoji.slack-edge.com/T13A2XXXX/slack/5ee0c9bea3.png',
pride: 'https://emoji.slack-edge.com/T13A2XXXX/pride/56b1bd3388.png',
thumbsup_all: 'https://emoji.slack-edge.com/T13A2XXXX/thumbsup_all/50096a1020.gif',
slack_call: 'https://emoji.slack-edge.com/T13A2XXXX/slack_call/b81fffd6dd.png',
shipit: 'alias:squirrel',
white_square: 'alias:white_large_square',
black_square: 'alias:black_large_square',
simple_smile: 'https://a.slack-edge.com/0e8da/img/emoji_2016_06_08/apple/simple_smile.png',
bot_aloha_01: 'https://emoji.slack-edge.com/T13A2XXXX/bot_aloha_01/8ca07cf9170a82c1.png',
bot_aloha_02: 'https://emoji.slack-edge.com/T13A2XXXX/bot_aloha_02/cbed400e1d85041f.png',
bot_aloha_03: 'https://emoji.slack-edge.com/T13A2XXXX/bot_aloha_03/4f9440ce2931a3df.png',
bot_aloha_04: 'https://emoji.slack-edge.com/T13A2XXXX/bot_aloha_04/4c4ccb4999b129e0.png' },
cache_ts: '1497403802.153746' }

前半は Slack の サービス側が追加したカスタム絵文字のようです. 後半に自分で追加したものがありました.
(Slack の サービス側追加のカスタム絵文字は Customize Your Team の Emoji には無いのですが、なんだろう…)

今回は bot_aloha_01~04 までを、こちらの Shaka Hand Sign Vectors - Download Free Vector Art, Stock Graphics & Images 素材を利用させていただき、アロハの挨拶で使われる Shaka sign の カスタム絵文字を追加させていただきました. 素敵なアイコン素材 を ありがとうございます!
(この ジェスチャー? ハンド・サイン? も、”アロハ“ と 思ってましたが、Shaka sign って いうんですね. 知らなかった.)

カスタム絵文字 を ランダムで選び、リアクションする

カスタム絵文字の一覧が取れるようになったので、あとは使いたいカスタム絵文字のセットからランダムで取得するだけになります. API 呼び出しのコールバック関数を以下のように実装しました.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bot.api.emoji.list({
token: process.env.access_token
}, (err, response) => {
let emojis = [];
for (let emoji in response.emoji) {
if (emoji.startsWith('bot_aloha_')) {
emojis.push(emoji)
}
}
bot.api.reactions.add({
name: emojis[Math.floor(Math.random() * emojis.length)],
channel: message.channel,
timestamp: message.ts
});
});

emoji.list API の 戻り response.emojifor-in で 回し、bot_aloha_ で 始まる カスタム絵文字を使う候補の配列に追加します.

候補配列ができたら、使うものをランダムで取得して bot.api.reactions.add() の 呼び出しに使います. リアクションはボットの権限で実行できるので、token は 渡しません.

emoji.list を キャッシュしておいたり、emoji.list を ハードコーディングしておくこともできますが、命名ルール(今回は bot_aloha_ で 始まる) に応じて動くようにしておくことで、命名ルールに則ってカスタム絵文字を追加するだけで拡張できるので、毎回 emoji.list を 呼び出すようにしました.

プログラム最終系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const Botkit = require('botkit');
const controller = Botkit.slackbot();
controller.spawn({
token: process.env.bot_access_token
}).startRTM();
controller.hears('hello', [ 'direct_message', 'direct_mention', 'mention' ], (bot, message) => {
bot.reply(message, 'Hello yourself.');
bot.api.emoji.list({
token: process.env.access_token
}, (err, response) => {
let emojis = [];
for (let emoji in response.emoji) {
if (emoji.startsWith('bot_aloha_')) {
emojis.push(emoji)
}
}
bot.api.reactions.add({
name: emojis[Math.floor(Math.random() * emojis.length)],
channel: message.channel,
timestamp: message.ts
});
});
});

OAuth で 取得した権限を実際に使ってみました.
Botkit の API 呼び出し bot.api.[SLACK_API_NAME]() の 第1引数のオブジェクトに token: process.env.access_token を 追加するだけで利用できるので簡単ですね. 権限が不要な場合は token: を つけなくてよいのも簡単で助かります. 多くの場合 token: 無しで使ってたりするので、必要な時にうっかり付け忘れて missing_scope で 怒られるというケースもありますが…
とはいえ、Slack API が 使いやすくなっていることと、Botkit が 便利にしてくれているおかげで、簡単に利用することができました!ありがたいです.

Slack OAuth を 簡単にするツールを作った

前回 Slack の ボット に OAuth で 権限を付与する方法 について書いたものの、ブラウザで頑張るのは結構めんどくさいよなぁと. なのでツールを作ってみました. まだ細かいところまで作り切れてないですが、少し使う分にはいけそうなので、ちょっと脱線してトークン活用の前にツールをご紹介.

作業環境

  • Slack
  • Windows 10
  • Google Chrome

Slack OAuth Helper

命名苦手なので、まんまの名前です.
GitHub リポジトリ https://github.com/azriton/slack-oauth-helper に ソース一式をアップし、GitHub Pages を master ブランチで設定したので、https://azriton.github.io/slack-oauth-helper/ で 動作しています. GitHub すごい!

設置を簡単にしたかったので HTML 1枚 で できています. 外部依存は Modulr.css という CSS ライブラリ と Font Awesome で、JavaScript は ライブラリなしです.
HTML5 で 追加された <template> タグ や SessionStorage, Selectors API などを使っていますが、最近のブラウザだったら大丈夫だと思います. たぶん. 環境の都合で、Windows 10 の Google Chrome と Microsoft Edge でしか動作確認してないです. すみません.
なんか、document.querySelectorAll()for-of で Chrome と Edge で 動きが違ったりしたので若干不安ではありますが…

使い方

アプリ・ボット の Redirect URL を 修正

ここではアプリ・ボットは登録されているものとして、Redirect URL の 変更から始めたいと思います.

Slack の Apps https://api.slack.com/apps へ アクセスし、利用するボットを選択します.

ボットの詳細画面が表示されるので、左メニューから [OAuth & Permissions] を クリックします.

画面中ほどの [Redirect URLs] にある、URL の 右にある [ペンのアイコン] を クリックします.

URL が 編集できるようになるので、https://azriton.github.io/slack-oauth-helper/ を 入力し、[Save] ボタンをクリックします. 最後の / を 忘れないようにご注意ください.

編集が完了します. 下にある [Save URLs] ボタンをクリックします. (こっちの Save も しないと確定されないのでご注意. よく忘れてトラブりました…)

Slack OAuth Helper の 利用

https://azriton.github.io/slack-oauth-helper/ へ アクセスします.
[Client ID] に アプリ・ボット の Client ID を 入力します.
[OAuth Scopes] で 必要な権限にチェックを入れていきます. ここでは 前回と同じスコープ に チェックしました.
権限選択後、[認可リクエスト] ボタンをクリックします.

Slack の Slack の OAuth 権限確認画面 が 表示されます. 権限の詳細を確認し、問題なければ [Authorize] ボタンをクリックします/

Slack OAuth Helper に 戻ります. トークン発行済みの場合は権限が更新されているので完了となります.
未発行の場合は、[トークン発行 URL] に 表示されている URL を コピーします. テキストフィールド右 の ファイル・アイコン を クリックすると、クリップボードへコピーされます. ブラウザのアドレスバーへペーストし REPLACE_THIS_WITH_YOUR_APP_CLIENT_SECRET を アプリ・ボット の Client Secret に 置き換えてからアクセスします.

※ トークン発行については、あえてフォームを作りませんでした. HTML 単独で動作しているので Client Secret を 抜くことはないのですが、この類のデータは不要なら入力欄は作りたくないという考えからになります. ここだけは手間が残りますが、大事なものは知らない場所に入力しない ってことでご容赦ください.

Known Bugs とか、ToDo とか

  • フォーム で required に なっているのに、効いてません. 未入力でも Slack OAuth へ 遷移して、エラーになります. orz
  • Slack OAuth Helper を 開く URL に パラメーター を つけると、設定を復元して画面表示できる機能があるけど、URL を 作る機能が未実装です. orz
  • トークン発行済み って スイッチ を 用意して、Slack OAuth 後の戻り画面を切り替えたい.
    いずれ GitHub Issues に 入れておかないと…

これで Slack の OAuth 権限の設定が少し簡単になりました. 最小権限で作り始めて、必要になってから追加するので、なんだかんだで権限が欲しくなり、そのたびに URL を 作るのもしんどかったので、思い切って作ってよかった.

自分が権限を持っている Slack チーム だと 自己完結できるので良いのですが、一般ユーザの権限しかないところでボットを作っていたりすると、OAuth を お願いしなければならないケースもあり、その際に管理者さまがすぐにやってくれるとよいのですが、いろいろとあると進まないので、こんな画面で渡すと意外と早かったりして助かります. 管理者さまへ簡単に渡せるように設定復元 URL を 作る機能を早く実装しないと.

Slack の ボット に OAuth で 権限を追加する

Slack の ボット を 自然言語で会話させたり、リマインド系の処理をさせたりと色々できるようになりました. もう少し踏み込んで Slack の API を 活用した処理をできるようにしたいと思います. そうなると、これまでの Bot トークンでは権限が足りず、処理ができません. まずは準備として Slack の ボット に OAuth で 権限を追加したいと思います.

作業環境

  • Windows 10
  • Slack
  • A3RT Talk API
  • Node.js 6.10.2 LTS
  • Botkit 0.5.4

アプリ・ボット の 作成

OAuth で ボットに権限を追加するには、アプリ・ボット(勝手に命名! App じゃ わかりにくいので.) を 作って、そちらで動作させる必要があります. これまでのボットは残念ながらサヨナラに (T_T とはいえ、Slack でのアカウントだけなので、作ってきたプログラムは そのままに動作させられます.

アプリ・ボット作成のページ https://api.slack.com/apps/new へ アクセスします.
[App Name] に アプリ・ボット の 名前を入力し、[Development Slack Team] で 自分の Slack チーム を 選択します.
[I plan to submit~] は、作成したボットを Slack App Directory で 公開する場合にチェックをつけますが、今回はなしで [Create App] ボタンをクリックして進めました.

アプリ・ボットが作成され基本情報の画面が表示されます. [Client ID] と [Client Secret] は 後で使うのでひかえておきます. Client Secret は [Show] ボタンをクリックすると表示されます. 特に大事なので取り扱いに注意します.

左メニューから [OAuth & Permission] を クリックし、画面中央の [Redirect URL(s)] に http://localhost:3000/slack/auth/redirect を 入力し、[Save Changes] を クリックします.
これは Slack の OAuth から リダイレクト・バックされる際の URL に なります. 通常はアプリを動かしておくのですが、今回は手動でブラウザ内完結するので localhost に しました. 詳細は こちら、Sign in with Slack も ご参照ください.

続いて Slack に ボットのユーザを追加します. 左メニューから [Bot Users] を クリックします.
[Default username] に Slack の ボット・ユーザー名を入力します. 既存のユーザー名と重複すると、自動的に連番が付与されるので注意してください.
入力後 [Add Bot User] を クリックします.

OAuth で 権限を追加

Slack の OAuth Scopes の ページから、必要な権限をピックアップします. 今回は、今後使っていきたい想定で bot, channels:history ,emoji:read, files:read, files:write:user, users:read の権限を取得することにしました.
※ 本来は必要になり次第、以下の手順で追加していくべきですが、一連の流れで作っていくのでまとめて取得しました. あまりとりすぎるとボットができる範囲が大きくなりすぎるので、何かあった際の影響も大きくなるため権限の設定は注意が必要です.

2017年6月7日 追記
以下の手順を簡易化するためのツールを作りました. よろしかったら、こちらもご利用ください.
Slack OAuth Helper - https://azriton.github.io/slack-oauth-helper/

必要な権限のスコープが決まったのでブラウザで https://slack.com/oauth/authorize?client_id=REPLACE_THIS_WITH_YOUR_APP_CLIENT_ID&scope=REPLACE_THIS_WITH_YOUR_OAUTH_SCOPE へ アクセスします.
REPLACE_THIS_WITH_YOUR_APP_CLIENT_ID は、先ほどアプリ・ボットを作成した際にひかえた [Client ID] を、
REPLACE_THIS_WITH_YOUR_OAUTH_SCOPE は、上記で選択した OAuth Scope を カンマつなぎ (e.g. bot,channels:history,emoji:read,files:read,files:write:user,users:read)で置き換えます.

そうすると、Slack の OAuth 権限確認画面が表示されます. 与える権限の内容を確認し問題なければ [Authorize] ボタンをクリックして認可します. (複数の Slack チーム に サインインしている場合はチーム選択が先に表示されるので、アプリ・ボットを使うチームを選択します.)

ブラウザが localhost へ リダイレクトされ、ページが表示できないエラーが表示されます. 慌てずに、アドレスバー の URL から code の 値をコピーします.
※ このリダイレクトされた先は、先にアプリ・ボットを作成した際に [OAuth & Permission] の [Redirect URL(s)] に 入力したものになります. 本来は OAuth で 連携したアプリに戻してプログラムで処理するのですが、今回は手動でやりきります.

ブラウザで、https://slack.com/api/oauth.access?client_id=REPLACE_THIS_WITH_YOUR_APP_CLIENT_ID&client_secret=REPLACE_THIS_WITH_YOUR_APP_CLIENT_SECRET&code=REPLACE_THIS_WITH_COPYED_CODE へ アクセスします.
置き換えは以下となります.

  • REPLACE_THIS_WITH_YOUR_APP_CLIENT_ID は、先にアプリ・ボットを作成した際にひかえた [Client ID]
  • REPLACE_THIS_WITH_YOUR_APP_CLIENT_SECRET は、先にアプリ・ボットを作成した際にひかえた [Client Secret]
  • REPLACE_THIS_WITH_COPYED_CODE は、上記ブラウザのリダイレクトで戻されたアドレスバーの URL code の 値

正しく入力できるとトークンが含まれた JSON が 返ります. access_tokenbot_access_token を、それぞれひかえておきます.
access_token は Slack の API を 呼び出す際に使うトークンで、bot_access_token は ボットを起動する際に使用するトークン(これまで使ってきたトークンと同じ位置づけ) です.

とりあえず、ボット を 起動

今回は OAuth の 権限を持ったボットの作成で準備段階なので、基本動作 の Botkit readme.md #Basic Usage の まま index.js を 作ります.

1
2
3
4
5
6
7
8
9
10
const Botkit = require('botkit');
const controller = Botkit.slackbot();
controller.spawn({
token : process.env.bot_access_token
}).startRTM();
controller.hears('hello', [ 'direct_message', 'direct_mention', 'mention' ], (bot, message) => {
bot.reply(message, 'Hello yourself.');
});

ボットのプログラムができたら起動します.
[API_TOKEN] は Slack からコピーした、ボットの API Token に なります.

1
2
3
4
5
6
7
8
9
10
c:\Develop\repos\slack-bot> set access_token=[ACCESS_TOKEN]
c:\Develop\repos\slack-bot> set bot_access_token=[BOT_ACCESS_TOKEN]
c:\Develop\repos\slack-bot> npm install --save botkit
c:\Develop\repos\slack-bot> node index.js
Initializing Botkit v0.5.4
info: ** No persistent storage method specified! Data may be lost when process shuts down.
info: ** Setting up custom handlers for processing Slack messages
info: ** API CALL: https://slack.com/api/rtm.connect
notice: ** BOT ID: dev-anonymous-poet ...attempting to connect to RTM!
notice: RTM websocket opened


OAuth の 権限を使ったボットの作成は、ちょっと長くなりそうなので今回は権限の取得まで…
もうちょっと やりたかったけど仕方ない. ボットが色々な権限を持つことで Slack 内でのちょっとしたお手伝いができるようになるので便利になりそうですね.

Slack ボット の AIトーク機能 を Docomo の API に 切り替える

Slack の ボット を リクルートテクノロジーズさん の API を 使って自然言語での会話できるようにしてみました. AI が 流行っている 2017年昨今、様々なサービスがあるのでいろいろ試してみたいと思います. 今回は NTTドコモさん の AIトーク の API を 試してみました.

作業環境

  • Slack
  • docomo Developer support 雑談対話 API
  • Node.js 6.10.2 LTS
  • Botkit 0.5.2

docomo Developer support とは ?

NTTドコモさん が 公開されている AI の API で、 “ドコモやパートナー企業が持つ様々なアセットを「API」として汎用化して提供 – docomo Developer support” してくれるものだそうです. 会話を意識した API では 音声認識や音声合成による読み上げなどの API があり、また 画像認識 や 面白いところでは、山座同定 - 画像に写っている山の名前を取得、仮想フェンス、交通情報 などなど、様々な API が 用意されています. NTTドコモさん の スマートフォン・アプリで使われている機能+αで提供されているような感じでしょうか.

今回は その中の 雑談対話 API “自然な会話をします。 – API/ツール“ を 使わせていただきました. ウェブサイト で おすすめ されている Repl-AI の 方が高機能なイメージがありましたが、シナリオベースで動かすような感じで、チャット上での雑多な会話に応答するには 雑談対話 API が よさそうでした.

docomo Developer support に ユーザ登録

API の 利用にあたり、まずは docomo Developer support に ユーザ登録する必要があります.

ログイン の ページへアクセスし、SNSアカウントでログイン / 新規登録 を します. 今回は [メールアドレスで新規登録] 選択しました.

メールアドレスの入力ページが表示されるので、[メールアドレス] と [確認用] に それぞれ 入力します.
[所属されている法人・組織に関する情報を登録する] は、今回は個人利用なのでチェックを外しました. 登録すると利用制限が緩和されるようです. 最初からチェックが入っており、会社名などが必須で表示されているので焦りますが、チェックを外すことで会社名などの項目は消えます.
最後に [文字認証] の 画像に表示されている文字列を入力し、利用規約を確認し、同意できたら [同意して確認画面へ] ボタンをクリックします.

確認画面が表示されるので、メールアドレスに間違えがないか確認し [仮登録する] ボタンをクリックします.

メール送付のステップに進み、確認メールが送信されたとの画面が表示されます.
ここで、先ほど入力したアドレスにメールが届くのを待ちます.

メールに書かれている URL へ アクセスすると、パスワード入力の画面が表示されます. 注意事項に従ったパスワードを決め入力し [パスワードを設定する] ボタンをクリックします.

パスワードが設定できると、新規アカウント登録完了の画面が表示します. 続いて API key を 取得するので、[ログインする] ボタンをクリックします.

雑談対話 API の 利用申請 と API key の 取得

アカウント作成の流れから ログイン画面 は 表示されますが、自動ログインや入力はないので、先ほど取得した アカウントのメールアドレスとパスワードでログインします.

マイページ画面が表示されるので、画面中ほどの API利用申請・管理 から [新規API利用申請へ] ボタンをクリックします.

アプリケーションの登録画面が表示されるので、情報を入力します.
審査の話が書かれていますが、今回はすぐに API key が 発行されました.
開発用の仮登録なので審査はなく、本登録時に審査があるのでしょうかね. 審査の説明があってちょっとドキドキしましたが…

コールバック URL は、今回は OAuth を 使わないので注釈の通り https://dummy と 入力しました. OAuth を 使うと、個人に応じた会話をしてくれるようです.
提供者名とサポートメールアドレスは OAuth 画面で使われるようで、今回は OAuth は 使わないのですが必須なので入力します.
入力後 [API 機能選択へ] ボタンをクリックします.

API 機能選択画面が表示されます. 今回は [雑談対話] のみを選択し [利用する API の 利用規約に同意して、次へ] ボタンをクリックします. 同意すべき利用規約が画面内にないのですが、アカウント作成時に同意した ご利用規約 で よいのかと思います.

利用規約に同意できたら、利用申請画面が表示されます. 選択した機能が表示されていることを確認し [利用申請する] ボタンをクリックします.

利用申請が完了しました! 続いて API key を 確認するため [登録アプリケーション一覧へ] ボタンをクリックします.

API利用申請・管理 画面が表示されます. アプリケーション情報 に 先ほど登録したアプリケーション名があり、client id、client secret、API key が 表示されています. 今回は API key のみ使用するので控えておきます.

Slack の ボット を 改修

前回のトーク機能を以下のように変更します.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const Botkit = require('botkit');
const request = require('request');
const controller = Botkit.slackbot();
controller.spawn({
token: process.env.token
}).startRTM();
var contexts = {};
controller.on('ambient', (bot, message) => {
request.post({
url: `https://api.apigw.smt.docomo.ne.jp/dialogue/v1/dialogue?APIKEY=${process.env.docomo_apikey}`,
json: {
utt: message.text,
context: contexts[message.user],
t: 20
}
}, (err, response, body) => {
if (body && body.utt) {
contexts[message.user] = body.context;
bot.reply(message, body.utt);
} else {
bot.reply(message, `エラーたよ:fearful: [${body}]`);
}
});
});

ambient の イベントを受けるのは変わらず、request 先が変わります.
url の API URL が 変わり、URL に 続いて ?APIKEY=${process.env.docomo_apikey} で API key を 渡します. リクエスト・パラメータに入れたかったのですが、どうしてもうまく動かなかった orz
リクエスト・パラメータ は json で 以下のデータを送ります.

  • utt は、API へ 渡す会話の文字列です. この入力に対して応答を考えて返してくれます. Slack の 入力なので message.text を 渡します.
  • context は、会話の継続を識別する ID とのことで API からのレスポンスに含まれる context を 再度渡すことで会話の継続ができるようです. Slack では 複数のユーザーが会話してくるので、ユーザーごとに context を とっておき渡すようにしました. (こうすると会話の横入りができないので、全員で共通でもよかったかも)
  • t は、キャラクター指定になります. 20 で 関西弁キャラ、30 で 赤ちゃんキャラ、指定なし で デフォルトキャラ だそうです. 会話の雰囲気を変えてみたかったので関西弁にしてみました.
    他にも会話しているユーザー の ニックネーム や 血液型、星座 などなど 多数のパラメーターが設定できます. 詳細は 機能別リファレンス を ご確認ください.

レスポンスの本体は body に 入ってきます. body.utt が レスポンスの会話なので、bot.reply() に 流します. また body.context に 会話のコンテキストが入っているので、request で 使用した var contexts に Slack の ユーザである message.user を キーに保持しておきます.
この形だとボットを再起動するなどして変数がクリアされると消えてしまいますが、永続化するほどの情報ではないので変数保持としました.

いざ、起動!

前回同様 Slack トークン と API Key を 環境変数から受け取るので環境変数を設定して起動します.

1
2
3
4
5
6
7
token=REPLACE_THIS_WITH_YOUR_TOKEN docomo_apikey=REPLACE_THIS_WITH_YOUR_APIKEY node index.js
Initializing Botkit v0.5.2
info: ** No persistent storage method specified! Data may be lost when process shuts down.
info: ** Setting up custom handlers for processing Slack messages
info: ** API CALL: https://slack.com/api/rtm.start
notice: ** BOT ID: bot ...attempting to connect to RTM!
notice: RTM websocket opened

※ Windows コマンドプロンプト の 場合は、下記のように set で 明示的に環境変数を設定してから実行します.

1
2
3
set token=REPLACE_THIS_WITH_YOUR_TOKEN
set docomo_apikey=REPLACE_THIS_WITH_YOUR_APIKEY
node index.js

トーク、トーク♪


前回の流れ同様の会話で始めましたが、いきなりよくわからない応答です. そして好きなんですかね、オフィス街…
会話が詰まってくると疑問を投げかけてきて話題を変えるような応答もしてきます. これはこれで面白い感じです.


ボットのフレームワーク に AI の サービス と、組み合わせるだけで簡単に会話ボットが作ることでき、また AI も Web API なので、切り替えも簡単にできました. フレームワークうやサービスを提供してくれてるおかげですね. ありがたいです.

個人的には、リクルートテクノロジーズさん の API に 比べて、NTTドコモさん の API のが、より自然な会話応答をしているようにも感じました. 途中で話を変えてきたり、ニュースをブチ込んできたりと色々と楽しいです. 例のヒツジさん あたりで培われている技術なんですかね.

サービスごとの特色があって面白いです. 次はどこの AI と 会話してみようかなぁ.

Slack の ボット に AIトーク機能を付ける

Slack の ボット で 自然言語での会話できるようにしてみたいという野望があるものの、個人ではなかなか太刀打ちできません. こんなときは巨人の肩、ですね. というこで、最近公開された リクルートテクノロジーズさん の AI を 使って、Slack の ボットにトーク機能を付けてみたいと思います. はたしてちゃんと会話が成立するボットになるのか、楽しみですね♪

作業環境

  • Slack
  • A3RT Talk API
  • Node.js 6.10.2 LTS
  • Botkit 0.5.2

A3RT API とは ?

リクルートテクノロジーズさん が 公開されている AI の API で、機械学習 や ディープラーニング(深層学習) を 用いた API だそう. ホットペッパービューティー や カーセンサー などで活用されれいたのだとか. 2017年4月現在、6種類 の API が 提供されていて、今回は その中の Talk API “様々なアプリケーション上でユーザーとの対話を自動化するAPIです。入力文から応答文を自動生成します。日常会話レベルでの応答が可能です。 – プレスリリース“ を 使わせていただきました.

A3RT Talk API の API KEY 発行申請

さっそく、A3RT Talk API を 利用するために、API KEY を 発行してもらいます.

Talk API の ページへアクセスし、[API KEY 発行] を クリックします.

メール確認の入力ページが表示されるので、まずは [利用規約、プライバシーポリシーに同意する] を クリックします.

画面内にウィンドウが表示され、利用規約 と プライバシーポリシー が 表示されます. 確認して、同期できたら [同意する] ボタン を クリックします. 同意できない場合は利用できないので、その場合は利用をあきらめましょう…

利用規約 と プライバシーポリシー に 同意すると、ウィンドウが閉じるので、利用者申請をするメールアドレスを入力し、[送信] ボタンをクリックします.

ステップ2へ進み、確認メールが送信されたとの画面が表示されます.
ここで、先ほど入力したアドレスにメールが届くのを待ちます.

メールに書かれている URL へ アクセスすると、メールアドレスの確認完了の画面が表示されます. 続いて同じメールアドレスに API KEY が 送られてきます.
API KEY を 受け取ったら、申請完了になります.

Slack の ボット に 設置

基本動作の確認確認として、Botkit の readme.md #Basic Usage を 使います. そして fail というキーワードでメンションをかけられたら、処理が失敗するコードを追加します.
余談ですが、最近 GitHub の Botkit Readme.md が 変わって、基本動作のソースが docs/readme.md へ 移動し、またソースが少しわかりにくくなってしまいました. 困るなぁ…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const Botkit = require('botkit');
const request = require('request');
const controller = Botkit.slackbot();
controller.spawn({
token: process.env.token
}).startRTM();
controller.on('ambient', (bot, message) => {
request({
url: 'https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk',
method: 'POST',
form: { apikey: process.env.a3rt_talk_apikey, query: message.text },
json: true
}, (err, response, body) => {
if (body.status == 0) {
bot.reply(message, `${body.results[0].reply} (${Math.ceil(body.results[0].perplexity * 100) / 100})`);
} else {
bot.reply(message, `エラーたよ:fearful: [${body.status} ${body.message}]`);
}
});
});

今回はチャンネル内で自由に会話応答したいので ambient の イベントを受けるようにしました. メンションでの応答にすると毎度つけるのがめんどくさいというのもあり. とはいえ、メンション以外のすべてに応答するので、ほぼ常時反応します. 本番で使う場合は専用ボットにしてチャンネルを限定したほうが良いかもしれません.

会話を受け取ったら Talk API を 呼び出して応答します. Talk API は HTTP POST で https://api.a3rt.recruit-tech.co.jp/talk/v1/smalltalk へ リクエストします. リクエスト・パラメータ は apikeyquery です.
apikey は、発行申請した際にメールで受け取ったものになります.
query は、Talk API へ 渡す会話の文字列です. この入力に対して応答を考えて返してくれます. Slack の 入力なので message.text を 渡します.

今回は request モジュールを使って実装しました. json: true を 設定すると、レスポンスを自動的に JSON オブジェクト として返してくれるので実装が簡単になります.
レスポンスの本体は body に 入ってきます. HTTP Status も しっかり切られているのですが、empty reply 応答テキストが空 の 場合 も 200 OK で 返ってきて無反応な場合が分かりにくかったので、API の Status コードで応答を振り分けました.

body.status == 0 は 正常に応答しているので、そのまま Slack へ リプライします. 応答メッセージは body.results[0].reply に 入っています. 2017年4月現在 results は 1つしか返ってきませんが、いずれ複数返ってくるようになるのでしょうか. また、body.results[0].perplexity に 予測性能 が 入っています. 数値が高いほど確度がよさそうに感じますが、詳細はドキュメントにありませんでした. 今回はテスト用に出力しています. 数値に合わせて絵文字をあてても面白いかもしれません.

body.status0 以外の場合は、何かしらのエラーになります. 今回はデバッグ用に Slack へ リプライさせています. 実際にはログに出せばよいでしょう.
注意点としては API が 返事を作れなかった場合は body.status2000 で 返ります. この場合に、応答を返さないで放置するか、自前で何かの応答を作りこむか判断ポイントになります. (ちなみに何も出力しないで放置バージョンを作ったら、ボットに話しかけたつもりで無視されたような形になり、寂しかったです…)

いざ、起動!

起動の仕方は、通常の Node.js の 起動に変わりありません. 今回は Slack トークン と A3RT Talk API KEY を 環境変数から受け取るようにしているので、その設定が必要です. 下記の REPLACE_THIS_WITH_YOUR_TOKEN を Slack ボット の トークンに、REPLACE_THIS_WITH_YOUR_APIKEY を A3RT Talk API の API KEY に 置き換えて実行します.

1
2
3
4
5
6
7
token=REPLACE_THIS_WITH_YOUR_TOKEN a3rt_talk_apikey=REPLACE_THIS_WITH_YOUR_APIKEY node index.js
Initializing Botkit v0.5.2
info: ** No persistent storage method specified! Data may be lost when process shuts down.
info: ** Setting up custom handlers for processing Slack messages
info: ** API CALL: https://slack.com/api/rtm.start
notice: ** BOT ID: bot ...attempting to connect to RTM!
notice: RTM websocket opened

※ Windows コマンドプロンプト の 場合は、下記のように set で 明示的に環境変数を設定してから実行します.

1
2
3
set token=REPLACE_THIS_WITH_YOUR_TOKEN
set a3rt_talk_apikey=REPLACE_THIS_WITH_YOUR_APIKEY
node index.js

トーク、トーク♪


Slack の 入力に対してちゃんと応答してくれました! 会話がかみ合っているような、そうでもないようなのは気にしないでおきましょう.


リクルートテクノロジーズさん が API を 公開してくださっているおかげで簡単に応答するボットを作ることができました. 登録もメールだけなので容易で助かります. クラウドサービスのサインアップとかになると大変なので、このぐらい手軽に使わせていただけるとうれしいですね. ほかの API も 試してみようっと.

Google Analytics に Search Console の 分析を追加する

このブログにアクセスしてくださる方々も増えてまいりました. ありがとうございます!
Google Analytics を 設置 していましたので、アクセスいただいている数値を知ることができますが、一番のアクセス元である検索エンジンから、どのような検索ワードで来てくださっているのかはわかりません. ということで、Google Search Console を 設置したいと思います. (今まで設定してなかったんかい…)

作業環境

  • Google Analytics
  • Google Search Console

Google Analytics から、Google Search Console の 設定

Google Analytics へ サインアップ&ログインしていることを前提に、Google Search Console の 設定をしたいと思います. まだサインアップしていない場合は、こちら を ご参照ください.

Google Analytics の ウェブサイトへアクセスし、左のメニュー から、[Search Console] - [ランディングページ] を クリックし、右のコンテンツから [Search Console の データ共有を設定] ボタンをクリックします.

各種設定のような画面が表示されますので 一番下 まで行き、[Search Console を 調整] ボタンをクリックします.

画面 一番上 まで行きます. (画面が書き換えられたのに、スクロール位置が固定されているようで一番下の何もない状態で描画されるので焦りました)
[Search Console の サイト] に ある [編集] の リンク を クリックします.

新しいタブ(or ウィンドウ) が 開き、Search Console の 連携画面が表示されます. [Search Console に サイトを追加] ボタン を クリックします.

さらに新しいタブが開き、Search Console の ようこそ画面が表示されます. ここにウェブサイトの URL を 入力し、[プロパティを追加] ボタンをクリックします.
今回は、これまでのブログ設置の流れから GitHub Pages に あるものとして https://[username].github.io/ と しました.

入力したウェブサイトの所有権があるかを確認されます. Google Analytics 連携しているので、推奨されている Google アナリティクス で 進めます. そのまま [確認] ボタンをクリックします.

確認が取れたこと表示されるので、[続行] リンクをクリックしして進めます.

Search Console の ダッシュボードへ戻ります.

これで、Google Search Console の 設定 が できました. Search Console として利用することはできるようになりましたが、Google Analytics で 一元的に見たいので、続いて Google Analytics との連携を進めます.

Google Analytics と Search Console の 連携設定

Search Console の 連携画面のタブに戻ります. ここで F5 キー もしくは、Ctrl + R を 押して画面をリロードします. そうすると、先ほど Google Search に 設定した URL が 表示されます.
追加した URL の ラジオボタンを選択し、[保存] ボタンをクリックします.

Google Analytics への関連付けを行ってよいかの確認ダイアログが表示されるので [OK] ボタンをクリックします.

これで、Google Analytics と Google Search の 連携が設定できました.

いざ確認!

さぁ Google Analytics に 戻り リロード! どのような検索ワードでいらっしゃってくださっているのか、いざ…
表示されるまで、2~3日かかるらしいです. はい.


無事、Search Console を 設置することができました.
結果は 2~3日ごとのことで、すぐに見れないのは残念ですが、まぁ そうですよね. もっと早くから設定しないとですね. いろいろ書いてみたいことが多くて、ブログ環境回りがついつい後回しになってしまいました…
とりあえず表示されるのを楽しみに待ちたいと思います.

Crystal Signal Pi on Docker

Raspberry Pi に 光り輝く四角柱 を 立てた Crystal Signal Pi、ようやくミドルウェアを導入しました. ミドルウェア を Docker の コンテナとして導入しましたので、φ(..)メモメモ.

作業環境

  • Raspberry Pi 3 Model B
  • Crystal Signal Pi
  • Docker

なぜ Docker ?

Raspbian Jessie Lite で Docker する - インストール編 の なぜ Docker ? で 書きました通り、ラズパイの環境に様々な SDK や ライブラリなどを混在させて競合が発生しないように、各環境を分離するためになります.

Crystal Signal Pi ミドルウェア は、Apache2 と Python2、そして pigpio に 依存しています. 依存関係が少ないので整理しやすいですが、他でまた Apache が 必要となったり、 Python3 を を 使い始めたら… と、思うとコンテナに分離しておけば環境もすっきりしますし、今後 Crystal Signal Pi を カスタマイズしようと思った際に、コンテナだったら Try & Error で 簡単に作り直しもできるのもよいです.

また、ちょっと他でラズパイが要りようになった際にも、コンテナを止めるだけで容易に転用できます. (もちろん、Crystal Signal Pi に 戻すのも簡単)

こんな考えから、Crystal Signal Pi on Docker で 作ることにしました.

ホスト側 OS に pigpio の 導入

Crystal Signal Pi は pigpio の サービス を 介して GPIO を 操作しています. そのため、pigpio を 導入する必要があります.
今回は Docker コンテナ として Crystal Signal Pi ミドルウェア を 導入しますが、pigpio は ラズパイ の GPIO 操作で共通的に使うものなので、コンテナではなく ホスト OS に 導入しました.

1
2
3
4
pi@raspberrypi:~ $ sudo apt-get update
pi@raspberrypi:~ $ sudo apt-get install -y --no-install-recommends pigpio
pi@raspberrypi:~ $ sudo systemctl enable pigpiod.service
pi@raspberrypi:~ $ sudo systemctl restart pigpiod.service

Dockerfile の 作成

Crystal Signal Pi 用に、以下のような Dockerfile を 用意します.
ベースは軽量の armhf/alpine で、それに合わせてパッケージ管理を apk で 行います. apk を 2回に分けているのは、稼働時に必要となるパッケージ(curlapache2python) と ビルド時だけ必要なものを分離し、ビルド時だけに必要なものはコンテナ・イメージを小さくするため最後に apk del するためです. apk --virtual の オプションで追加(インストール) したものを疑似的にまとめることができ、削除する際に同じキーワードで削除できるのがいいですね.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
pi@raspberrypi:~ $ nano Dockerfile
FROM armhf/alpine
RUN apk --no-cache upgrade \
&& apk add --no-cache curl apache2 python \
&& apk add --no-cache --virtual build-dependencies openssl rsync py2-pip gcc make python-dev musl-dev \
&& pip install --upgrade pip \
&& pip install pigpio \
\
&& curl -sSL https://raw.githubusercontent.com/azriton/crystal-signal-armhf-alpine/master/install.sh | sh \
\
&& apk del --purge build-dependencies \
&& rm -fr /tmp/* \
&& rm -fr /root/.cache \
;
EXPOSE 80
CMD /usr/sbin/httpd -f /etc/apache2/httpd.conf && /usr/local/bin/LEDController.py

上記 Dockerfile では、Crystal Signal Pi の ミドルウェアをインストールするスクリプト install.sh は、私の GitHub リポジトリから curl して実行しています. これは Docker コンテナで動かすためにスクリプトを一部修正してるものになります.
後々のアップデートに追随できなくなると困るので、完全な作り変えはせず、以下の方針で変更しある程度 diff が とれるようにしました. (どのくらい変えるかのバランスで悩んだ. こんな時はどうするのか、よい方法を知りたい)

  • OS と Python の パッケージ管理は Dockerfile へ 外部化する
  • 処理を実行させないものは削除する (コメントアウトにしない)

※ この Dockerfile も GitHub の リポジトリにアップしました.
https://github.com/azriton/crystal-signal-docker-armhf-alpine

ビルドする

Dockerfile が 用意できたら、docker build します.
--tag=repository/tag は 自身のリポジトリとタグを設定します.

1
pi@raspberrypi:~ $ docker build --force-rm --no-cache --tag=repository/tag .

実行!

Docker コンテナ の 実行は以下になります. --tag=repository/tag は ビルド時に指定したものと同じにします.

1
pi@raspberrypi:~ $ docker run -d -p 80:80 --net host --name crystal-signal-pi repository/tag

Crystal Signal Pi の 管理コンソールへブラウザでアクセスできるように -p 80:80 で 80番ポートを公開します.
--net host で コンテナからホスト側のネットワークスタックへアクセスできるようにします. これはホスト側に導入した pigpiod.service へ アクセスするためです.



今回 armhf/alpine の コンテナを使ったことから、パッケージ管理のコマンドが異なったり、コンテナ内では systemd が 使えなかったりと、多少勝手が異なりましたが、何とか動かすことができました.
Docker 化 できたので、これで何も恐れることなく Try & Error できます. いざ、いろいろなシーンに合わせて光を変える挑戦へ!

花粉症対策 - 来年の自分へ宛てた手紙

ようやく花粉が少なくなってきた、気もしますが、まだまだヒノキにやられ花粉症のありとあらゆる症状が出て大変… 最近の薬はよくなってきたと聞くのですが故あって薬は使えないので、もうどうにもなりません orz
そんな中、新しい対策 グルタミン がかなり効いているので メモ & 毎年 対策に出遅れて困っている自分の来年へのメッセージ. 聞いた話、なんとなくやっていたことは忘れてしまうが、一生懸命書いたものは覚えていることを期待して.
※ あくまでも個人の所感・メモであり、症状の改善等を保証するものではありませんし、お体に合わないこともあり得ますので同様の方法を取られる場合は自己責任でお願いします. (個人のブログなので改めて書くことではないと思いますが…)

#1: 10月ごろから、毎日 “ヨーグルト” を 食べる

-- Azriton、キミはいつも出遅れているのだが、毎日ヨーグルトを食べることは花粉症対策として良い方法だ. 朝でも夜でもいい、とにかく 1日 1回ヨーグルトを食べるんだ. 種類は問わない食べやすいものを選び、継続することが大切だ. よく覚えておいて来年こそは冬が始まるころにはヨーグルトの日々を送ろう.

最近は機能性表示食品が増えてきました. 花粉症に効果があるとするヨーグルトも増えています. そういったものを選ぶのもよいでしょうし、食べやすい物でもよいでしょう. とにかく冬頃から継続的にヨーグルトを食べることで症状を抑えることができます.
この対策は半年ぐらい前から始める必要があるので、ついつい出遅れてしまったり、途中で止めてしまうのが難点だったりもします. とはいえ日々の食事と考えるとコスパは良いのかもしれません.

ちゃんと毎日ヨーグルトを食べていたころは 明治ブルガリアヨーグルト でした. 冷凍のブルーベリーなどを添えて. 春には自分でも驚くほど花粉症の効果がなかったことを覚えています. なんで続けられなかったかなぁ~

明治ブルガリアヨーグルトは花粉症対策をうたっていませんが、まず何よりも腸内環境を整えることが一番名だと思います. 最近では機能性表示食品で花粉症対策をうたっているものもあるので、そちらを選ぶのも手だと思います.

またヨーグルトメーカーを使うことで家庭でヨーグルトを作ることもできます. 最近は、だいぶ値段を抑えたメーカーも出てきたので、よりコスパを求めることができますね.

ヨーグルトメーカー

#2: 1月ごろから、”アレルケア”

-- Azriton、キミは また ヨーグルトのタイミングを逃したのだろう. しかたがない、年明けから始められる対策だ. カルピス健康通販のアレルケアだ. これなら錠剤のサプリだから、寝る前の水と一緒に飲める.

アレルケア「L-92乳酸菌」配合サプリ、こちらはアレルギーに効く乳酸菌をうたっています. もちろん、花粉症にも効果があるとのこと.
サプリとはいえ乳酸菌なので、こちらも中長期的な対策が必要です. 普段からサプリをとっている方は継続に問題ないかと思いますが、うっかりとか、めんどくさいとか…
これも効果を実感できたのに、なんで続けなかったかなぁ~ きっと当時はアマゾンで買えなかったら、ということにしておこう. ← 違う!

アレルケア

#3: 花粉を感じ始めたら、”アレルシャット 花粉イオンでブロック”

-- Azriton、キミは またしても対策を怠った. もう対処しかない. 花粉を感じ始めたら摂取しないようにブロックすることだ. 対処では何もしないよりはマシというレベルではあるだろうが… あと、マスクはするべきだ. どんなに嫌いでも!

対策を怠ってしまったら、もう対処しかない. 策は無いのだ…
ということで、マスクをして、眼鏡をして、とガードするしかないのですが、最近は付けないマスクということで、イオンでブロックできるらしいです.

花粉症は体内に入った花粉量が影響するのだとかで、とにかく体内に入れないこと. 少しでも感じ始めたらブロックするのが良いでしょう. イオンでどのくらいブロックできるのかわかりませんが、マスク嫌いで、どんなに花粉症がつらくてもマスクしない無謀な挑戦にも、何もしないよりはマシなぐらいには応えてくれました.

なお個人の所感ではありますが、スプレー式より、ポンプ式のが最後までしっかりつかえてよかったです. スプレー式はガスが抜けて最後まで使い切れなかった感(使い切ってたのかもしれませんが、缶を振るとシャプシャプして悔しかった)がありました.
ところで、花粉をブロックできるなら、インフルエンザとかも対処できるのかな?

付けないマスク

#4: 出遅れて花粉症の症状に困ったら、”グリコのグルタミン”

-- Azriton、もうダメだ… 対策を忘れたキミに未来は無い…
が、Azriton、キミは新しい方法を入手した. そう グルタミン だ. 花粉症が発火してからの対処として使え、即効性もある. 今のところ最強の武器を手に入れたのだ. きっと来年も対策ができていないであろう、未来のキミに伝えるとしよう.

年々 対策を忘れ、そして悪化していく花粉症の中(って、悪化するなら対策すべきなのですが)、ほとほと困っているところを助けていただくツイートが!

藁をもすがる思いで アミノ酸プロスペック グルタミンパウダー を 購入. こちらは乳酸菌も入っているから、少しでも効用が増えることを期待して. そして、5g 飲んだところで、なんと 3分もしないうちにスッキリ! あれだけ困っていた花粉症の症状がおさまりました. 凄い!! (※ 個人の感想です)

3~5時間ぐらいで効果がなくなり元通りですが、十分な効果です. アミノ酸なので副作用もないのだとか. (各々の体質や、併せ呑みとかで影響も変わると思うので自己責任で)
どうしても効果が得られない日もありますが、格段に日常の過ごしやすさが変わりました. これは助かります. @bik__bo さん、ありがとうございます!

朝飲んでから出かけても、昼過ぎから夕方には効果が切れてしまうので、携帯が必要なので 薬包紙、パラピン を 買ってみました. 錠剤やカプセルを携帯するケースは売っているのですが、粉薬を携帯する商品ってなかなかない物ですね… 今回は “中: 105 x 105” を 買いましたが 5g だと、ちょっとギリギリな感じだったので、”大: 120 x 120” でもいいかもしれません.

薬包紙の折り方は こちら “説明図 薬包紙の折り方 - 薬包紙 - Wikipedia

グルタミン

その他

常に、”体を温めること”

体が冷えると症状が悪化する気がします. よく温めるとよいでしょう.

SAKE、”SAKE を 我慢” だ

-- Azriton、キミには無理な話だろう… だから、あえて語るまい. ただ、ひとつだけ言っておくと SAKE を 呑んだ後はグルタミンの効果は期待できない. それだけだ.


-- Azriton、未来のキミは花粉症対策ができているだろうか. それとも相も変わらず対処法を探しているのだろうか. 未来のキミが、この記事にたどりつけていることを祈り、そして花粉症に悩んでいないことを祈る.

ということで、文章として書いておけば、少しでも記憶に残っていて、将来の対策と対処に役に立っていることを期待して、ポスト.

同じ症状で困っている方、何かの役に立つ情報になれば幸いです. とはいえ医者でもなんでもないので、あくまでも ご参考程度&自己責任で見ていただければと.