Skip to content

Commit

Permalink
Add top sender (#98)
Browse files Browse the repository at this point in the history
* Add top point giver to the response

* Iterate the users object

* forgot the toarray bit

* Adding new db field to help with functions

* Updating sender db queries to only find if total exists

* Adding cron

* Update the cron

* Update cron to configure day of week and cron timing

* fixing parse int issue

* Updating package.json with updated repos

* Move to node 16

* adding x placeholders to node

* Add npm

* Bump version prep

* Bump versions of node around

* I'm a derp and forgot the i in a loop

* Adding more stats

* Finish up the cron setup
  • Loading branch information
O-Mutt authored Oct 1, 2021
1 parent cc95684 commit d949679
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 46 deletions.
23 changes: 23 additions & 0 deletions helpful_queryies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
db.scores.find({ slackId: { $exists: true }}).forEach((user) => {
let total = 0;
for (const key in user.pointsGiven) {
total += parseInt(user.pointsGiven[key], 10);
}
db.scores.update({ _id: user._id }, { $set: { "totalPointsGiven": total }});
});

var theDate = new Date(ISODate().getTime() - 7 * 24 * 60 * 60000)
db.scoreLog.distinct("from", { date: { $gt: new ISODate().getTime() - 7 * 24 * 60 * 60000) } }).forEach((fromUser) => {
print(fromUser);
//print(to + ", " + value + ": " + db[collection].count({[to]: value}))
})

db.scoreLog.aggregate([
{
$match: {
date: { $gt: new Date(new Date().setDate(new Date().getDate()-15)).toISOString() }
}
},
{
$group: { "_id": "$from", "scoreChange": { "$sum": "$scoreChange" }}
}]);
18 changes: 17 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"name": "hubot-plusplus-expanded",
"version": "3.2.0",
"version": "3.3.0",
"description": "A hubot script for micro praise",
"main": "index.js",
"engines": {
"node": "^14"
"node": "^14.x.x",
"npm": "^6.x.x"
},
"config": {
"mongodbMemoryServer": {
Expand All @@ -20,7 +21,7 @@
},
"repository": {
"type": "git",
"url": "git://github.com/Mutmatt/hubot-plusplus-expanded.git"
"url": "git://github.com/O-Mutt/hubot-plusplus-expanded.git"
},
"keywords": [
"hubot",
Expand All @@ -32,18 +33,19 @@
"slack"
],
"author": {
"name": "Matt Erickson",
"email": "hubot@matterickson.me",
"url": "https://github.com/Mutmatt/hubot-plusplus-expanded"
"name": "Matt O'Keefe",
"email": "hubot@okeefe.dev",
"url": "https://github.com/O-Mutt/hubot-plusplus-expanded"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/Mutmatt/hubot-plusplus-expanded/issues"
"url": "https://github.com/O-Mutt/hubot-plusplus-expanded/issues"
},
"dependencies": {
"@slack/client": "^5.0.2",
"axios": "^0.21.1",
"clark": "^0.0.6",
"cron": "^1.8.2",
"hubot-conversation": "^1.1.1",
"lodash": "^4.17.21",
"moment": "^2.29.1",
Expand Down
84 changes: 84 additions & 0 deletions src/cronEvents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const clark = require('clark');
const moment = require('moment');
const _ = require('lodash');
const { CronJob } = require('cron');

const helpers = require('./lib/helpers');
const DatabaseService = require('./lib/services/database');

module.exports = (robot) => {
const procVars = helpers.getProcessVariables(process.env);
const databaseService = new DatabaseService({ robot, ...procVars });

if (!procVars.notificationsRoom) {
return;
}

const { monthlyScoreboardCron, monthlyScoreboardDayOfWeek } = procVars;
const job = new CronJob(monthlyScoreboardCron, async () => {
if (isScoreboardDayOfWeek()) {
robot.logger.debug('running the cron job');

// Senders
const topSenders = await databaseService.getTopSenderInDuration(10, 30);
let message = [];
if (topSenders.length > 0) {
for (let i = 0, end = topSenders.length - 1, asc = end >= 0; asc ? i <= end : i >= end; asc ? i++ : i--) {
const person = `<@${topSenders[i]._id}>`;
const pointStr = topSenders[i].scoreChange > 1 ? 'points given' : 'point given';
message.push(`${i + 1}. ${person} (${topSenders[i].scoreChange} ${pointStr})`);
}
} else {
message.push('No scores to keep track of yet!');
}

let graphSize = Math.min(topSenders.length, Math.min(10, 20));
message.splice(0, 0, clark(_.take(_.map(topSenders, 'scoreChange'), graphSize)));
message.splice(0, 0, `:tada: The top 10 ${robot.name} point senders over the last month! :tada:`);
robot.messageRoom(procVars.notificationsRoom, message.join('\n'));

// Recipients
const topRecipient = await databaseService.getTopReceiverInDuration(10, 30);
message = [];
if (topRecipient.length > 0) {
for (let i = 0, end = topRecipient.length - 1, asc = end >= 0; asc ? i <= end : i >= end; asc ? i++ : i--) {
const person = `<@${topRecipient[i]._id}>`;
const pointStr = topRecipient[i].scoreChange > 1 ? 'points given' : 'point given';
message.push(`${i + 1}. ${person} (${topRecipient[i].scoreChange} ${pointStr})`);
}
} else {
message.push('No scores to keep track of yet!');
}

graphSize = Math.min(topRecipient.length, Math.min(10, 20));
message.splice(0, 0, clark(_.take(_.map(topRecipient, 'scoreChange'), graphSize)));
message.splice(0, 0, `:tada: The top 10 ${robot.name} point recipients over the last month! :tada:`);
robot.messageRoom(procVars.notificationsRoom, message.join('\n'));

// Room
const topRoom = await databaseService.getTopRoomInDuration(3, 30);
message = [];
if (topRoom.length > 0) {
for (let i = 0, end = topRoom.length - 1, asc = end >= 0; asc ? i <= end : i >= end; asc ? i++ : i--) {
const person = `<#${topRoom[i]._id}>`;
const pointStr = topRoom[i].scoreChange > 1 ? 'points given' : 'point given';
message.push(`${i + 1}. ${person} (${topRoom[i].scoreChange} ${pointStr})`);
}
} else {
message.push('No scores to keep track of yet!');
}

graphSize = Math.min(topRoom.length, Math.min(10, 20));
message.splice(0, 0, clark(_.take(_.map(topRoom, 'scoreChange'), graphSize)));
message.splice(0, 0, `:tada: The top 3 rooms that sent ${robot.name} point(s) over the last month! :tada:`);
robot.messageRoom(procVars.notificationsRoom, message.join('\n'));
}
}, null, true, 'America/Chicago');
job.start();

function isScoreboardDayOfWeek() {
robot.logger.debug(`Run the cron but lets check what day it is Moment day: [${moment().day()}], Configured Day of Week: [${monthlyScoreboardDayOfWeek}], isThatDay: [${moment().day() === monthlyScoreboardDayOfWeek}]`);
const isToday = moment().day() === monthlyScoreboardDayOfWeek;
return isToday;
}
};
2 changes: 2 additions & 0 deletions src/lib/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ function getProcessVariables(env) {
procVars.furtherHelpUrl = env.HUBOT_CRYPTO_FURTHER_HELP_URL || undefined;
procVars.notificationsRoom = env.HUBOT_PLUSPLUS_NOTIFICATION_ROOM || undefined;
procVars.falsePositiveNotificationsRoom = env.HUBOT_PLUSPLUS_FALSE_POSITIVE_NOTIFICATION_ROOM || undefined;
procVars.monthlyScoreboardCron = env.HUBOT_PLUSPLUS_MONTHLY_SCOREBOARD_CRON || '0 10 1-7 * *';
procVars.monthlyScoreboardDayOfWeek = parseInt(env.HUBOT_PLUSPLUS_MONTHLY_SCOREBOARD_DAY_OF_WEEK, 10) || 1; // 0-6 (Sun - Sat)
return procVars;
}

Expand Down
8 changes: 8 additions & 0 deletions src/lib/regexpCreator.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ class RegExpCreator {
);
}

createTopPointGiversRegExp() {
const topOrBottom = '(top|bottom)';
const digits = '(\\d+)';
return new RegExp(
`${topOrBottom}${this.allowSpaceAfterObject}(?:point givers?|point senders?|givers?|senders?)${this.allowSpaceAfterObject}${digits}`,
'i'
);
}
/**
* user1++ for being dope
* user1-- cuz nope
Expand Down
90 changes: 89 additions & 1 deletion src/lib/services/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ class DatabaseService {
return dbUser;
}

/*
* user - the name of the user
*/
async getAllUsers() {
const search = { slackId: { $exists: true } };
this.robot.logger.debug('getting _all_ users');
const db = await this.getDb();

const dbUsers = await db.collection(scoresDocumentName).find(search).toArray();
return dbUsers;
}

/**
* Saves the user with a new score
* @param {object} user the user who is getting a point change
Expand Down Expand Up @@ -86,8 +98,10 @@ class DatabaseService {

async savePlusPlusLog(to, from, room, reason, incrementValue) {
const fromId = from.slackId || from.name;
const scoreSearch = from.slackId ? { slackId: from.slackId } : { name: from.name };
const toId = to.slackId || to.name;
const db = await this.getDb();
await db.collection(scoresDocumentName).updateOne(scoreSearch, { $inc: { totalPointsGiven: incrementValue } });
await db.collection(logDocumentName).insertOne({
from: fromId,
to: toId,
Expand Down Expand Up @@ -202,7 +216,33 @@ class DatabaseService {
.limit(amount)
.toArray();

this.robot.logger.debug('Trying to find top tokens');
this.robot.logger.debug('Trying to find bottom tokens');

return results;
}

async getTopSender(amount) {
const db = await this.getDb();
const results = await db.collection(scoresDocumentName)
.find({ totalPointsGiven: { $exists: true } })
.sort({ totalPointsGiven: -1, accountLevel: -1 })
.limit(amount)
.toArray();

this.robot.logger.debug('Trying to find top sender');

return results;
}

async getBottomSender(amount) {
const db = await this.getDb();
const results = await db.collection(scoresDocumentName)
.find({ totalPointsGiven: { $exists: true } })
.sort({ totalPointsGiven: 1, accountLevel: -1 })
.limit(amount)
.toArray();

this.robot.logger.debug('Trying to find bottom sender');

return results;
}
Expand Down Expand Up @@ -252,6 +292,54 @@ class DatabaseService {
return botWallet;
}

async getTopSenderInDuration(amount = 10, days = 7) {
const db = await this.getDb();
const topSendersForDuration = await db.collection(logDocumentName).aggregate([
{
$match: { date: { $gt: new Date(new Date().setDate(new Date().getDate() - days)).toISOString() } },
},
{
$group: { _id: '$from', scoreChange: { $sum: '$scoreChange' } },
},
{
$sort: { scoreChange: -1 },
}])
.limit(amount).toArray();
return topSendersForDuration;
}

async getTopReceiverInDuration(amount = 10, days = 7) {
const db = await this.getDb();
const topRecipientForDuration = await db.collection(logDocumentName).aggregate([
{
$match: { date: { $gt: new Date(new Date().setDate(new Date().getDate() - days)).toISOString() } },
},
{
$group: { _id: '$to', scoreChange: { $sum: '$scoreChange' } },
},
{
$sort: { scoreChange: -1 },
}])
.limit(amount).toArray();
return topRecipientForDuration;
}

async getTopRoomInDuration(amount = 3, days = 7) {
const db = await this.getDb();
const topRoomForDuration = await db.collection(logDocumentName).aggregate([
{
$match: { date: { $gt: new Date(new Date().setDate(new Date().getDate() - days)).toISOString() } },
},
{
$group: { _id: '$room', scoreChange: { $sum: '$scoreChange' } },
},
{
$sort: { scoreChange: -1 },
}])
.limit(amount).toArray();
return topRoomForDuration;
}

/**
*
* @param {string} userName the name of the user receiving the points
Expand Down
Loading

0 comments on commit d949679

Please sign in to comment.