Python 3.6 64bit の インストール

Python を 使うことになり、初めてなので インストール・メモ. ちょっとしたメモでも仲間が増えたときに、こんな感じで~って説明できるので残しておくことにしたことはないですね.

作業環境

  • Windows 10 64bit
  • Python 3.6 64bit

バージョン と インストールする環境について検討

今回は Windows 10 に Python を インストールします. Windows 10 だと、Bash on Ubuntu on Windows で Linux 環境に Python を 入れられるはずですが、いきなり複雑なことをするとトラブル時に対応できなくなりそうなので、まずは Windows 10 に 直接インストールし、Python に 慣れてきたら Bash on Ubuntu on Windows を 使ったりとアレンジしたいと思います.

Pyhton は 2.x と 3.x があります. 今回はまったく新しく使い始めるため、ありがたいことに過去のしがらみなし、ということで 2017年7月現在 最新 の 3.6.2 を 使いたいと思います. また、開発・実行環境の Windows 10 が 64bit なので、Python も 64bit を 選択したいと思います. Pyhton の ライブラリ によっては 32bit しか用意がないなど、64bit を 使うと困ることもあるみたいですが、これは切り替えが簡単なので、困るまでは 64bit で 行ってみます.

インストール手順

Python の トップページ や Downloads の メニュー、Downloads ページ にある [Download Python 3.6.2] は、OS を 自動判定して適切なインストーラーをダウンロードさせてくれるのですが、こちらからだと 32bit 版 が ダウンロードされます. そのため こちらからはダウンロードはせず、Windows 版のダウンロード・ページから 64bit 版 を 選択してダウンロードします.

Windwos 版 の ダウンロード・ページ Python Releases for Windows | Python.org https://www.python.org/downloads/windows/ へ アクセスします.
こちらから Windows x86-64 executable installer を ダウンロードします.

チェックサムの確認は Python 3.6.2 - 2017-07-17 リンクから Python Release Python 3.6.2 | Python.org 画面へ行き、画面中段の Files に MD5 Sum が 記載されています. 今回ダウンロードした Windows x86-64 executable installer4377e7d4e6877c248446f7cd6a1430cf です.
確認方法は Windows PowerShell 4.0 以降の Get-FileHash コマンドを使います.

1
2
3
4
5
c:\> powershell Get-FileHash -Algorithm MD5 c:\python-3.6.2-amd64.exe
Algorithm Hash
--------- ----
MD5 4377E7D4E6877C248446F7CD6A1430CF

ダウンロードした python-3.6.2-amd64.exe を ダブルクリックして、インストーラーを起動します.

PATH は 追加しておいた方が便利なので、[Add Python 3.6 to PATH] に チェックをつけます.
インストール・オプションを指定したいので [Customize installation] を クリックしてインストールを進めます.

Optional Features では、特に変更せず [Next] ボタンをクリックして進みます.

Advanced Options では、以下を設定し、[Install] ボタンをクリックします.

  • [Install for all users] を チェック
  • [Precompile standard library] を チェック (Install for all users チェックすると自動で付く)
  • [Customize install location] を 必要に応じて設定 (私は C:\Develop 以下にまとめるのが好きなので設定)

インストールが完了しました.
[Disable path length limit] を すると、Windows の パスの長さ(ドライブ・レター、フォルダ、ファイル名) が 260文字に制限されている のを解除できます. Windows 10 で、この MAX_PATH が 解除できるようになったため Python 3.6 で 追加された機能(Issue 27731: Opt-out of MAX_PATH on Windows 10 - Python tracker) になります.
パスが長くなるようでしたら設定します. 今回は長くなる想定が無いので選択しませんでした.

動作確認

コマンド プロンプト で バージョンを出力してみます. コマンドは python --version もしくは python -V です. 大文字で -V であることに注意です. インストール・オプションで [Add Python 3.6 to PATH] に チェックしたので、パスが通っているため、直接 python コマンドが実行できます.

1
2
3
4
5
6
7
8
c:\> echo %PATH%
C:\Develop\sdk\Python36\;C:\Develop\sdk\Python36\Scripts\; ...(省略)
c:\> python --version
Python 3.6.2
c:\> python -V
Python 3.6.2

小文字の場合は 詳細報告 (verbose) モード の オプション指定になり、インタプリタに入ります. 突然大量の出力があり、その後は プロンプトが c:\ のような Windows から >>> に 変わり、Python 命令を受け付ける状態になります.
1 + 1 のような命令を入力すると、実行結果が返ってきます.
一方で命令にないことをすると、エラーが返ります.
終了するには Ctrl + Z キーを押す、もしくは exit() を 実行します. exit で 実行すると Use exit() or Ctrl-Z plus Return to exit と返ってきます.
なお、Ctrl + CKeyboardInterrupt です.
突然の出力とインタプリタの起動で思わぬ動きをしてビックリしますが、落ち着いて exit() しましょう.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
c:\> python -v
import _frozen_importlib # frozen
import _imp # builtin
import sys # builtin
... (省略)
>>>
>>> 1 + 1
2
>>>
>>> python -V
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'python' is not defined
>>>
>>> (※ Ctrl+C)
KeyboardInterrupt
>>>
>>> exit()


インストーラーのダウンロードで 32bit が 自動選択されるという現象がありましたが、それ以外は特に難しいことなくインストールができますね. 後はバージョン情報を出力させる際に、つい python -v と 小文字を使う癖があるようで、いきなりの詳細報告モードのインタプリタで毎回焦ります (;^_^A
何はともあれインストールができたので、バリバリ開発にいそしみ、面白いものができたらアップしていけたらと思います.

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

Slack の Free Plan でも、API から 2FA の 設定状況が見れることが分かりました. それを使ってボットが 2FA の 設定状況を監視しレポートするようにしたいと思います.

作業環境

  • Slack
  • Node.js 6.11.0 LTS
  • Botkit 0.5.2

通知方法の検討

セキュリティに関することなのでキッチリ警告していきたいものの、あまり頻度が高いのも考え物. 加減が難しいところです…
今回は、未設定者に DM で 週1回 月曜日 の 14時 に 通知し、Slack の チーム管理者 向けに #sandbox へ 未設定者一覧の支援依頼のメッセージを出力します. (未設定者を公開で晒すのも微妙なので、実際には管理者用チャンネルとかにした方が良いかもしれないですね)

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
const Botkit = require('botkit');
const cron = require('cron');
const controller = Botkit.slackbot();
const channel = '#sandbox';
const url = 'https://get.slack.help/hc/ja/articles/204509068-2%E8%A6%81%E7%B4%A0%E8%AA%8D%E8%A8%BC%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B';
controller.spawn({
token: process.env.bot_access_token
}).startRTM((err, bot, payload) => {
new cron.CronJob({ cronTime: '00 00 14 * * 1', timeZone: 'Asia/Tokyo', start: true, onTick: () => {
let admins = [];
let reports = [];
bot.api.users.list({ token: process.env.access_token }, (err, response) => {
for (let member of response.members) {
if (member.deleted || member.is_bot || member.name == 'slackbot') {
continue;
}
if (member.is_admin) {
admins.push(member.id)
}
if (!member.has_2fa) {
reports.push(member.id)
}
}
if (reports.length != 0) {
bot.say({
channel: channel,
text: `2FA の 未設定 ${reports.length} 人、み~つけた! ` +
'管理者の人~、設定の仕方を助けてくださいませ. ' +
`設定の説明は <${url}|こっち> に あるよ. \n` +
`未設定者: ${createMentions(reports)}`
});
}
for (let report of reports) {
bot.startPrivateConversation({ user: report }, (response, convo) => {
convo.say('Slack の 2FA(Two Factor Authentication / 二要素認証) 設定をしてくださいな. ' +
`設定の説明は <${url}|こっち> に あるよ. \n` +
`あとは ${bot.team_info.name} Slack チーム の 管理者 ${createMentions(admins)} に 聞くのもありだね.`
);
});
}
});
}});
function createMentions(userIds) {
let mentions = [];
for (let userId of userIds) {
mentions.push(` <@${userId}>`);
}
return mentions;
}
});

まずは、cron モジュールを使ったボットにするため controller.spawn().startRTM() 内で処理を実装するボットを作ります. この辺りは Slack の ボット で 定時アクション で 作ったものになります.

続いて定期処理を作るために new cron.CronJob()cronTime: '00 00 14 * * 1' と 処理、その他オプションを渡します. cronTime は 秒 分 時 日 月 曜日 なので、'00 00 14 * * 1' は 左3つで14時ちょうど、右3つで毎週月曜日となります.

14行目からメインのコードになります. チーム管理ユーザ と レポート対象ユーザ を 保持するための配列を用意します.
続いてユーザー一覧を取得する Slack API を 前回の通り bot.api.users.list()token に OAuth で 権限を与えられている方のトークンを渡します.

API から取得した ユーザー一覧を for-of で 回しながら adminsreports の 配列を作成していきます. 削除済み と ボット と “slackbot” は チェック不要なので continue します. “slackbot” さん は、なぜかボット判定が効かないので名前で判別しています.
続いて、is_admin で チーム管理者の判定をします. オーナーも is_admintrue で 管理者に入ります. (もし外すなら is_primary_owneris_owner で オーナー判定できます)
最後に今回の肝である has_2fa で レポート対象ユーザーの判定をします. 通常は無いはずですが、管理者が 2FA 未設定のケースを想定して is_adminhas_2faelse if ではなく if で 分けてます.

32行目から、管理者向けの通知になります.
レポート対象ユーザー reports が 空でなければ bot.say() で 指定チャンネルへ未設定者のリストを通知します.
※ 今回 const channel = '#sandbox'; と チャンネル名指定してますが、正式には https://slack.com/api/channels.list?token=[API_TOKEN] で 調べた ID を 使うべきです

42行目から、未設定者に対する DM になります.
未設定者の配列 は for-of で 回し、DM を 送る bot.startPrivateConversation() を 呼び出します.
bot.say() のように、直接メッセージを出せず、Conversation の 形式で送ります. そのため bot.startPrivateConversation() の 第2引数で渡すコールバック関数で受け取る 第2引数 convo に対して say() を 呼び出します.

通知!

まずは管理者向けにチャンネルへポストされた方になります. 今回は実験用なので #sandbox に 晒されてます.

続いて DM を 受けている側になります. ちゃんと相談先のチーム管理者へのメンションも出ています. 安心ですね.


これで、2FA 未設定者を ×炙り出して晒す ◎検出して通知 できるようになりました.
有料プランのように強制はできないものの、毎週通知されることと、管理者へもフォローするよう通知が行くので、おのずと設定されることに期待したいと思います.

もし強化するとしたら、全チャンネルから BAN して、チャンネル参加を拒否する鬼ボットにするとかですかね… なんか面白そうだなぁ. 作ってみたくなってきた.

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日ごとのことで、すぐに見れないのは残念ですが、まぁ そうですよね. もっと早くから設定しないとですね. いろいろ書いてみたいことが多くて、ブログ環境回りがついつい後回しになってしまいました…
とりあえず表示されるのを楽しみに待ちたいと思います.