AWS
python3
lambda
APIGateway
Alexa

AlexaからIFTTT経由でショッピングリストの情報を取得すると文字化けするのをなんとかしたかった

※注意:解決していません。
※2018/10/15追記 こっちで解決できました

Amazon Echo Dotを購入して買い物リストを便利に使っていたのですが、
2018年の4月あたりから文字化けを起こすようになり
すっかり使えなくなったまま放置していました。

01.PNG

が、先日コメントをいただいたりしちゃったので改めて調べてみると
やはり同時期からAlexaからIFTTT経由でショッピングリストの情報を取得すると文字化けする事象が相次いでいることがわかりました。
[Alexa 文字化け]で検索するとわんさかでてきます。
※我が家のログを確認すると4/2から文字化けし始めています。

一回便利になったあと不便になりつつも放置していたのですが、コメントももらったことだし、せっかくなのでどうにかしようと思って仕組みを考えてみました。

想定

といっても、文字化けしているんだから変換してやりゃいいんだろ。
逆に言えば、どう考えても変換処理をかまさないといけないので、何で実装するのが楽かを考える。

■入口部分

Alexaからショッピングリストの情報を取得している部分
〇課題
 IFTTTをつかってトリガー+情報を取得しているが、この情報が文字化けしている
・案1:文字化けしない別のツールでトリガーを取得
→他のツールで取得できたとしても、文字化けしてないかどうかわからん。
・案2:文字化けで取得されるのはあきらめて、以降の処理で変換する

他のツールをこれから探すのもめんどくさいので案2でいくことにする。

■出口部分

取得したショッピングリストの情報をWunderlistへ登録する
〇課題
 文字化けした情報をそのまま登録しているため、登録できた文字列が視認できない

・案1:文字化けしたものを変換してからWunderlistへ登録する

ここはもう変換するぐらいしか案がない。

決定した方針としては、
IFTTT上では文字化けしちゃうんは仕方ないので後続処理で何とか戻そう!


具体化

変換させたいがIFTTT上では処理を作成するのは無理っぽいなので、後続で何かしらの変換をかませられるようにする。
とすると、簡単そうな案としてLambdaでやってみることにする。
※Alexaのスキルを作ったりしているので、AWSの契約が既にあるというのもある。

構成案としては以下となる
Alexa→IFTTT→Webhooks→AWS API GateWay→AWS Lambda→Wunderlist

※makerで作るのかなと思っていろいろ調べてたけど、単純にPOSTするだけならWebhooksで問題なし。

よくよく考えたらAWS上にWindowsのインスタンスもあるのでそこで受信してもよかったのかなと思わなくもない。
が、とりあえず今回は一回も使ったことのない[AWS API GateWay→AWS Lambda]の組み合わせを触ってみたかったのでやってみる。

うまくいくかどうかはまだわからない。

■まずはLambdaとGatewayの使い方を理解。

以下を参考にしてサンプルを作成して流れを理解。

〇ゼロから作りながら覚えるAPI Gateway環境構築
https://dev.classmethod.jp/cloud/aws/getting-start-api-gateway/

本家のチュートリアルよりもすげーわかりやすかったです。

■呼び出せているか確認したい

CloudWatch
https://dev.classmethod.jp/cloud/aws/lambda-and-cloudwatch/

これはいまいちうまくいかない。
ここで時間をかけてるとやる気がなくなってしまうので飛ばして先へ進む。
※たぶん中途半端なロールを使ったのが間違っていたんだと思われる。

■構成案に組み込んでみる。

サンプルでAPIキーを使ってみたけど、IFTTT上のWebhooksだと設定できそうな感じがない。
仕方がないので認証は無しにしておく。
IFTTTからはアイテム名をJSON形式にして飛ばす。
image.png

飛んできた結果が見たい

飛ばした結果もしたくなったけど、CloudWatchにログがきれいにでないのでちょっと困る。
なんとなくの思いつきでSlackに飛ばしてみる。

以前別のことがしたくてAPIでSlackに投稿できるようにしてたのでそれを流用。
といっても有効にしてたTOKENを流用してGETでCALLしただけなので処理としては以下。

import urllib.request
url = "http://xxxx/xxxx"
urllib.request.urlopen(url)

だけで飛ばせるかと思ったけど、日本語だとUnicodeEncodeErrorとなるのでエンコード処理も入れる。

quote_item_name = urllib.parse.quote(get_item_name)

確認用のフローが完成した時点でのLambdaソース

import json

print('Loading function')


def lambda_handler(event, context):
    print("Received event: " + json.dumps(event, indent=2))
    get_item_name = event['item']
    print(get_item_name)


    # 送信確認用にSlackへ飛ばす
    #送信先URL
    token = "your slack token"
    channel = "target channnel id"
    url = "https://slack.com/api/chat.postMessage?token={}&pretty=1&channel={}&text={}"
    import urllib.parse
    quote_item_name = urllib.parse.quote(get_item_name)
    print(quote_item_name)
    url = url.format(token, channel, quote_item_name)

    #API実行
    import urllib.request
    urllib.request.urlopen(url)
    return "res:OK"

ここで大事なことに気が付く

これでIFTTTで設定して連携確認としてAlexaの買い物リストに登録してCheckしてみると想定通り文字化けしたものがSlackへ登録されるのがわかる。
そう何も進んでいないのである。。

そして、アレクサから飛んできている文字化けはなんの文字コードなのか?

文字化けしているなら変換してあげればいいじゃんと思っていたけども、何から何に戻してあげればいいのかが不明すぎる。

文字化け解決支援
https://ltside.com/enc/

どれにも該当せず。

本日の結論

変換後だけだと欠損しているのかも。。。
・・・要するに現状ではお手上げ。

スキルで解決させるしかないのかなぁ。。
Lambda部分ができてしまえば入口をIFTTT経由からカスタムスキル経由にするだけなのでそこまでむつかしくもないだろうし。

ということで、結局今回出来上がったのは
IFTTTからWebhooksを使用してAWS Lambdaを呼び出してSlackにテキストを投稿する
という本来の想定とはまるで違うものでした。。