Skip to content

Instantly share code, notes, and snippets.

@antifuchs
Last active March 26, 2021 07:29
Show Gist options
  • Save antifuchs/dde7d18d757d57478ba8 to your computer and use it in GitHub Desktop.
Save antifuchs/dde7d18d757d57478ba8 to your computer and use it in GitHub Desktop.
////// Easily customizable stuff
// Step zero: have a filter that sorts all [email protected] mail into _github_incoming & archives it
var incomingLabel = '_github_incoming'; // You can hide this in the sidebar.
// github sends to "me", and I want less of that pollution
var toMeLabel = 'asf';
// labels for various conditions:
var meLabel = 'github';
var teamMentionLabel = 'github/team_mention';
///// End of the easily customizable stuff
// The main entry and trigger point for the post-hoc filter:
function processIncoming() {
processMessages(true);
}
// Run this manually from the scripts console to backfill your github labels without filling your inbox:
function processIncomingBackfill() {
processMessages(false);
}
function processMessages(putIntoInbox) {
var incoming = getOrCreateLabel(incomingLabel);
var threads = incoming.getThreads();
for (var i = 0; i < threads.length; i++) {
var thread = threads[i];
var messages = thread.getMessages();
// We consider only the last message, as you might have unsubscribed from github threads, or situations may have otherwise changed:
sortMessage(messages[messages.length-1], thread, putIntoInbox);
thread.removeLabel(incoming);
}
}
function getOrCreateLabel(name) {
var label = GmailApp.getUserLabelByName(name);
if(label == null){
label = GmailApp.createLabel(name);
}
return label
}
function sortMessage(message, thread, putIntoInbox) {
var headers = messageHeaders(message.getRawContent());
if (isMessageRelevant(headers)) {
Logger.log("Thread with message subject %s is relevant", headers['Subject']);
markAsMine(thread, putIntoInbox);
} else {
Logger.log("Thread with subject %s is not relevant", headers['Subject']);
markAsNonRelevant(thread);
}
}
function isMessageRelevant(headers) {
var isIt = (headers['X-GitHub-Reason'] === 'author') ||
(headers['X-GitHub-Reason'] === 'comment') ||
(headers['X-GitHub-Reason'] === 'assign') ||
(headers['X-GitHub-Reason'] === 'mention');
return isIt;
}
function markAsMine(thread, putIntoInbox) {
thread.addLabel(getOrCreateLabel(meLabel));
if (putIntoInbox) {
thread.moveToInbox();
}
}
function markAsNonRelevant(thread) {
thread.addLabel(getOrCreateLabel(teamMentionLabel));
var messages = thread.getMessages();
var wasEverRelevant = false;
for(var i=0; i < messages.length; i++) {
var body = messages[i].getRawContent();
var headers = messageHeaders(body);
if (isMessageRelevant(headers)) {
wasEverRelevant = true;
}
}
if (!wasEverRelevant && toMeLabel !== null) {
thread.removeLabel(GmailApp.getUserLabelByName(toMeLabel));
}
}
/* Takes a raw message and returns a dictionary of header=>header values.
* Note: This handles only "simple"&short (non-continued) headers, so any
* continuation lines aren't going to be processed - only the first line
* will be considered a value.
*/
function messageHeaders(body) {
var lines = body.split(/\r?\n/);
var headers = [], wasNewline = false;
// Determine the empty line & split there:
for(var i=0; i < lines.length && !wasNewline; i++) {
var line = lines[i];
if (line === '') {
wasNewline = true;
} else {
headers.push(line);
}
}
var headerDict = {}
for (var i=0; i < headers.length; i++) {
var headerSplit = headers[i].split(": ");
var key = headerSplit.shift();
if (!key.match(/^\s/)) {
// it's a not header continuation, so add it as a new key
headerDict[key] = headerSplit.join(": ");
}
}
return headerDict;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment