Skip to content

Commit

Permalink
Merge branch 'master' into threads
Browse files Browse the repository at this point in the history
  • Loading branch information
BGR360 committed Jan 28, 2019
2 parents f3b6614 + d3f731d commit 33b8bae
Show file tree
Hide file tree
Showing 8 changed files with 324 additions and 24 deletions.
31 changes: 31 additions & 0 deletions HOW-TO-UPDATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# How to Update `piazza-link-bot`

So you've got an outdated Piazza bot, huh? Well don't worry, here's how to quickly update your deployment!

## Method A: Command Line

This is the most straightforward method. It requires that you have the heroku CLI installed.

1. Check to see if any new Environment variables were added in the update. If so, you should update these in your Heroku app's settings before proceeding.
1. Clone the up-to-date `piazza-link-bot` repo to your local machine
```
$ git clone https://github.com/BGR360/piazza-link-bot
```
1. Force push the code directly to your Heroku app instance
```
$ heroku login
$ git remote add heroku https://git.heroku.com/YOUR-PIAZZA-LINK-BOT-APP-NAME.git
$ git push -f heroku master
```

## Method B: Fork and Browser

If you really don't wanna install Heroku CLI, then you can try this method.

1. Check to see if any new Environment variables were added in the update. If so, you should update these in your Heroku app's settings before proceeding.
1. Fork this repo to your GitHub account.
1. Go to your heroku dashboard and click on your piazza link bot app.
1. Go to the "Deploy" menu.
1. Under "Deployment method", select GitHub as the option.
1. Grant Heroku permissions.
1. Select your fork of the repo and use that to deploy.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ Based on [regexbot](https://github.com/sjmelia/regexbot) by sjmelia.

![Example image](https://i.gyazo.com/3fbcb71b81845b5ca65cef08af1334d8.png)


Got an out-of-date deployment?
------------------------------

Go to [HOW-TO-UPDATE.md](HOW_TO_UPDATE.md) for instructions on how to update your deployment to the latest version.


Full instructions
-----
-----------------

### Create Slack App

Expand Down
7 changes: 5 additions & 2 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@
},
"REPLY_AS_THREAD": {
"description": "Should the bot reply as a thread? Leave empty for no, put any value for yes.",
"required": false,
"value": "LEAVE EMPTY FOR NO, PUT ANY VALUE FOR YES"
"required": false
},
"RETRY_MEMORY": {
"description": "Number of message ids to hold in memory to prevent duplicate messages (linear search involved) (default=100)",
"required": false
}
}
}
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
{
"name": "regexbot",
"name": "piazza-link-bot",
"version": "1.0.0",
"description": "Regular expression responder for slack",
"repository": "https://github.com/sjmelia/regexbot",
"description": "Slackbot that responds with links to Piazza posts",
"repository": "https://github.com/bgr360/piazza-link-bot",
"main": "src/index.js",
"dependencies": {
"@slack/client": "^4.8.0",
"@slack/events-api": "^2.1.1",
"app.json": "^1.3.0",
"jira-client": "^4.2.0",
"node-schedule": "^1.2.0"
},
Expand All @@ -25,6 +24,6 @@
"start": "node src/index.js",
"test": "eslint src && mocha"
},
"author": "Steve Melia",
"author": "Ben Reeves",
"license": "MIT"
}
3 changes: 3 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ var config = {

schedules: [],

// Number of message ids to keep in memory in order to prevent duplicate replies.
retryMemory: process.env['RETRY_MEMORY'] || 100,

build: function (id) {
this.regexes.push({ regex: /@(\d+)/g, message: this.piazza_base_url + '?cid=[1]' });
}
Expand Down
44 changes: 28 additions & 16 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
var config = require('./config');
var RegexBot = require('./regexbot');
var RetryFilter = require('./retryfilter');
var randomiser = function (max) {
return Math.floor(Math.random() * max);
};
var regexbot = new RegexBot(config, randomiser);
var retryFilter = new RetryFilter(config);

const { RTMClient, WebClient, ErrorCode } = require('@slack/client');
const { createEventAdapter } = require('@slack/events-api');
Expand Down Expand Up @@ -43,25 +45,35 @@ client.on('message', (message) => {

console.log('Accepted a message: ' + JSON.stringify(message));

regexbot.respond(message.text, (reply) => {
console.log('Responding with: ' + reply);
function messageOkay (message) {
// Make the retry filter remember this message
retryFilter.addMessage(message);

var replyMessage = {
channel: message.channel,
text: reply,
as_user: true
};
regexbot.respond(message.text, (reply) => {
console.log('Responding with: ' + reply);

// If bot is configured to reply as a thread, or if the message that
// triggered the bot was already a threaded reply, then add a 'thread_ts'
// so that the bot replies inside the thread.
if (config.reply_as_thread || message.thread_ts !== undefined) {
console.log("has it!")
replyMessage.thread_ts = message.thread_ts || message.ts;
}
var replyMessage = {
channel: message.channel,
text: reply,
as_user: true
};

postMessage(replyMessage);
});
// If bot is configured to reply as a thread, or if the message that
// triggered the bot was already a threaded reply, then add a 'thread_ts'
// so that the bot replies inside the thread.
if (config.reply_as_thread || message.thread_ts !== undefined) {
replyMessage.thread_ts = message.thread_ts || message.ts;
}

postMessage(replyMessage);
});
};

function messageIsDuplicate (message) {
console.log('Message is a duplicate');
}

retryFilter.filter(message, messageOkay, messageIsDuplicate);
});

client.on('error', console.error);
Expand Down
71 changes: 71 additions & 0 deletions src/retryfilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Slack API will retry messages if they take too long.
* When a Heroku dyno is starting up, it typically receives
* the same message 3 times due to this retry, causing the bot
* to send 3 identical replies. This is a solution to this problem.
*
* SECURITY / PRIVACY NOTE:
* None of the contents of messages are kept in memory longer than needed.
* Only the unique timestamp and channel id of the message are stored
* in the previousMessages array.
*/
function RetryFilter (config) {
this.config = config;
this.previousMessages = [];

this.addMessage = addMessage;
this.filter = filter;
this.isRetry = isRetry;

/**
* Adds a message to the memory and removes an old one if necessary.
* Returns the message that was popped from the front, if it was, otherwise null.
*/
function addMessage (message) {
this.previousMessages.push({
ts: message.ts,
channel: message.channel
});

// Remove first item of array if array too big
while (this.previousMessages.length > this.config.retryMemory) {
let popped = this.previousMessages[0];
this.previousMessages.shift();
return popped;
}

return null;
}

/**
* Calls callback only if the message is not a repeat,
* otherwise calls ifRetry
*/
function filter (message, callback, ifRetry) {
if (this.isRetry(message)) {
if (ifRetry !== undefined) {
ifRetry(message);
}
} else {
callback(message);
}
}

function isRetry (message) {
if (this.previousMessages.length === 0) {
return false;
}

// Search through to see if any of them have the same timestamp and channel number
for (let i = 0; i < this.previousMessages.length; i++) {
let prevMsg = this.previousMessages[i];
if (prevMsg.ts === message.ts && prevMsg.channel === message.channel) {
return true;
}
}

return false;
}
}

module.exports = RetryFilter;
Loading

0 comments on commit 33b8bae

Please sign in to comment.