FactoryをつかってAlexaの処理をDRYに書く
APIを呼び出す系のスキルなどでは、権限確認などの処理をどのハンドラーにも書かないといけないということがあります。 この例では、アカウントリンクのアクセストークンの有無を確認し、存在しない場合にアカウントリンクを促す処理 […]
広告ここから
広告ここまで
目次
APIを呼び出す系のスキルなどでは、権限確認などの処理をどのハンドラーにも書かないといけないということがあります。
const ListMessageIntentHandler: RequestHandler = {
canHandle(handlerInput) {
return isMatchedIntent(handlerInput, 'ListMessageIntent');
},
async handle(handlerInput) {
const token = Alexa.getAccountLinkingAccessToken(handlerInput.requestEnvelope)
if (!token) {
return handlerInput.responseBuilder
.speak('Please link your Alexa account to AAA account.')
.withLinkAccountCard()
.getResponse();
}
const client = new SomeAPI({token})
const items = await client.messages()
const message = items.member.map(item => item.name).join(' and ')
return handlerInput.responseBuilder
.speak('This is your messages. ' + message)
.reprompt('What is next?')
.getResponse()
},
};
const ListItemIntentHandler: RequestHandler = {
canHandle(handlerInput) {
return isMatchedIntent(handlerInput, 'ListItemIntent');
},
async handle(handlerInput) {
const token = Alexa.getAccountLinkingAccessToken(handlerInput.requestEnvelope)
if (!token) {
return handlerInput.responseBuilder
.speak('Please link your Alexa account to AAA account.')
.withLinkAccountCard()
.getResponse();
}
const client = new SomeAPI({token})
const items = await client.list()
const message = items.member.map(item => item.name).join(' and ')
return handlerInput.responseBuilder
.speak('This is your items. ' + message)
.reprompt('What is next?')
.getResponse()
},
};
この例では、アカウントリンクのアクセストークンの有無を確認し、存在しない場合にアカウントリンクを促す処理が重複しています。
インテントの数が増えると、これを毎回書くのが煩雑です。
そこでFactoryパターンで共通化してみましょう。
FactoryでRequestHandlerを作る
Factoryパターンで、必要なRequestHandlerを作ってもらう形にします。まずはFactoryを用意しましょう。
class SomeServiceRequestHandlerFactory {
public static create(intentName: string, handle: (token: string, handlerInput: Alexa.HandlerInput) => Promise<Response> ): RequestHandler {
return {
canHandle(handlerInput: Alexa.HandlerInput) {
return isMatchedIntent(handlerInput, intentName)
},
async handle(handlerInput) {
const token = Alexa.getAccountLinkingAccessToken(handlerInput.requestEnvelope)
if (!token) {
return handlerInput.responseBuilder
.speak('Please link your Alexa account to AAA account.')
.withLinkAccountCard()
.getResponse();
}
return handle(token, handlerInput)
}
}
}
}
あとは作りたいReqestHandlerをこのFactoryで作るだけです。
const ListMessageIntentHandler: RequestHandler = SomeServiceRequestHandlerFactory.create(
'ListItemIntent',
async (token, handlerInput) => {
const client = new SomeAPI({token})
const items = await client.messages()
const message = items.member.map(item => item.name).join(' and ')
return handlerInput.responseBuilder
.speak('This is your messages. ' + message)
.reprompt('What is next?')
.getResponse()
},
};
const ListItemIntentHandler: RequestHandler = SomeServiceRequestHandlerFactory.create(
'ListItemIntent',
async (token, handlerInput) => {
const client = new SomeAPI({token})
const items = await client.list()
const message = items.member.map(item => item.name).join(' and ')
return handlerInput.responseBuilder
.speak('This is your items. ' + message)
.reprompt('What is next?')
.getResponse()
}
)
かなり見通しがよくなりましたね。