3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Alexaに買いたいものを伝えて共有の買い物リストに追加:文字化け対応編

Posted at

前段

スキルアワードのお知らせが改めてメールで来てた。
http://alexaskillawards.jp/

審査や公開前のスキルでも構わないみたいなので
せっかくなのでスキル経由でwunderlistに追加できるようなスキルを作ってみることにした。
※完成しても自分用のベータのみにする予定。

Alexaとwunderlistとの連携の経緯については以下の過去を参照。
Alexaに買いたいものを伝えて共有の買い物リストに追加
AlexaからIFTTT経由でショッピングリストの情報を取得すると文字化けするのをなんとかしたかった

今回のAlexaスキルの目的

以前Alexaの買い物リストへ登録した際にIFTTT経由でwunderlistにも登録させるような仕組みを構築した。
が、ある日突然文字化けしちゃうようになった。
そこでAlexaの買い物リスト経由ではなく、カスタムスキル経由でダイレクトに登録させるようにしてみる。
イメージとしてはこんな感じ
Alexa→Lambda→IFTTT→wunderlist

Alexa Skill作成

久々にAlexa Skillのコンソールをみたら、
最初に作ったときにはなかったような機能がいくつかできていて割と簡単にできるようになっている印象。
当時はこのコンソールはβ版としてあったような気はするが、その時よりも格段に使いやすくなってる。

image.png
・スキル名などを設定し「カスタム」を選択して次へ。

image.png

image.png
・スキルのトリガー名を指定する

image.png
・インテントスロットなんてあった?

image.png
・ここでLambda側のエンドポイントを指定する

AlexaSkillの基本的な仕組みさえわかっていれば、なんとなくでもスキルのガワは簡単に作れるレベルになっている気がする。
で、なんとなく作ってみた。

手間取った部分

スキルID

よくわからなかったがLambda側にここのスキルIDを設定しておかないとダメだった。

Lambda側でスロットのデータを取得する方法がわからない

しばし悩んだが、難しくはなかった。
こんな感じ。
[intent.slots.add_item.value]
.valueまで必要だった。
これはどちらというとNode.jsのお作法がわかってなかったからなのかもしれない。

ベータテストまでできるようになったが、セッションが終了しない

これはLambda側のスキルの問題だった模様。
おそらくベースにしたサンプルがわるかったと思うのだが、どうやらaskで終わるとセッションを維持する模様。
シンプルなサンプルをベースに実装しなおしたら解消。

この時点でAlexaからカスタムスキルを使って、Lambdaに追加したいアイテム名を投げる処理が完成。
あとはこのアイテムをwunderlistに投げつけてあげればOKだ。

ToWunderlist

APIを使って直接登録することもできるのだが、トークン取得処理などを書くのがめんどくさいので既存の処理のIFTTT経由にのっけてみる。
当初のイメージを少し変えてこんな感じにする。
Alexa→Lambda→IFTTT→Gmail→wunderlist
IFTTT→Gmail→wunderlistの部分はもうあるので、Lambda→IFTTTを作るのを目標にする。

IFTTTのオフィシャルには載っていないのだが、webhookを使えばThat側で受けることもできそう。

https://ifttt.com/maker_webhooks
ここをみてみるとよくわからないのだが、
image.png
[Documentation]をクリックしてみると
image.png
こんなページになる。ここに記載されているURLをトリガーにすることができる。
※データは3つまでしか送れないみたいだが。

ThatとなるAPIが作れたら、API経由でwunderlistで登録できることを確認しておく。

Lambda→IFTTT

Webhook経由でメール登録はOKなことが確認できたら、IFTTTへのPOST処理をLambdaに埋め込む。

var request = require('request');
var options = {
uri: "https://maker.ifttt.com/trigger/towunderlist/with/key/XXXXXXXXX",
headers: {
    "Content-type": "application/json",
},
json: {
    "value1": "param1"
}
};
request.post(options, function(error, response, body){});

単純に考えて、上記あたりの処理になるかと思ったのだが、標準ではrequestが入っていないのでエラーになる。
モジュールを追加したZIPを作ってアップロードしないといけないのだが、それもめんどくさい。

なのでhttpsモジュールでやることにする。
以下を参考にさせてもらった。
https://qiita.com/n0bisuke/items/33a6a6da1d6f455105f9

const https = require("https")
const HOST = `maker.ifttt.com`;
const PATH = `/trigger/towunderlist/with/key/XXXXXXXXX`;

let postData = {
    "value1": "param1"
};

let postDataStr = JSON.stringify(postData);
let options = {
    host: HOST,
    path: PATH,
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    }
};

let req = https.request(options, (res) => {
res.setEncoding('utf8');
res.on('data', (chunk) => {
    console.log('BODY: ' + chunk);
});
});
req.on('error', (e) => {
console.log('problem with request: ' + e.message);
});
req.write(postDataStr);
req.end();

こんな感じ。

完成

これで音声でwunderlistに追加することができるようになりました。
スキルに対するトリガーも必要になるので、
以前のように
「アレクサ、牛乳を買い物リストに追加して」
というような形式ではなく
「アレクサ、ワンダーリストを開いて、牛乳を追加して」
というように長くなってしまったのがちょっと難点。
これを一息で伝えるというのが意外にめんどくさい。
上手いトリガー名が思い浮かべばもう少し楽になるのかもしれない。

もう一つの目的にスキルアワードへの申請は別記事で。
どうやら動作しているところの動画も撮影+Webで参照できるようにしないといけないっぽいのがちょっとめんどくさい。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?