/**
* App ID for the skill
*/
var APP_ID = undefined; //replace with "amzn1.echo-sdk-ams.app.[your-unique-value-here]";
/**
* The AlexaSkill prototype and helper functions
*/
var AlexaSkill = require('./AlexaSkill');
var request = require('request');
var moment = require('moment');
var Promise = require('bluebird');
var WunderlistSDK = require('wunderlist');
var linkingCard = "You must link Task Master to your Wunderlist account. From the Alexa app, go to Skills -> Your Skills -> Task Master -> Link Account";
var linkingSpeech = "You must use the Alexa app to link task master to your Wunderlist account before this skill will work";
var linkingTitle = "Account Linking Required";
/**
* TaskMaster.is a child of AlexaSkill.
* To read more about inheritance in JavaScript, see the link below.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#Inheritance
*/
var TaskMaster = function () {
AlexaSkill.call(this, APP_ID);
};
// Extend AlexaSkill
TaskMaster.prototype = Object.create(AlexaSkill.prototype);
TaskMaster.prototype.constructor = TaskMaster;
TaskMaster.prototype.eventHandlers.onSessionStarted = function (sessionStartedRequest, session) {
console.log("TaskMaster.onSessionStarted requestId: " + sessionStartedRequest.requestId + ", sessionId: " + session.sessionId);
// any initialization logic goes here
};
TaskMaster.prototype.eventHandlers.onLaunch = function (launchRequest, session, response) {
console.log("TaskMaster.onLaunch requestId: " + launchRequest.requestId + ", sessionId: " + session.sessionId);
if(typeof session.user.accessToken !== 'undefined'){
var speechOutput = "Welcome to Task Master. You can say, Whats due today?, Review my inbox, add pickup dry cleaning to inbox.";
var repromptText = "You can say, Whats due today?, Review my inbox, add pickup dry cleaning to inbox.";
response.ask(speechOutput, repromptText);
}else{
response.linkAccountCard(linkingSpeech, linkingTitle, linkingCard);
}
};
TaskMaster.prototype.eventHandlers.onSessionEnded = function (sessionEndedRequest, session) {
console.log("TaskMaster.onSessionEnded requestId: " + sessionEndedRequest.requestId+ ", sessionId: " + session.sessionId);
// any cleanup logic goes here
};
TaskMaster.prototype.intentHandlers = {
// register custom intent handlers
"AddTaskIntent": function (intent, session, response) {
if(typeof session.user.accessToken !== 'undefined'){
// If list name is not provided, task is added to the inbox
wunder.getListId(session.user.accessToken, intent.slots.ListName.value || null)
.then(function(listId){
return wunder.addTask(session.user.accessToken, intent.slots.TaskName.value, listId);
})
.catch(function(errorResponse){
response.tell(errorResponse);
})
.then(function(){
response.tellWithCard("I've added "+ intent.slots.TaskName.value +" to your Wunderlist!", "Item added to Wunderlist", "I've added "+ intent.slots.TaskName.value +" to your Wunderlist!");
})
.catch(function(){
response.tell("I had a problem saving your task");
});
}else{
response.linkAccountCard(linkingSpeech, linkingTitle, linkingCard);
}
},
"CheckListIntent": function (intent, session, response) {
if(typeof session.user.accessToken !== 'undefined'){
// Capture listName
var sessionAttributes = {};
var listName = intent.slots.ListName.value;
// determine what the listId is
wunder.getListId(session.user.accessToken, intent.slots.ListName.value || null)
.then(function(listId){
console.log("listId: ", listId);
// return all open tasks for list
return wunder.inbox(session.user.accessToken, listId);
})
.then(function(result){
console.log("Wunderlist Response: ", result);
var tasks = result.length;
console.log("Length of response: ", tasks);
sessionAttributes.inbox = result;
session.attributes = sessionAttributes;
switch(tasks){
case 0:
response.tell("The "+listName+" list is empty.");
break;
case 1:
response.ask("You have "+tasks+" item in your "+listName+" list, Would you like to hear the details?");
break;
default:
response.ask("You have "+tasks+" items in your "+listName+" list, Would you like to hear the details?");
}
})
.catch(function(failResponse){
response.tell(failResponse);
});
}else{
response.linkAccountCard(linkingSpeech, linkingTitle, linkingCard);
}
},
"DueIntent": function(intent, session, response){
if(typeof session.user.accessToken !== 'undefined'){
console.log(intent.slots.date);
var sessionAttributes = {};
var listName;
console.log(typeof intent.slots.ListName.value);
if(typeof intent.slots.ListName.value !== 'undefined'){
console.log('defined!');
listName = intent.slots.ListName.value;
}else{
console.log(intent.slots);
listName = 'inbox';
}
wunder.getListId(session.user.accessToken, listName)
.then(function(listId){
return wunder.due(session.user.accessToken, intent.slots.date.value, listId);
})
.then(function(due){
var taskCount = due.length;
sessionAttributes.due = due;
session.attributes = sessionAttributes;
switch(taskCount){
case 0:
response.tell("none of your tasks are due for "+ listName);
break;
case 1:
response.ask("You have "+taskCount+" task in your "+listName+" list that is due, Would you like to hear the details?");
break;
default:
response.ask("You have "+taskCount+" tasks in your "+listName+" list that are due, Would you like to hear the details?");
}
})
.catch(function(failResponse){
response.tell(failResponse);
});
}else{
response.linkAccountCard(linkingSpeech, linkingTitle, linkingCard);
}
},
"AMAZON.YesIntent": function(intent, session, response){
if(typeof session.user.accessToken !== 'undefined'){
console.log("session: ", session.attributes);
var sessionAttributes = session.attributes;
var i;
var speechOutput = "";
var repromptText = "";
if(typeof sessionAttributes.due !== "undefined"){
var due = sessionAttributes.due;
for(i = 0; i < due.length; i++){
speechOutput += "Task "+(i+1)+", "+due[i].title+", ";
}
response.tell(speechOutput);
}else if(typeof sessionAttributes.inbox !== "undefined"){
var inbox = sessionAttributes.inbox;
for(i = 0; i < inbox.length; i++){
speechOutput += "Task "+(i+1)+", "+inbox[i].title+", ";
}
response.tell(speechOutput);
}else{
response.tell("Sorry something went wrong");
}
}else{
response.linkAccountCard(linkingSpeech, linkingTitle, linkingCard);
}
},
"AMAZON.HelpIntent": function (intent, session, response) {
response.ask("You can say review my inbox. You can say what is due in my inbox today, this week, or this month. You can say add task pickup dry cleaning.");
},
"AMAZON.StopIntent": function (intent, session, response) {
response.tell("Goodbye");
}
};
// Create the handler that responds to the Alexa Request.
exports.handler = function (event, context) {
// Create an instance of the TaskMaster.skill.
var taskMaster = new TaskMaster();
taskMaster.execute(event, context);
};
// Object literral containing Wunderlist API calls
var wunder = {
inbox: function(accessToken, listId){
var wunderlistAPI = new WunderlistSDK({
'accessToken': accessToken,
'clientID': 'ee32a7e1b5c063b28e8f'
});
console.log("listID received: ", listId);
return new Promise(function(resolve, reject){
wunderlistAPI.http.tasks.forList(listId)
.done(function (taskData, statusCode) {
console.log("listData: ", taskData);
resolve(taskData);
})
.fail(function(){
reject();
});
});
},
due: function(accessToken, date, listId){
var wunderlistAPI = new WunderlistSDK({
'accessToken': accessToken,
'clientID': 'ee32a7e1b5c063b28e8f'
});
// determine date format
var reDay = /^(\d+-\d+-\d+)$/;
var reWeek = /^\d+-([W]\d+)$/;
var reMonth = /^(\d+-\d+)$/;
var startDate, endDate;
if(reDay.test(date)){
startDate = moment(date);
endDate = moment(date);
}else if(reWeek.test(date)){
var weekNum = reWeek.exec(date);
startDate = moment().week(weekNum[1]).startOf('week');
endDate = moment().week(weekNum[1]).endOf('week');
}else if(reMonth.test(date)){
startDate = moment().month(date).startOf('month');
endDate = moment().month(date).endOf('month');
}
var dueToday = [];
var i;
return new Promise(function(resolve, reject){
wunderlistAPI.http.tasks.forList(listId)
.done(function(tasksData, statusCode){
var tasks = tasksData;
for(var i = 0; i < tasks.length; i++){
if(typeof tasks[i].due_date !== 'undefined' && moment(tasks[i].due_date).isBetween(startDate, endDate, 'day')){
dueToday.push(tasks[i]);
console.log("matched task");
}else if(typeof tasks[i].due_date !== 'undefined' && moment(tasks[i].due_date).isSame(startDate)){
dueToday.push(tasks[i]);
console.log("matched task");
}else{
console.log("no matches", tasks[i].due_date);
}
}
resolve(dueToday);
});
});
},
getListId: function(accessToken, listName){
console.log("listName:", listName);
if(listName === null){
listName = "inbox";
}
var wunderlistAPI = new WunderlistSDK({
'accessToken': accessToken,
'clientID': 'ee32a7e1b5c063b28e8f'
});
return new Promise(function(resolve, reject){
wunderlistAPI.http.lists.all()
.done(function (lists) {
console.log("returned lists: ", lists);
for(i = 0; i < lists.length; i++){
var title = lists[i].title;
if(title.toLowerCase() === listName.toLowerCase()){
resolve(lists[i].id);
}
}
reject("I can't find a list named "+ listName +", to add your task to. Please try again.");
})
.fail(function(){
reject("I ran into a problem looking up your to do list");
});
});
},
addTask: function(accessToken, taskName, listId){
var wunderlistAPI = new WunderlistSDK({
'accessToken': accessToken,
'clientID': 'ee32a7e1b5c063b28e8f'
});
return new Promise(function(resolve, reject){
wunderlistAPI.http.tasks.create({'list_id': listId, 'title': taskName})
.done(function(taskData, statusCode){
resolve();
})
.fail(function(){
reject();
});
});
}
};
Comments