Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functionality to start and stop service #14

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a5389e7
Add a modifed_at meta field in users table
thakichowdhury Aug 1, 2019
f8d438a
Create function to toggle a user's activity level
thakichowdhury Aug 1, 2019
36e0dc2
Create util function for making db queries
thakichowdhury Aug 1, 2019
fc04737
Create db action for checking user active state
thakichowdhury Aug 1, 2019
fec7cc3
Update spacing
thakichowdhury Aug 1, 2019
4a2ee4c
Compose db action for checking and toggling, as needed, a user's active
thakichowdhury Aug 1, 2019
37ed224
Add semicolon to end of query
thakichowdhury Aug 1, 2019
e0dfaa4
Change name of twilio message function to place emphasis on sending
thakichowdhury Aug 1, 2019
42f1fbf
Abstracted formatting of phone string to a parent function
thakichowdhury Aug 1, 2019
6cf58fb
Create a function to route messages and change endpoint callback to
thakichowdhury Aug 1, 2019
8c82591
Fix import path for twilioSendMessage
thakichowdhury Aug 1, 2019
8890579
Fix import path for twilioSendMessage
thakichowdhury Aug 1, 2019
349e160
Fix returning field name
thakichowdhury Aug 1, 2019
f15d4bb
Add modified_at field to message insert and return response from db
thakichowdhury Aug 1, 2019
5c6e946
Update message based on message insertion save
thakichowdhury Aug 1, 2019
5be88fb
Pass timestamp value to modified_at field at user creation
thakichowdhury Aug 1, 2019
fdd6820
Remove modified_at value insert at message creation
thakichowdhury Aug 1, 2019
dd5dd33
Update message insertion success condition
thakichowdhury Aug 1, 2019
aebfcd8
Adjust some commenting and variable naming for clarity
thakichowdhury Aug 1, 2019
bdbd045
Add TODO comment and return only id field values from fetching random
thakichowdhury Aug 1, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/db/actions/checkAndToggleUserActiveState.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const checkUserActivity = require('./checkUserActivity.js');
const toggleUserActivity = require('./toggleUserActivity.js');

const checkAndToggleUserActiveState = async ({ phoneNumber, directive }) => {
const isUserActive = await checkUserActivity({ phoneNumber });

const alreadyAtDesiredState = `Your account is already ${isUserActive ? 'active' : 'inactive'}.`;
const switchedState = `Your account has been set to ${isUserActive ? 'inactive' : 'active'}.`;

// if account's is_active field should be updated
const shouldToggleActivityLevel = (directive === 'START' && !isUserActive) || (directive === 'STOP' && isUserActive);

if (shouldToggleActivityLevel) {
// toggle the is_active field and return message informing of the state update
await toggleUserActivity({ phoneNumber });
return switchedState;
}

// else return message saying that the update was unneccessary
return alreadyAtDesiredState;
};

module.exports = checkAndToggleUserActiveState;
11 changes: 11 additions & 0 deletions src/db/actions/checkUserActivity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const sendQuery = require('../util/sendQuery');

const checkUserActivity = async ({ phoneNumber }) => {
const query = 'SELECT is_active FROM users WHERE phone_number = $1;';
const values = [phoneNumber];

const [response] = await sendQuery({ query, values });
return response;
};

module.exports = checkUserActivity;
2 changes: 1 addition & 1 deletion src/db/actions/createNewUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const getCurrentTimestamp = require('../../util/getCurrentTimestamp');
const createNewUser = async ({ phoneNumber }) => {
const createdAt = getCurrentTimestamp();

const query = 'INSERT INTO users (phone_number, is_active, created_at) VALUES ($1, $2, $3) RETURNING phone_number;';
const query = 'INSERT INTO users (phone_number, is_active, created_at, modified_at) VALUES ($1, $2, $3, $3) RETURNING phone_number;';
const values = [phoneNumber, true, createdAt];

try {
Expand Down
3 changes: 2 additions & 1 deletion src/db/actions/fetchRandomNoteId.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ const getRandomInt = require('../../util/getRandomInt');

const fetchRandomNoteId = async () => {
const { rows } = await db.query(
// TODO: add check to see if the user that saved the message has is_active to true
`
SELECT * FROM notes
SELECT id FROM notes
WHERE
date_part('day', last_called) < date_part('day', NOW())
OR date_part('day', created_at) < date_part('day', NOW())
Expand Down
13 changes: 9 additions & 4 deletions src/db/actions/insertNewMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ const fetchUser = require('./fetchUser');
const createNewUser = require('./createNewUser');

const insertNewMessage = async ({
phoneString,
phoneNumber,
message,
}) => {
const createdAt = getCurrentTimestamp();
const phoneNumber = parseInt(phoneString.slice(2), 10);

let user = await fetchUser({ phoneNumber });

Expand All @@ -22,8 +21,14 @@ const insertNewMessage = async ({
const values = [message, user.phone_number, createdAt];

return db.query(query, values)
.then(res => console.log(res))
.catch(err => console.error(err));
.then((res) => {
console.log(res);
return res;
})
.catch((err) => {
console.error(err);
return err;
});
};

module.exports = insertNewMessage;
6 changes: 4 additions & 2 deletions src/db/actions/sendMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const db = require('../../db');
const fetchRandomNoteId = require('./fetchRandomNoteId');
const updateLastCalled = require('./updateLastCalled');

const createMessage = require('../../lib/twilio/createMessage');
const twilioSendMessage = require('../../lib/twilio/twilioSendMessage');

const sendMessage = async () => {
const randomId = await fetchRandomNoteId();
Expand All @@ -14,8 +14,10 @@ const sendMessage = async () => {

const { rows: [{ phone_number: phoneNumber, message }] } = await db.query(query, values);

createMessage({ to: phoneNumber, message });
// send sms message to user phone number
twilioSendMessage({ to: phoneNumber, message });

// update the last_called field for the notes message
updateLastCalled(randomId);
}
};
Expand Down
19 changes: 19 additions & 0 deletions src/db/actions/toggleUserActivity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const db = require('../index');

const getCurrentTimestamp = require('../../util/getCurrentTimestamp');

const toggleUserActivity = async ({ phoneNumber }) => {
const modifiedAt = getCurrentTimestamp();

const query = 'UPDATE users SET is_active = NOT is_active, modified_at = $2 WHERE phone_number = $1 RETURNING phone_number;';
const values = [phoneNumber, modifiedAt];

try {
const { rows } = await db.query(query, values);
return rows[0];
} catch (err) {
console.error(err);
}
};

module.exports = toggleUserActivity;
2 changes: 1 addition & 1 deletion src/db/actions/updateLastCalled.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const getCurrentTimestamp = require('../../util/getCurrentTimestamp');
const updateLastCalled = async (notesId) => {
const lastCalled = getCurrentTimestamp();

const query = 'UPDATE notes SET last_called = $1 WHERE id = $2 RETURNING id';
const query = 'UPDATE notes SET last_called = $1 WHERE id = $2 RETURNING id;';
const values = [lastCalled, notesId];

const { rows: [{ id }] } = await db.query(query, values);
Expand Down
3 changes: 2 additions & 1 deletion src/db/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ CREATE DATABASE note_reminder;
CREATE TABLE users (
phone_number BIGINT PRIMARY KEY,
is_active BOOL NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
modified_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE notes (
Expand Down
12 changes: 12 additions & 0 deletions src/db/util/sendQuery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const db = require('../index');

const sendQuery = async ({ query, values }) => {
try {
const { rows } = await db.query(query, values);
return rows;
} catch (err) {
console.error(err);
}
};

module.exports = sendQuery;
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const {
TWILIO_VERIFIED_NUMBER,
} = require('../../../secrets/local.js');

const twilioCreateMessage = async ({
const twilioSendMessage = async ({
to,
message,
}) => {
Expand All @@ -20,4 +20,4 @@ const twilioCreateMessage = async ({
.catch(error => console.error(`Message was not sent: error: ${error}`));
};

module.exports = twilioCreateMessage;
module.exports = twilioSendMessage;
31 changes: 31 additions & 0 deletions src/server/actions/routeMessage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const insertNewMessage = require('../../db/actions/insertNewMessage');
const checkAndToggleUserActiveState = require('../../db/actions/checkAndToggleUserActiveState');

const sendMessage = require('../../lib/twilio/twilioSendMessage');

const routeMessage = async ({
phoneString,
message,
}) => {
const phoneNumber = parseInt(phoneString.slice(2), 10);
let responseMessage = '';

// if incoming message is a directive to stop or start activity
const messageUpperCase = message.toUpperCase();
const isDirective = messageUpperCase === 'STOP' || messageUpperCase === 'START';

if (isDirective) {
// respond with appropriate action and response message
responseMessage = await checkAndToggleUserActiveState({
phoneNumber,
directive: messageUpperCase,
});
} else {
const insertResponse = await insertNewMessage({ phoneNumber, message });
responseMessage = insertResponse.rowCount ? 'Message was successfully saved!' : 'There was an error saving your message.';
}

sendMessage({ to: phoneNumber, message: responseMessage });
};

module.exports = routeMessage;
17 changes: 10 additions & 7 deletions src/server/start.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
const app = require('./index.js');

const insertNewMessage = require('../db/actions/insertNewMessage');
const routeMessage = require('./actions/routeMessage');

// start cron-jobs
require('./cron');

const PORT = process.env.PORT || 3000;

// TODO: break endpoints into a separate routes file
app.post('/sms', ({
body: {
From: phoneString,
Body: message,
},
}) => insertNewMessage({ phoneString, message }));
app.post(
'/sms',
async ({
body: {
From: phoneString,
Body: message,
},
}) => routeMessage({ phoneString, message }),
);

app.listen(
PORT,
Expand Down