-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathgmail-gitlab-filtering.gs
More file actions
126 lines (105 loc) · 3.72 KB
/
gmail-gitlab-filtering.gs
File metadata and controls
126 lines (105 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/* SPDX-License-Identifier: BSD-2-Clause */
const personalLabelName = "mattst88";
const unprocessedLabels = ["freedesktop"];
const maxThreads = 240;
let personalLabel;
function processInbox() {
userLabels.update();
personalLabel = GmailApp.getUserLabelByName(personalLabelName);
for (const label of unprocessedLabels) {
processLabel(userLabels.get(label));
}
}
/* the GmailLabel.addToThreads/removeFromThreads functions
* only process 100 threads at a time */
function processInChunks(threads, callback) {
const chunkSize = 100;
for (let i = 0; i < threads.length; i += chunkSize) {
const end = Math.min(i + chunkSize, threads.length);
callback(threads.slice(i, end));
Logger.log(`\t... ${end} done`);
}
}
function getOrSetDefault(map, key, defaultValue) {
if (!map.has(key)) {
map.set(key, defaultValue);
}
return map.get(key);
}
function processLabel(unprocessedLabel) {
const toInboxThreads = [];
const toRemoveThreads = new Map();
const toAddThreads = new Map();
const threads = GmailApp.search(`label:${unprocessedLabel.getName()}`, 0, maxThreads);
if (threads.length < 1) {
Logger.log(`No threads to process with label:${unprocessedLabel.getName()}`);
return;
}
Logger.log(`Processing threads with label:${unprocessedLabel.getName()}`);
function processThread(thread) {
let moveToInbox = false;
const labelNames = new Set();
const messages = thread.getMessages();
for (const message of messages) {
/* If the X-GitLab-NotificationReason header exists in any message
* in the thread, it was sent to us because we were mentioned, we participated, etc.
* We want to move those threads to the Inbox. */
const notificationReason = message.getHeader("X-GitLab-NotificationReason");
if (notificationReason) {
moveToInbox = true;
}
/* Collect project paths in a Set to automatically deduplicate */
const projectPath = message.getHeader("X-GitLab-Project-Path");
if (projectPath) {
labelNames.add(projectPath);
}
}
for (const labelName of labelNames) {
/* Get/create a label nested under our unprocessed label */
const label = userLabels.get(`${unprocessedLabel.getName()}/${labelName}`);
getOrSetDefault(toAddThreads, label, []).push(thread);
}
if (moveToInbox) {
toInboxThreads.push(thread);
} else {
getOrSetDefault(toRemoveThreads, personalLabel, []).push(thread);
}
getOrSetDefault(toRemoveThreads, unprocessedLabel, []).push(thread);
}
for (const [i, thread] of threads.entries()) {
Logger.log(`Processing thread ${i}`);
processThread(thread);
}
/* Apply labels to threads */
for (const [label, threads] of toAddThreads) {
Logger.log(`Adding ${label.getName()} label to ${threads.length} threads`);
processInChunks(threads, (chunk) => label.addToThreads(chunk));
}
/* Move threads to Inbox */
if (toInboxThreads.length > 0) {
Logger.log(`Moving ${toInboxThreads.length} to Inbox`);
processInChunks(toInboxThreads, (chunk) => GmailApp.moveThreadsToInbox(chunk));
}
/* Remove labels from threads */
for (const label of [personalLabel, unprocessedLabel]) {
const threads = toRemoveThreads.get(label);
if (!threads)
continue;
Logger.log(`Removing ${label.getName()} label from ${threads.length} threads`);
processInChunks(threads, (chunk) => label.removeFromThreads(chunk));
}
}
const userLabels = (() => {
let cache = {};
return {
update() {
cache = Object.fromEntries(GmailApp.getUserLabels().map(label => [label.getName(), label]));
},
get(name) {
if (!cache[name]) {
cache[name] = GmailApp.createLabel(name);
}
return cache[name];
},
};
})();