Skip to content

Instantly share code, notes, and snippets.

@undocumented-code
Last active June 1, 2018 01:33
Show Gist options
  • Save undocumented-code/cf794f2fef850d3ea83c366ac6f415ae to your computer and use it in GitHub Desktop.
Save undocumented-code/cf794f2fef850d3ea83c366ac6f415ae to your computer and use it in GitHub Desktop.
Google Apps Script for a Slack Bot backed by a Google Sheet. https://blog.tuckerosman.com/2018/05/make-slackbot-from-google-spreadsheet.html
function checkingLoop() {
//This is what checks every so often and sends the reminder message.
const range = getNearestDateTimeRange(moment());
if(!range) return;
const leavingCell = range.getCell(1,2);
const returnCell = range.getCell(1,3);
const leaving = leavingCell.getDisplayValue();
const returning = returnCell.getDisplayValue();
if(leaving.length) {
const leavingCars = leaving.split(";");
leavingCars.forEach(function(element) {
const leavingPeople = element.split(",");
if(leavingPeople.length<2) return;
var leavingMessage = "Hey "+normalizeName(leavingPeople[0])+", you're leaving";
if(leavingPeople.length>1) {
leavingMessage += " with "+listPeople(leavingPeople.slice(1));
}
sendMessage({"text":leavingMessage, "link_names": 1});
});
}
if(returning.length) {
const returningCars = returning.split(";");
returningCars.forEach(function(element) {
const returningPeople = element.split(",");
if(returningPeople.length<2) return;
var returningMessage = "Hey "+normalizeName(returningPeople[0])+", you're returning";
if(returningPeople.length>1) {
returningMessage += " with "+listPeople(returningPeople.slice(1));
}
sendMessage({"text":returningMessage, "link_names": 1});
});
}
}
function normalizeName(name) { //Maps to username and tags
if(!name) return "";
switch(name.toLowerCase()) {
//Add case statements here for names that are different from usernames. Returns an @ reference for slack to resolve.
default:
return "@"+name.toLowerCase().trim();
break;
}
}
function listPeople(people) {
if(people.length == 0) return "";
else if(people.length == 1) return normalizeName(people[0]);
else if(people.length == 2) return normalizeName(people[0]) + " and " + normalizeName(people[1]);
else {
var out = "";
for(var i = 0; i<people.length-1; i++) out += normalizeName(people[i])+", ";
out += "and "+normalizeName(people[people.length-1]);
return out;
}
}
function getNearestDateTimeRange(time) {
const now = time || moment();
//Determine the column
if(now.day()<1 || now.day()>5) return undefined;
var col = 3*(now.day()-1)+1;
//Now let's figure out the row. We don't want to do anything too early, so let's keep it to 7 minutes or less before the designated time.
if(now.hour()<7 || now.hour()>17) return undefined;
//Now let's find the next 15 minute increment
var next = roundToNextInterval(now); //Returns discrete moment
var duration = next.diff(now, "minutes");
if ((duration >= 60 && (duration - 60) > 5) || (duration < 60 && duration > 5)) return undefined;
var row = (now.hour()-7)*4+3; //Get the base hour
if(next.minutes()==0) row += 4;
else row += next.minutes()/15;
//Data source so it's statically linked for running in the background
return SpreadsheetApp.openById("1sG4n2VwfDkcirrU3B8NnZ64T2T4irHcgwK92UeZZLLQ").getSheets()[0].getRange(row, col, 1, 3);
}
function roundToNextInterval(x) {
const next = x.clone();
const intervals = Math.floor(next.minutes() / 15);
if(next.minutes() % 15 != 0)
intervals++;
if(intervals == 4) {
next.add('hours', 1);
intervals = 0;
}
next.minutes(intervals * 15);
//next.seconds(0);
return next;
}
function sendMessage(content) {
const options = {
"method" : "POST",
"contentType" : "application/json",
"payload" : JSON.stringify(content)
};
const url = "https://hooks.slack.com/services/..."; //Slack WebHook here.
const response = UrlFetchApp.fetch(url, options);
return response;
}
function test() {
sendMessage({"text": "This is a test text message."});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment