diff --git a/functions/gracedata/index.js b/functions/gracedata/index.js index e0a1cde..ac17133 100644 --- a/functions/gracedata/index.js +++ b/functions/gracedata/index.js @@ -29,12 +29,11 @@ const projectMap = { }; function createTable(tableDef) { - const ensureCreate = dynamodb.createTable(tableDef).promise(); return dynamodb.deleteTable( {'TableName': tableDef['TableName']}) .promise() - .then(ensureCreate) - .catch(ensureCreate); + .then(() => { return dynamodb.createTable(tableDef).promise(); }) + .catch(() => { return dynamodb.createTable(tableDef).promise(); }); }; function populateTable(tableDef, content) { @@ -44,7 +43,7 @@ function populateTable(tableDef, content) { for(item in content) { const kvItem = {}; kvItem[keyField] = {S: item}; - kvItem[valueField] = {S: content[item]} + kvItem[valueField] = {S: content[item]}; items.push({PutRequest: {Item: kvItem}}); }; const requests = {}; @@ -54,6 +53,9 @@ function populateTable(tableDef, content) { exports.handle = function(e, ctx, cb) { createTable(projectsTable) + .catch((err) => { + console.log(err, err.stack); + }) .then(populateTable(projectsTable, projectMap)) .then((data) => { cb(null, {status: 'OK'}); diff --git a/functions/upbot/index.js b/functions/upbot/index.js index e89f032..70e9214 100644 --- a/functions/upbot/index.js +++ b/functions/upbot/index.js @@ -1,7 +1,11 @@ console.log('starting function') const AWS = require('aws-sdk'); const lexmodelbuildingservice = new AWS.LexModelBuildingService({apiVersion: '2017-04-19'}); +const dynamodb = new AWS.DynamoDB({apiVersion: '2012-08-10'}); +/* + Intent slot types +*/ const projectName = { name: 'ProjectName', description: 'The names of all our projects', @@ -15,8 +19,122 @@ const projectName = { {value: 'Manager'} ] }; +const projectRepository = { + name: 'ProjectRepository', + description: 'The url of the project source code repository', + priority: 4 +}; + + +function updateSlotType(tableName, tableAttr, slotType) { + return Promise.all([ + lexmodelbuildingservice + .getSlotType({name: slotType.name, version: "$LATEST"}) + .promise(), + dynamodb + .scan({TableName: tableName}) + .promise() + ]).then((data) => { + console.log('Updating slot type ', slotType.name); + slotType.checksum = data[0].checksum; + + const values = new Array(); + for(item in data[1]['Items']) { + values.push({value: item[tableAttr]['S']}); + } + slotType['enumerationValues'] = values; + + return lexmodelbuildingservice.putSlotType(slotType).promise(); + }).catch((err) => { + console.log( err, err.stack); + }); +}; + + +/** + * Intent slots + */ +const projectNameSlot = { + name: "project", + description: "The name of the project.", + priority: 3, + valueElicitationPrompt: { + maxAttempts: 2, + messages: [ + {contentType: "PlainText", content: "What is the name of the project?"}, + {contentType: "PlainText", content: "Project name please?"}, + {contentType: "PlainText", content: "Project name?"}, + {contentType: "PlainText", content: "What project?"} + ] + }, + sampleUtterances: [ + "Project {project} ", + "App {project} ", + "Webapp {project} ", + "For {project} " + ], + slotConstraint: "Required", + slotType: "ProjectName", + slotTypeVersion: "$LATEST" +}; +const projectRepositorySlot = { + name: 'repository', + description: 'The url of the project source code repository.', + priority: 4, + valueElicitationPrompt: { + maxAttempts: 2, + messages: [ + {contentType: "PlainText", content: "What is the repository for {project}?"}, + {contentType: "PlainText", content: "What is bitbucket url for {project}?"} + ] + }, + sampleUtterances: [ + "In bitbucket {repository} ", + "At {repository} ", + "Webapp {repository} ", + "For {repository} " + ], + slotConstraint: "Required", + slotType: "ProjectRepository", + slotTypeVersion: "$LATEST" +}; + +const rejections = { + messages: [ + {contentType: "PlainText", content: "k thnx bye"}, + {contentType: "PlainText", content: "I have so many stories"}, + {contentType: "PlainText", content: "I'm just a bot and I don't understand everything"}, + {contentType: "PlainText", content: "I didn't understand that. How about a pug?"} + ] +}; + + +/** + * The Intents + */ +const addProject = { + name: 'AddCodeRepositories', + sampleUtterances: [ + 'I have created a new project', + 'We have a new project', + 'A new project has been created', + 'Project {project} is new and its repository is {repository} ' + ], + slots: [projectNameSlot, projectRepositorySlot], + confirmationPrompt: { + maxAttempts: 1, + messages: [ + {contentType: "PlainText", content: "Please confirm that {project} is here {repository}"}, + {contentType: "PlainText", content: "Should I learn that {project} is here {repository}?"} + ] + }, + rejectionStatement: rejections, + fulfillmentActivity: { + type: "ReturnIntent" + } +}; -const intent = { +const getRepository = { name: 'CodeRepositories', sampleUtterances: [ "Where is the source code", @@ -25,45 +143,21 @@ const intent = { "Where is the code for {project} ", "What is the repository for {project} source code " ], - slots: [{ - name: "project", - description: "The name of a project.", - priority: 3, - valueElicitationPrompt: { - maxAttempts: 1, - messages: [ - {contentType: "PlainText", content: "For what project?"}, - {contentType: "PlainText", content: "What project?"} - ] - }, - sampleUtterances: [ - "Project {project} ", - "App {project} ", - "Webapp {project} ", - "For {project} " - ], - slotConstraint: "Required", - slotType: "ProjectName", - slotTypeVersion: "$LATEST" - }], + slots: [projectNameSlot], confirmationPrompt: { maxAttempts: 1, messages: [ {contentType: "PlainText", content: "pls cnfrm"} ] }, - rejectionStatement: { - messages: [ - {contentType: "PlainText", content: "k thnx bye"} - ] - }, + rejectionStatement: rejections, /* - For some reason lex does not like this - conclusionStatement: { - messages: [ - {contentType: "PlainText", content: "Anything else?"}, - {contentType: "PlainText", content: "Can I help with anything else?"} - ], + For some reason lex does not like this + conclusionStatement: { + messages: [ + {contentType: "PlainText", content: "Anything else?"}, + {contentType: "PlainText", content: "Can I help with anything else?"} + ], responseCard: "string" }, */ @@ -72,31 +166,33 @@ const intent = { } }; -exports.handle = function(e, ctx, cb) { - console.log('processing event: %j', e); - - const c1 = lexmodelbuildingservice - .getSlotType({name: projectName.name, version: "$LATEST"}) - .promise() - .then((data) => { - projectName.checksum = data.checksum; - console.log('XXX', data.name, data.checksum); - return lexmodelbuildingservice.putSlotType(projectName).promise(); - }) - .catch(() => {}); - const c2 = lexmodelbuildingservice +function updateIntent(intent) { + return lexmodelbuildingservice .getIntent({name: intent.name, version: "$LATEST"}) .promise() .then((data) => { intent.checksum = data.checksum; - console.log('YYY', data.name, data.checksum); }) - .catch(() => {}); + .catch(() => {}) + .then(() => { + console.log('Updating intent: ', intent.name); + return lexmodelbuildingservice.putIntent(intent).promise(); + }); +}; + +exports.handle = function(e, ctx, cb) { + console.log('processing event: %j', e); + + const st1 = updateSlotType('projects', 'name', projectName); + const st2 = updateSlotType('projects', 'url', projectRepository); + + const i1 = updateIntent(getRepository); + const i2 = updateIntent(addProject); Promise - .all([c1, c2]) + .all([st1, st2]) .then(() => { - return lexmodelbuildingservice.putIntent(intent).promise(); + return Promise.all([i1, i2]) }) .then((data) => { cb(null, data);