Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

こんばんは、さっきまで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になってしもた

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away