From 33d2ca3e60b2dd0613c8c44c3f5ec8d5473e0473 Mon Sep 17 00:00:00 2001 From: Riley Childs Date: Tue, 16 Jul 2019 20:40:06 -0700 Subject: [PATCH] Added stuff needed for points rate limiting --- app.json | 4 ++++ src/events.js | 12 ++++++++---- src/points.js | 52 +++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/app.json b/app.json index e3da633..53f0d5b 100644 --- a/app.json +++ b/app.json @@ -16,6 +16,10 @@ "description": "Verification Token provided by Slack. Find this under Basic Information -> App Credentials within your Slack app management page.", "value": "xxxxxxxxxxxxxxxxxxxxxxxx" }, + "MAX_OPS": { + "description": "Max number of ops per 24 hour period", + "value": "20" + }, "YARN_PRODUCTION": { "description": "This configures Heroku to only install production dependencies. See https://devcenter.heroku.com/articles/nodejs-support#package-installation for more details.", "value": "true" diff --git a/src/events.js b/src/events.js index 3b279eb..dfb8eb9 100644 --- a/src/events.js +++ b/src/events.js @@ -42,12 +42,16 @@ const handleSelfPlus = ( user, channel ) => { * @return {Promise} A Promise to send a Slack message back to the requesting channel after the * points have been updated. */ -const handlePlusMinus = async( item, operation, channel ) => { +const handlePlusMinus = async( item, operation, channel, userInit ) => { + + if (checkCanUpdate(userInit)){ const score = await points.updateScore( item, operation ), operationName = operations.getOperationName( operation ), message = messages.getRandomMessage( operationName, item, score ); - - return slack.sendMessage( message, channel ); + return slack.sendMessage( message, channel ); + } + + return slack.sendMessage( 'What you trying to do? Cheat? @<' + userInit + '>?', channel ); }; /** @@ -215,7 +219,7 @@ const handlers = { // Otherwise, let's go! - return handlePlusMinus( item, operation, event.channel ); + return handlePlusMinus( item, operation, event.channel, event.user ); }, // Message event. diff --git a/src/points.js b/src/points.js index 3d35707..a8278bb 100644 --- a/src/points.js +++ b/src/points.js @@ -17,13 +17,18 @@ const pg = require( 'pg' ); const DATABASE_URL = process.env.DATABASE_URL, DATABASE_USE_SSL = 'false' === process.env.DATABASE_USE_SSL ? false : true; /* eslint-enable no-process-env */ - +const MAX_OPS = process.env.MAX_OPS const scoresTableName = 'scores', postgresPoolConfig = { connectionString: DATABASE_URL, ssl: DATABASE_USE_SSL }; +const userTrackerTableName = 'userTracker', + postgresPoolConfig = { + connectionString: DATABASE_URL, + ssl: DATABASE_USE_SSL + }; const postgres = new pg.Pool( postgresPoolConfig ); /** @@ -214,10 +219,53 @@ const getScore = async( item, operation ) => { }; // UpdateScore. +const checkCanUpdate = async(user) => { + + const dbClient = await postgres.connect(); + await dbClient.query( '\ + CREATE EXTENSION IF NOT EXISTS citext; \ + CREATE TABLE IF NOT EXISTS ' + userTrackerTableName + ' (user CITEXT PRIMARY KEY, operations INTEGER, ts INTEGER); \ + ' ); + + const userOperations = await dbClient.query( '\ + SELECT operations FROM ' + userTrackerTableName + ' WHERE user = \'' + user + '\'; \ +' ); + + const userTS = await dbClient.query( '\ + SELECT ts FROM ' + userTrackerTableName + ' WHERE user = \'' + user + '\'; \ +' ); + + if ((Math.floor(new Date() / 1000) - userTS) < 86400) { + if(userOperations >= MAX_OPS ) { + return false + } + else { + await dbClient.query( '\ + INSERT INTO ' + userTrackerTableName + ' VALUES (\'' + user + '\', ' + '+' + '1, ' + userTS + ' ) \ + ON CONFLICT (user) DO UPDATE SET operations = ' + userTrackerTableName + '.operations + 1; \ + ' ); + return true + } + } + else { + await dbClient.query( '\ + INSERT INTO ' + userTrackerTableName + ' VALUES (\'' + user + '\', 1, ' + (Math.floor(new Date() / 1000) ) + ' ) \ + ON CONFLICT (user) DO UPDATE SET operations = 1, ts = ' + (Math.floor(new Date() / 1000) ) + ' ; \ + ' ); + return true + + } + + + + +} + module.exports = { retrieveTopScores, updateScore, randomScore, reallyRandomScore, - getScore + getScore, + checkCanUpdate };