7
3

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.

IoTLTAdvent Calendar 2018

Day 6

Alexaに頼むとFANZAから動画を検索してくれるやつ(Alexa SDK V2で)

Last updated at Posted at 2018-12-05

こんばんは、さっきまでAVでVJしたいなと思ってFANZAでWEBスクレイピングしたりサンプル動画を無限に取得してました。
スクリーンショット 2018-12-06 7.12.49.png

これを応用して、

Alexa、キーワードのえっちぃ動画を紹介してと頼んだら紹介してくれるやつを作ります
書きながら作ります。ほんとはdialogflowとgoogle homeでやりたいところですが
google homeをもっていませんのでAlexaでやります。誰かください。
せっかくなのでAlexa SDK V2で作ります。
あとなんか久々にlambdaを触ったらレイヤー機能というものがあったので使います

##Lambda関数を作ろう
どうやらSDKV2はローカルに落としてきて、入れてあげないといけないみたいです。
なのでとりあえず設計図からalexa-skill-kit-sdk-factskillを選んで
こんな感じでlambda関数を作成します。
スクリーンショット 2018-12-05 22.58.30.png

##SDKV2を入れよう(レイヤーを使って)
Lambdaにいつのまにか登場していたレイヤー機能がすごい便利!!
他の関数から呼び出せる関数みたいなイメージです。
これさえあれば10MB制限でインラインエディタ使えないみたいなこともない!!
ということでSDKV2レイヤーを作ります

$ mkdir sdkv2
$ cd sdkv2
$ yarn add ask-sdk
$ cd ..
$ zip -r nodejs.zip nodejs

というZIPを作成し
Lambda > layer > レイヤーの作成

スクリーンショット 2018-12-06 6.36.54.png

リクエストモジュールも使うのでついでにリクエストモジュールレイヤーも作っておいてください

基本関数.js
const alexa = require('ask-sdk');
const request = require(`request`);
//const iconvLite = require('iconv-lite');

let skill;
exports.handler = async function (event, context) {
    if (!skill) {
      skill = alexa.SkillBuilders.custom()
        .addRequestHandlers(LaunchRequestHandler,SerchHandler)
        .create();
    }
    return skill.invoke(event);
}

const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
    },
    handle(handlerInput) {
        return handlerInput.responseBuilder
            .speak('ウェルカム!')
            .getResponse();
    }
};

テンプレートテストから Alexa Start Session を選択し、実行してみよう!

スクリーンショット 2018-12-06 6.42.04.png **動いた!!**

#Alexaのスキルを作ります
スクリーンショット 2018-12-06 6.44.18.png

こんな感じのインテントを作ります。
searchqueryを使いたかったのですが、日本語対応してないみたいでビルドエラーおきたのでactorで妥協・・・

エンドポイントの設定とかはググってください

#FANZA APIを使おう

スクリーンショット 2018-12-06 7.03.02.png

FANZAのAPIめちゃくちゃ充実してて、適当にリクエスト投げてあげるだけでなんでもできちゃいます。
アフィリエイトIDが必要なので、取得して使ってみてください

#できた

スクリーンショット 2018-12-06 7.00.30.png

現状キーワード検索して一番上をひっぱってきてるだけです。
echobotディスプレイに対応したりLINEにサンプル動画送ってくれたり、次へっていったら次の動画になったりしたかったのですが、それはおいおい

最終的なコードです。

index.js
const alexa = require('ask-sdk');
const request = require(`request`);
//const iconvLite = require('iconv-lite');

let skill;
exports.handler = async function (event, context) {
    if (!skill) {
      skill = alexa.SkillBuilders.custom()
        .addRequestHandlers(LaunchRequestHandler,SerchHandler)
        .create();
    }
    return skill.invoke(event);
}

const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
    },
    handle(handlerInput) {
        return handlerInput.responseBuilder
            .speak('ウェルカム!')
            .getResponse();
    }
};

const SerchHandler = {
    //サーチハンドラ
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
            && handlerInput.requestEnvelope.request.intent.name === 'FANZAintent';
    },
    handle(handlerInput) {
        //console.log(handlerInput.requestEnvelope.request.intent.slots.actor.value)
        let keyword = handlerInput.requestEnvelope.request.intent.slots.actor.value
        const opts = {
            url: "https://api.dmm.com/affiliate/v3/ItemList?api_id=" + process.env.APPID + "&affiliate_id=" + process.env.AFFILIATEID + "&site=FANZA&service=digital&floor=videoa&hits=1&sort=date&keyword=" + encodeURIComponent(keyword) + "&output=json",
            headers: {
                "Content-type": "charset=UTF-8",
            },
            json: true
        }
        //この辺から検索
        return new Promise((resolve, reject) => {
            doRequest(opts).then((body) => {
                if(body.result.items[0].title != undefined){
                    var title = body.result.items[0].title
                    console.log(title)
                    resolve(handlerInput.responseBuilder
                        .speak(title)
                        .getResponse())
                }
                else{
                    reject(handlerInput.responseBuilder
                        .speak('取得できませんでした')
                        .getResponse())
                }
            })
        })
    }
}

//resolve返せるリクエストにしてあげる関数
function doRequest(options) {
  return new Promise(function (resolve, reject) {
    request(options, function (error, res, body) {
      if (!error && res.statusCode == 200) {
        resolve(body);
      } else {
        reject(error);
      }
    });
  });
}

SDK V1 では以下のようにインテントごとに処理をしていましたが

node.js
const handlers = {
    'hogeintent' : function() {
        //hogehoge
    },

V2では各ハンドラの入り口で処理をするみたいです

node.js
const hogeIntentHandler = {
    canHandle(handlerInput) {
        // インテント名がhogeIntentの時に処理する
        return handlerInput.requestEnvelope.request.type === 'IntentRequest'
            && handlerInput.requestEnvelope.request.intent.name === 'hogeIntent';
    },
    handle(handlerInput) {
        // 処理の内容
    }
};

利点として同一インテント名に対するハンドラをまとめて処理できたり、処理わけが簡単だったりします。

[日本語Alexa] Alexa SDK for Node.js Ver2入門(その1)はじめの一歩
https://dev.classmethod.jp/cloud/alexa-sdk-v2-first/

が参考になりました。

#まとめ
IoTじゃなくてVUIになってしもた

7
3
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
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?