【Amazon Echo入門#6】AlexaちゃんとTwitterアカウントを連携してみる

前々回くらいにやったゴミ出しの日をAlexaちゃんに教えてもらうとしたりとかをちゃんと作ろうとすると、当然住んでいる地域でゴミ出しの曜日はバラバラなので、ユーザーごとに異なる結果を返す必要があります。

ともすると、外部アプリケーションと連携してアカウント認証の仕組みが必要になるので、そのあたりを調べてみたい。今回は一旦はAlexaちゃんとTwitterアカウントを紐付けるところまでやってみます。

参考: Amazon AlexaのAccount Linkingを使ってAmazon EchoからTwitterに書き込ませてみる

サーバ側の準備

認証を通すには、AlexaちゃんとTwitterの間でアカウント連携を仲介する必要があります。サンプルコードがそのまま使えるのでセットアップしていきましょう。

https://github.com/bignerdranch/developing-alexa-skills-solutions/tree/master/5_accountLinking

とりあえずソースコードをローカルに持ってくる。

$ git clone git@github.com:bignerdranch/developing-alexa-skills-solutions.git

ローカルで起動してみて正しく動くことを確認しておく。

$ cd developing-alexa-skills-solutions/5_accountLinking/solution/server
$ ruby -v
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin14]
$ bundle install
$ thin start --ssl -p 3000

画面を開く

https://localhost:3000/app

thinはじめて使ったけど、sslも出来るみたい。ただしssl警告とかキーチェーン認証とかガンガンでてくる。とりあえず無視して進めば画面は開けた。

サーバ側画面

次はこれをHerokuにデプロイして、Alexaちゃんからも見えるようにします。Herokuアプリ(alexa-twitter-connect)は既に登録済みの状態。

$ cd ..
$ cp -r server ~/source_code/alexa-twitter-connect-server
$ cd ~/source_code/alexa-twitter-connect-server

$ git init
$ git add .
$ git commit

$ git remote add heroku https://git.heroku.com/alexa-twitter-connect.git
$ git push heroku master

$ heroku open

サーバ画面(Heroku)

Twitter Appの準備

OAuth認証の仕組みを使うので、Twitter Application ManagementからApplicationを作る必要があります。普通にOAuth認証と同じ感じでOK。

  • Website: https://alexa-twitter-connect.herokuapp.com/app
  • Callback URL: https://alexa-twitter-connect.herokuapp.com/oauth/callback

Twitter Settings

登録が出来たら、Keys and Access Tokensタブを開き、Consumer Key (API Key)とConsumer Secret (API Secret)をメモっておく。

Alexa側

いつものようにAlexaのスキルを作成します。基本的な作成の仕方は【Amazon Echo入門#1】Alexaちゃんに今日履いているパンツの色を答えさせるでやっているのでそちらを参考に。

https://developer.amazon.com/

インテントスキーマ・カスタムスロットタイプ・サンプル発話の設定は、上記GitHubのサンプルコードのsolution/skill/airportinfo/resources配下のtxtファイルをコピペすればOK。

インテントスキーマ

{
  "intents": [
    {
      "slots": [
        {
          "name": "AIRPORTCODE",
          "type": "FAACODES"
        }
      ],
      "intent": "tweetAirportStatusIntent"
    },
    {
      "slots": [
        {
          "name": "AIRPORTCODE",
          "type": "FAACODES"
        }
      ],
      "intent": "airportInfoIntent"
    }
  ]
}

カスタムスロット

  • タイプ: FAACODES
  • 値:
    • AAC
    • AAE
    • AAF
    • …省略

サンプル発話

tweetAirportStatusIntent  tweet {AIRPORTCODE}
tweetAirportStatusIntent  tweet delay {AIRPORTCODE}
tweetAirportStatusIntent  tweet status {AIRPORTCODE}
tweetAirportStatusIntent  tweet info {AIRPORTCODE}
tweetAirportStatusIntent  tweet delay info {AIRPORTCODE}
tweetAirportStatusIntent  tweet status info {AIRPORTCODE}
tweetAirportStatusIntent  tweet for {AIRPORTCODE}
tweetAirportStatusIntent  tweet delay for {AIRPORTCODE}
tweetAirportStatusIntent  tweet status for {AIRPORTCODE}
tweetAirportStatusIntent  tweet info for {AIRPORTCODE}
tweetAirportStatusIntent  tweet delay info for {AIRPORTCODE}
tweetAirportStatusIntent  tweet status info for {AIRPORTCODE}
airportInfoIntent {AIRPORTCODE}
airportInfoIntent flight {AIRPORTCODE}
airportInfoIntent airport {AIRPORTCODE}
airportInfoIntent delay {AIRPORTCODE}
airportInfoIntent flight delay {AIRPORTCODE}
airportInfoIntent airport delay {AIRPORTCODE}
airportInfoIntent status {AIRPORTCODE}
airportInfoIntent flight status {AIRPORTCODE}
airportInfoIntent airport status {AIRPORTCODE}
airportInfoIntent info {AIRPORTCODE}
airportInfoIntent flight info {AIRPORTCODE}
airportInfoIntent airport info {AIRPORTCODE}
airportInfoIntent delay info {AIRPORTCODE}
airportInfoIntent flight delay info {AIRPORTCODE}
airportInfoIntent airport delay info {AIRPORTCODE}
airportInfoIntent status info {AIRPORTCODE}
airportInfoIntent flight status info {AIRPORTCODE}
airportInfoIntent airport status info {AIRPORTCODE}
airportInfoIntent for {AIRPORTCODE}
airportInfoIntent flight for {AIRPORTCODE}
airportInfoIntent airport for {AIRPORTCODE}
airportInfoIntent delay for {AIRPORTCODE}
airportInfoIntent flight delay for {AIRPORTCODE}
airportInfoIntent airport delay for {AIRPORTCODE}
airportInfoIntent status for {AIRPORTCODE}
airportInfoIntent flight status for {AIRPORTCODE}
airportInfoIntent airport status for {AIRPORTCODE}
airportInfoIntent info for {AIRPORTCODE}
airportInfoIntent flight info for {AIRPORTCODE}
airportInfoIntent airport info for {AIRPORTCODE}
airportInfoIntent delay info for {AIRPORTCODE}
airportInfoIntent flight delay info for {AIRPORTCODE}
airportInfoIntent airport delay info for {AIRPORTCODE}
airportInfoIntent status info for {AIRPORTCODE}
airportInfoIntent flight status info for {AIRPORTCODE}
airportInfoIntent airport status info for {AIRPORTCODE}

続いてアカウントリンクの設定。

  • 認証 URL: https://alexa-twitter-connect.herokuapp.com/oauth/request_token?vendor_id=<VENDOR_ID>&consumer_key=<TWITTER_CONSUMER_KEY>&consumer_secret=<TWITTER_CONSUMER_SECRET>
    • VENDOR_IDは、直後の「リダイレクトURL」に表示されているvendorId=xxxxxxxの部分をコピペする。
  • ドメインリスト: api.twitter.comを追加しておく
  • 認可の承諾タイプ: 簡易版のImplicit Grantにしておく

エンドポイントのデフォルトは、今回はアカウントリンクだけ試したいので、とりあえず適当なLambdaのARN IDを入れておく。カイジのとか入れておいた。

アカウントリンク

サーバに環境変数を設定する

Herokuの環境変数にTwitterアプリのキー情報など、必要な値をセットします。

$ heroku config:set CONSUMER_KEY=<Twitterで取得したConsumer key>
$ heroku config:set CONSUMER_SECRET=<Twitterで取得したConsumer secret>
$ heroku config:set VENDOR_ID=<Alexa側で自動的に発行されるID、上記参照>
$ heroku config:set CALLBACK_URL=https://alexa-twitter-connect.herokuapp.com/oauth/callback
$ heroku config:set SESSION_SECRET=<サンプルコードのままでOK>

試してみる

Alexaのポータルへ行ってスキルを開くと言語が違うと言われて先に進めず試せない。。

そう、なにしろ、そもそもぼくはAmazon Echo実機を持っていないのである。

Alexa言語が一致しない

実機がなければ日本語設定も出来ないのだけど、echosim.ioというWEB上でAlexaのシミュレーションが出来るサービスがある。Alexaのポータルではこれも有効みたい。

だがしかし、このサービスはamazon.jpのアカウントでは利用できず、amazon.comのアカウントが必要。仕方ないので、Amazonアカウントも、開発者コンソールも、amazon.comの方で取り直して、Alexaのスキルも作り直した。

※この手順はAmazon Echo実機が入手出来れば必要ないです。

よし、いけたいけた。この画面では開発中のスキルも試すことが出来ます。

Alexa Skills

諸々問題なくいけばこのようにリンク成功の画面が表示されます。

Twitterリンク成功

ハマった点

どうしてもAlexaポータルからTwitter連携をしようとすると、認可は通るものの、なぜかPINコードが表示されてしまい、どうにも連携出来ない状態でハマりました。

結論から言うとHeroku側の環境変数設定忘れでした。heroku config:set HOGEHOGE=xxxxxxxxxxxxxxxってやつ。参考元の記事にはこの手順は書いてなかったのでご注意を。



mofmof inc.では、一緒に仕事をしてくださるエンジニアを募集しております。
募集要項については以下をご確認ください。
興味を持っていただけましたら、ぜひ一度ゆっくりお話出来れば嬉しいです。

募集一覧(wantedly)
https://www.wantedly.com/companies/mof-mof/projects

mofmofは何をしたいのか
https://www.mof-mof.co.jp/recruit/want-to-do

mofmof入社ガイド
http://everyday.mof-mof.co.jp/entry/2017/01/25/141201