OOO DynamoDB
CheckOutOfOfficeHours
index.mjs /* Amplify Params - DO NOT EDIT ENV REGION STORAGE_JHOOODDB_ARN STORAGE_JHOOODDB_NAME STORAGE_JHOOODDB_STREAMARN Amplify Params - DO NOT EDIT */ import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; import { DynamoDBDocumentClient, QueryCommand } from '@aws-sdk/lib-dynamodb'; const client = new DynamoDBClient({ region: process.env.REGION }); const dynamodb = DynamoDBDocumentClient.from(client); const partitionKeyName = 'extension'; async function getOOOHours(agentExtension) { console.log(`getOOOHours(${agentExtension})`); const queryParams = { TableName: process.env.STORAGE_JHOOODDB_NAME, KeyConditionExpression: '#ext = :ext', ExpressionAttributeNames: { '#ext': partitionKeyName }, ExpressionAttributeValues: { ':ext': agentExtension } }; console.log(queryParams); let isOOO = false; let transferPhoneNumber = ''; let hasCallForward = false; let oooMessage = ''; try { const data = await dynamodb.send(new QueryCommand(queryParams)); console.log(data); if (!data.Items || data.Items.length < 1) { console.log('No OOO entry found for ' + agentExtension); } else { const record = data.Items[0]; console.log(record); const now = new Date().setTimeToNow(); const startDate = new Date(record.startDate); const endDate = new Date(record.endDate); if (now > startDate && now < endDate) { console.log(`currently (${now.toISOString()}) within OOO period of ${startDate.toISOString()} - ${endDate.toISOString()}`); isOOO = true; transferPhoneNumber = record.transferPhoneNumber.replace(/\s/g, ''); hasCallForward = record.hasCallForward; oooMessage = `${record.oooMessage} `; } else { console.log(`not currently (${now.toISOString()}) within OOO period of ${startDate.toISOString()} - ${endDate.toISOString()}`); } } } catch (error) { const errorMsg = 'Could not load items: ' + error; console.error(errorMsg); throw new Error(errorMsg); } return { isOOO, transferPhoneNumber, hasCallForward, oooMessage }; } export const handler = async (event) => { return await getOOOHours(event.Details.Parameters.agentExtension); };
OOOAPI
app.mjs import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; import { DynamoDBDocumentClient, ScanCommand, QueryCommand, GetCommand, PutCommand, DeleteCommand } from '@aws-sdk/lib-dynamodb'; import serverlessExpress from '@vendia/serverless-express'; import bodyParser from 'body-parser'; import express from 'express'; const dynamoClient = new DynamoDBClient({ region: process.env.TABLE_REGION }); const dynamodb = DynamoDBDocumentClient.from(dynamoClient); const usersLookupTable = process.env.USERS_LOOKUP_TABLE; let tableName = 'oooTable'; if (process.env.ENV && process.env.ENV !== 'NONE') { tableName = tableName + '-' + process.env.ENV; } const userIdPresent = false; // TODO: update in case is required to use that definition const partitionKeyName = 'extension'; const partitionKeyType = 'S'; const sortKeyName = ''; const sortKeyType = ''; const hasSortKey = sortKeyName !== ''; const path = '/items'; const UNAUTH = 'UNAUTH'; const hashKeyPath = '/:' + partitionKeyName; const sortKeyPath = hasSortKey ? '/:' + sortKeyName : ''; // declare a new express app const app = express(); app.use(bodyParser.json()); // Enable CORS for all methods app.use(function (req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', '*'); next(); }); // convert url string param to expected Type const convertUrlType = (param, type) => { switch (type) { case 'N': return Number.parseInt(param); default: return param; } }; /******************************** * HTTP Get method for list objects * ********************************/ app.get(path, async function (req, res) { console.log('hello from normal get'); const params = { TableName: tableName, Select: 'ALL_ATTRIBUTES', }; try { const data = await dynamodb.send(new ScanCommand(params)); res.json({ data: data.Items }); } catch (err) { res.json({ error: 'Could not load items: ' + err.message }); } }); app.get(path + hashKeyPath, async function (req, res) { console.log('hello from lambda get'); console.log('path: ', path, 'hashKeyPath: ', hashKeyPath); let keyValue; if (userIdPresent && req.apiGateway) { keyValue = req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH; } else { try { keyValue = convertUrlType(req.params[partitionKeyName], partitionKeyType); } catch (err) { res.statusCode = 500; return res.json({ error: 'Wrong column type ' + err }); } } // comment const queryParams = { TableName: tableName, KeyConditionExpression: '#pk = :pkval', ExpressionAttributeNames: { '#pk': partitionKeyName }, ExpressionAttributeValues: { ':pkval': keyValue } }; try { const data = await dynamodb.send(new QueryCommand(queryParams)); console.log(data.Items); res.json(data.Items); } catch (err) { res.statusCode = 500; res.json({ error: 'Could not load items: ' + err.message }); } }); /***************************************** * HTTP Get method for get single object * *****************************************/ app.get(path + '/object' + hashKeyPath + sortKeyPath, async function (req, res) { console.log('hello from lambda get object'); var params = {}; if (userIdPresent && req.apiGateway) { params[partitionKeyName] = req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH; } else { try { params[partitionKeyName] = convertUrlType(req.params[partitionKeyName], partitionKeyType); } catch (err) { res.statusCode = 500; return res.json({ error: 'Wrong column type ' + err }); } } if (hasSortKey) { try { params[sortKeyName] = convertUrlType(req.params[sortKeyName], sortKeyType); } catch (err) { res.statusCode = 500; return res.json({ error: 'Wrong column type ' + err }); } } const getItemParams = { TableName: tableName, Key: params }; try { const data = await dynamodb.send(new GetCommand(getItemParams)); if (data.Item) { res.json(data.Item); } else { res.json(data); } } catch (err) { res.statusCode = 500; res.json({ error: 'Could not load items: ' + err.message }); } }); /****************************************** * HTTP Get method for users extension * ******************************************/ // comment app.get(path + '/username' + hashKeyPath + sortKeyPath, async function (req, res) { console.log('hello from lambda get object extension'); console.log('path: ', path, 'hashKeyPath: ', hashKeyPath, 'sortKeyPath', sortKeyPath); var params = {}; if (userIdPresent && req.apiGateway) { params['username'] = req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH; } else { try { params['username'] = convertUrlType(req.params['extension'].toUpperCase(), partitionKeyType); } catch (err) { res.statusCode = 500; return res.json({ error: 'Wrong column type ' + err }); } } if (hasSortKey) { try { params[sortKeyName] = convertUrlType(req.params[sortKeyName], sortKeyType); } catch (err) { res.statusCode = 500; return res.json({ error: 'Wrong column type ' + err }); } } const email = `${params.username}`; const getItemParams = { TableName: usersLookupTable, IndexName: 'username-extension-index', KeyConditionExpression: 'username = :hkey', ExpressionAttributeValues: { ':hkey': email.toUpperCase(), } }; console.log(getItemParams); try { const data = await dynamodb.send(new QueryCommand(getItemParams)); if (data.Item) { res.json(data.Item); } else { res.json(data); } } catch (err) { console.log(err); res.statusCode = 500; res.json({ error: 'Could not load items: ' + err.message }); } }); /************************************ * HTTP put method for insert object * ************************************/ app.put(path, async function (req, res) { console.log('hello from lambda put'); if (userIdPresent) { req.body['userId'] = req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH; } const putItemParams = { TableName: tableName, Item: req.body }; try { const data = await dynamodb.send(new PutCommand(putItemParams)); res.json({ success: 'put call succeed!', url: req.url, data: data }); } catch (err) { res.statusCode = 500; res.json({ error: err.message, url: req.url, body: req.body }); } }); /************************************ * HTTP post method for insert object * ************************************/ app.post(path, async function (req, res) { console.log('hello from lambda post'); if (userIdPresent) { req.body['userId'] = req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH; } const putItemParams = { TableName: tableName, Item: req.body }; try { const data = await dynamodb.send(new PutCommand(putItemParams)); res.json({ success: 'post call succeed!', url: req.url, data: data }); } catch (err) { res.statusCode = 500; res.json({ error: err.message, url: req.url, body: req.body }); } }); /************************************** * HTTP remove method to delete object * **************************************/ app.delete(path + '/object' + hashKeyPath + sortKeyPath, async function (req, res) { console.log('hello from lambda delete'); var params = {}; if (userIdPresent && req.apiGateway) { params[partitionKeyName] = req.apiGateway.event.requestContext.identity.cognitoIdentityId || UNAUTH; } else { try { params[partitionKeyName] = convertUrlType(req.params[partitionKeyName], partitionKeyType); } catch (err) { res.statusCode = 500; return res.json({ error: 'Wrong column type ' + err }); } } if (hasSortKey) { try { params[sortKeyName] = convertUrlType(req.params[sortKeyName], sortKeyType); } catch (err) { res.statusCode = 500; return res.json({ error: 'Wrong column type ' + err }); } } const removeItemParams = { TableName: tableName, Key: params }; try { const data = await dynamodb.send(new DeleteCommand(removeItemParams)); res.json({ url: req.url, data: data }); } catch (err) { res.statusCode = 500; res.json({ error: err.message, url: req.url }); } }); app.listen(3000, function () { console.log('App started'); }); // Export handler for AWS Lambda via @vendia/serverless-express export const handler = serverlessExpress({ app });
updateTTLStream
/* Amplify Params - DO NOT EDIT
ENV
REGION
STORAGE_JHOOODDB_ARN
STORAGE_JHOOODDB_NAME
STORAGE_JHOOODDB_STREAMARN
Amplify Params - DO NOT EDIT */
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, UpdateCommand } from '@aws-sdk/lib-dynamodb';
import { unmarshall } from '@aws-sdk/util-dynamodb';
const client = new DynamoDBClient({ region: process.env.REGION });
const dynamodb = DynamoDBDocumentClient.from(client);
export const handler = async (event) => {
console.log(JSON.stringify(event, null, 2));
for (const record of event.Records) {
console.log(JSON.stringify(record, null, 2));
if (record.eventName === 'REMOVE') {
console.log('Skipping deleted record.');
continue;
}
const newImage = unmarshall(record.dynamodb.NewImage);
console.log(newImage);
const parsedEndDate = new Date(newImage.endDate);
if (isNaN(parsedEndDate.getTime())) {
console.log('endDate is missing or invalid - skipping.');
continue;
}
// Add 1 week (in milliseconds) to endDate, then convert to Unix epoch seconds for TTL
const oneWeekMs = 7 * 24 * 60 * 60 * 1000;
const ttl = Math.floor((parsedEndDate.getTime() + oneWeekMs) / 1000);
console.log(`new ttl: ${ttl}`);
try {
console.log('Saving updated record.');
const result = await dynamodb.send(new UpdateCommand({
TableName: process.env.STORAGE_JHOOODDB_NAME,
Key: { extension: newImage.extension },
UpdateExpression: 'SET #ttl = :val',
ExpressionAttributeNames: { '#ttl': 'ttl' },
ExpressionAttributeValues: { ':val': ttl },
ReturnValues: 'ALL_NEW'
}));
console.log(result);
} catch (error) {
console.error(error);
}
}
return 'Successfully processed DynamoDB record';
};