Edited at

GoogleHomeをスプラトゥーンアシスタントにする #2 Twitterからステージ情報の取得

More than 1 year has passed since last update.


はじめに

Google Homeを買ったはいいものの、テレビ無し、外出ない、家電使わない自分には少々物足りないので

生活の大半を占めるスプラトゥーンのアシスタントをGoogle Homeには勤めてもらいます。

みたいな事を書いたので、その続きです。

GoogleHomeをDialogflow(旧:API.ai)でスプラトゥーンアシスタントにする


実装する機能

スプラトゥーンは3つのゲームモードがあり、それぞれ時間によってステージが異なります。

確認するにはスマホアプリかまたはゲーム内アナウンスで確認する必要があるので、これをハンズフリーで確認できるようにしたいと思います。

スクリーンショット 2017-10-16 17.55.37.png

実装する機能のイメージ↓


僕「ステージ 〇〇(ゲームモード)

GoogleHome「〇〇のステージは××(ステージ名)です


また、ゲームモードの「ガチマッチ」「リーグマッチ」ではルールが3種類あるのでそれも確認できるようにします。


使用ツール・環境

webhookの置き場にherokuを使用し、

前回とは違い、IFTTTは使用せずDialogflowとwebhookのみで実装します。


ステージ情報の取得

現在配信されているステージ情報を取ってきます。

公式アプリから閲覧できるイカリング2からプロキシをごにょごにょして取ってきてもいいんですが、

【スプラトゥーン2】イカリング2の戦績データをPCブラウザで無理矢理閲覧する

世の中には便利なBotを作っている人がいるのでこちらのBotのツイートから取得しようと思います。

ツイート取得機能は応用が効きそうですしね(イカリングからの取得が面倒そうだからという訳では無いです)


twythonをインストール

TwitterAPIを叩くのに今回はtwythonを使います。

初期設定はこちら参照

Twitter REST APIの使い方

どうせ大した事しないのでtwython使うまでも無い気はしますが...

$pip install twython

スクリプトを書きます。


twython.py

from twython import Twython, TwythonError

APP_KEY = "取得したAPI Key"
APP_SECRET = "取得したAPI Secret"
OAUTH_TOKEN = "取得したAccess Token"
OAUTH_TOKEN_SECRET = "取得したAccess Token Secret"

def getStage(num,mode):
twitter = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
#ツイートを取得したいTwiiterアカウントのID
screen_name = "splatoon2_stage"
results = twitter.get_user_timeline(screen_name=screen_name,count=5)
date = list(filter(lambda s:s != '', results[num]["text"].replace("▼","").replace("、","と").split()))
time = date[1].replace((b'\xef\xbd\x9e').decode('utf-8'),"から")
nawabari = date[3]
gachi_mode = date[4]
gachi_stage = date[5]
league_mode = date[6].replace("リーグ:","モードは")
league_stage = date[7]
if mode == "ナワバリ":
return time + nawabari
elif mode == "ガチマッチ":
return time+"モードは"+gachi_mode+"ステージは"+gachi_stage
elif mode == "リーグマッチ":
return time +league_mode +"ステージは"+ league_stage

if __name__ == '__main__':
print(getStage(0,"ガチマッチ")+"です")


これで、現在のステージ名とガチマッチ・リーグマッチの場合は「ガチホコ」「ガチエリア」「ガチヤグラ」等のゲームモードを出力できるようになりました。

出力例

スクリーンショット 2017-10-16 17.14.47.png

これを後は前回作成したpythonファイルに書き加えればOKです。


webhook-dialogflow.py

from __future__ import print_function

from future.standard_library import install_aliases
install_aliases()

from urllib.parse import urlparse, urlencode
from urllib.request import urlopen, Request
from urllib.error import HTTPError

import json
import os

from flask import Flask
from flask import request
from flask import make_response, jsonify
import gspread
from oauth2client.service_account import ServiceAccountCredentials

from twython import Twython, TwythonError
APP_KEY = "取得したAPI Key"
APP_SECRET = "取得したAPI Secret"
OAUTH_TOKEN = "取得したAccess Token"
OAUTH_TOKEN_SECRET = "取得したAccess Token Secret"

# Flask app should start in global layout
app = Flask(__name__)

@app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json(silent=True, force=True)
result = req.get("result")
parameters = result.get("parameters")
text = ""
if req.get("result").get("action") == "getSpreadSheet":
text = getSpreadSheet(parameters.get("weapon_name"))
if req.get("result").get("action") == "getStage":
text = getStage(0,parameters.get("mode"))+"です"
r = make_response(jsonify({'speech':text,'displayText':text}))
r.headers['Content-Type'] = 'application/json'
return r

def getStage(num,mode):
twitter = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
screen_name = "splatoon2_stage"
results = twitter.get_user_timeline(screen_name=screen_name,count=5)
date = list(filter(lambda s:s != '', results[num]["text"].replace("▼","").replace("、","と").split()))
time = date[1].replace((b'\xef\xbd\x9e').decode('utf-8'),"から")
nawabari = date[3]
gachi_mode = date[4]
gachi_stage = date[5]
league_mode = date[6].replace("リーグ:","モードは")
league_stage = date[7]
if mode == "ナワバリ":
return time + nawabari
elif mode == "ガチマッチ":
return time+"モードは"+gachi_mode+"ステージは"+gachi_stage
elif mode == "リーグマッチ":
return time +league_mode +"ステージは"+ league_stage

def getSpreadSheet(weapon_name):
#
#省略 前回のスクリプト参照
#
return text

if __name__ == '__main__':
port = int(os.getenv('PORT', 5000))

print("Starting app on port %d" % port)

app.run(debug=False, port=port, host='0.0.0.0')


では、次にwebhookを送信するDialogflowの設定に行きましょう。


Dialogflowのセッティング

詳しくは前回のを見て頂くとして、新規に設定する部分を載せます。

前回のBotに機能を追加する場合はIntentsに新しく返答を登録すればOKです。


Intents

Intentsで入力の受け取りや失敗した際の返答を登録します。

新しくstageを作成。CREATE INTENTで新規intentを登録可能です。

スクリーンショット_2017-10-18_22_06_40.png

(成績が前回作成したintent)

今回はユーザーの発言が「ステージ」だった場合にBotが反応し、

「ステージ」の後に続く部分をmodeとして入力で受け取ります。

スクリーンショット 2017-10-16 16.40.24.png

ActionにはgetStageと入力。JSONのこの部分を上記のpythonスクリプトは見て前回のwebhookと分岐させています。

スクリーンショット 2017-10-16 18.06.21.png


Entities

入力として受け取る単語をEntitiesから登録します。

今回もスプラトゥーンのデータベースは無いようなのでポチポチ登録しましょう。

スクリーンショット 2017-10-16 16.40.40.png


Fulfillment

前回と変更点はありません。

webhookを流すurlを入力しておきましょう。

20171012132542.png

これでセッティングは終了です。


テストする

Dialogdlowのコンソール右側にテキストを入力してテストしましょう。

スクリーンショット 2017-10-16 16.40.14.png

ステージが出てきました!

action,parameter valueも問題なさそうですね。


完成

動作の確認はこちらの動画から↓

IMAGE ALT TEXT HERE


おわりに

今回はゲームモードを取得しましたが、先日開催されたフェスやもう1つのゲームモードサーモンランに対応していないのでそこら辺やろうかと思います。

でも別々のTwitterBotから取得するぐらいならイカリングから読み出した方がいい気も…先は長いですね。

スプラトゥーン以外にもTwitterとの連携は便利そうなので使っていきたいです。

良きスプラトゥーンライフを!(フェスは負けました)


参考