Created
January 25, 2020 17:30
-
-
Save javichur/3abbf932ea73ce1c7b6eafed9a7d8b16 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const https = require('https'); | |
const mode = 'prod'; // dev or 'prod' | |
const clientID = 'xxx'; // obtenido de consola web de Alexa developers. | |
const clientSecret = 'xxx'; // obtenido de consola web de Alexa developers. | |
let tokenGlobal = null; // se usa para enviar notificaciones. Dura 1h. Se rellena en notify(). | |
// Ejemplo de envío de una notificación | |
const who = 'cake'; | |
const userId1 = 'amzn1.ask.account.xxx'; | |
const apiEndpoint = getApiEndpoint(userId1); | |
notify(userId1, 'ALERT', who, apiEndpoint); | |
// TODO: se ha simplificado este método para el ejemplo. Implementar según instrucciones antes | |
// de llevarlo a producción. | |
// Devuelve 'api.amazonalexa.com', 'api.eu.amazonalexa.com' o 'api.fe.amazonalexa.com' | |
function getApiEndpoint(userId) { | |
// Recuperar de base de datos la url base de la API, según la región del user. | |
// Solución posible: guardar en base de datos esta info cuando el user abre nuestra skill: | |
// handlerInput.requestEnvelope.context.System.apiEndpoint; | |
return 'api.eu.amazonalexa.com'; | |
} | |
async function notify(userId, eventType, message, apiEndpoint) { | |
if (tokenGlobal == null) { | |
tokenGlobal = await getToken(); | |
} | |
return sendEvent(eventType, tokenGlobal, userId, message, apiEndpoint); | |
} | |
function getProactiveOptions(token, postLength, apiEndpoint) { | |
return { | |
hostname: apiEndpoint.replace('https://', ''), // 'api.amazonalexa.com', api.eu.amazonalexa.com (Europe) api.fe.amazonalexa.com (Far East) | |
port: 443, | |
path: `/v1/proactiveEvents/${mode && mode === 'prod' ? '' : 'stages/development'}`, // mode: global var | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
'Content-Length': postLength, | |
Authorization: `Bearer ${token}`, | |
}, | |
}; | |
} | |
function getProactivePostData(eventType, userId, message) { | |
switch (eventType) { | |
case 'ALERT': | |
return getAlertMessageEvent(userId, message); | |
} | |
} | |
function getAlertMessageEvent(userId, productNameExpired) { | |
const timestamp = new Date(); | |
const expiryTime = new Date(); | |
expiryTime.setMinutes(expiryTime.getMinutes() + 60); | |
const referenceId = `SampleReferenceId${new Date().getTime()}`; // cross reference to records in your existing systems | |
const eventJson = { | |
timestamp: timestamp.toISOString(), | |
referenceId, | |
expiryTime: expiryTime.toISOString(), | |
event: { | |
name: 'AMAZON.MessageAlert.Activated', | |
payload: { | |
state: { | |
status: 'UNREAD', | |
freshness: 'NEW', | |
}, | |
messageGroup: { | |
creator: { | |
name: productNameExpired, | |
}, | |
count: 1, | |
urgency: 'URGENT', | |
}, | |
}, | |
}, | |
relevantAudience: { | |
type: 'Unicast', | |
payload: { | |
user: userId, | |
}, | |
}, | |
}; | |
return eventJson; | |
} | |
// ---------------------------------------------------------------------------- | |
function getTokenOptions(postLength) { | |
// const TokenPostData = getTokenPostData(); | |
return { | |
hostname: 'api.amazon.com', | |
port: 443, | |
path: '/auth/O2/token', | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/x-www-form-urlencoded', | |
'Content-Length': postLength, // TokenPostData.length | |
}, | |
}; | |
} | |
function getTokenPostData() { | |
return `grant_type=client_credentials&client_id=${clientID}&client_secret=${clientSecret}&scope=alexa::proactive_events`; | |
} | |
// const TokenPostData = 'grant_type=client_credentials&client_id=amzn1.application-oa2-client.45690dc26b6848419d11e3c3e51c4c76&client_secret=5571d04619803b123fc305f0b2a8b3ac4f91504f512c2faed7165ca54356aaff&scope=alexa::proactive_events'; | |
async function getToken() { | |
console.log('Entrando en getToken()'); | |
return new Promise((resolve) => { | |
const TokenPostData = getTokenPostData(); | |
const req = https.request(getTokenOptions(TokenPostData.length), (res) => { | |
res.setEncoding('utf8'); | |
let returnData = ''; | |
res.on('data', (chunk) => { returnData += chunk; }); | |
res.on('end', () => { | |
console.log('onEnd() en getToken()'); | |
const tokenRequestId = res.headers['x-amzn-requestid']; | |
// console.log(`Token requestId: ${tokenRequestId}`); | |
resolve(JSON.parse(returnData).access_token); | |
}); | |
}); | |
console.log('Write() en getToken()'); | |
req.write(TokenPostData); | |
req.end(); | |
}); | |
} | |
// ---------------------------------------------------------------------------- | |
async function sendEvent(eventType, token, userId, message, apiEndpoint) { | |
return await new Promise((resolve) => { | |
const ProactivePostData = JSON.stringify(getProactivePostData(eventType, userId, message)); | |
console.log(`\nProactivePostData\n${JSON.stringify(JSON.parse(ProactivePostData), null, 2)}\n-----------`); | |
const ProactiveOptions = getProactiveOptions(token, ProactivePostData.length, apiEndpoint); | |
console.log(`ProactiveOptions\n${JSON.stringify(ProactiveOptions, null, 2)}`); | |
const req = https.request(ProactiveOptions, (res) => { | |
res.setEncoding('utf8'); | |
if ([200, 202].includes(res.statusCode)) { | |
// console.log('successfully sent event'); | |
console.log(`requestId: ${res.headers['x-amzn-requestid']}`); | |
} else { | |
console.log(`Error https response: ${res.statusCode}`); | |
console.log(`requestId: ${res.headers['x-amzn-requestid']}`); | |
if ([403].includes(res.statusCode)) { | |
console.log(`userId ${userId}\nmay not have subscribed to this event.`); | |
} | |
} | |
let returnData; | |
res.on('data', (chunk) => { returnData += chunk; }); | |
res.on('end', () => { | |
// console.log(`return headers: ${JSON.stringify(res.headers, null, 2)}`); | |
resolve(`sent event ${eventType}`); | |
}); | |
}); | |
req.write(ProactivePostData); | |
req.end(); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment