Created
September 8, 2021 03:56
-
-
Save tonyxiao/a1b44f0788d7106a036698f0c5d70f8d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @ts-check | |
const lodash = require('lodash') | |
const addrs = require('email-addresses') | |
/** | |
* | |
* @param {*} lib | |
* @param {string} email Used for last update key | |
* @param {boolean} reset Whether to clear the key | |
* @returns | |
*/ | |
module.exports.getNewEmails = async function (lib, email, reset = false) { | |
const kLastUpdate = `LAST_UPDATE-${email}` | |
// Retrieve last e-mail data, if we need it. | |
// Limit it to last day of e-mail at worst case (1d * 24h * 60m * 60s) | |
console.log(`[${email}] Fetching last e-mail info...`) | |
if (reset) { | |
await lib.utils.kv['@0.1.16'].clear({key: kLastUpdate}) | |
} | |
const lastUpdate = await lib.utils.kv['@0.1.16'].get({ | |
key: kLastUpdate, | |
defaultValue: { | |
internalDate: ((new Date().valueOf() / 1000) | 0) - 1 * 24 * 60 * 60, | |
historyId: 0, | |
messageId: '', | |
}, | |
}) | |
let internalDate = lastUpdate.internalDate | |
let historyId = lastUpdate.historyId | |
let messageId = lastUpdate.messageId | |
// Get Gmail messages after 1s before your last e-mail | |
// This is incase we got two emails within the same 1s, but somehow missed one | |
console.log(`[${email}] Retrieving Gmail messages...`, lastUpdate) | |
/** @type {{id: string, threadId: string}[]} */ | |
const msgAndThreadIds = await lib.gmail.messages['@0.2.7'].list({ | |
query: `after:${internalDate - 1}`, | |
labelIds: ['INBOX'], | |
includeSpamTrash: false, | |
}) | |
console.log(`[${email}] Getting e-mail data for ${msgAndThreadIds.length} messages...`) | |
let messages = await Promise.all( | |
msgAndThreadIds.map(async ({id: messageId}) => { | |
/** @type {GmailFullMessage} */ | |
const msg = await lib.gmail.messages['@0.2.7'].retrieve({ | |
id: messageId, | |
format: 'FULL', | |
}) | |
// Parse these to integers | |
// internalDate is in ms, so divide by 1000 | |
msg.internalDate = Math.floor(parseInt(msg.internalDate) / 1000) | |
msg.historyId = parseInt(msg.historyId) | |
// Set our latest date / historyId | |
internalDate = Math.max(internalDate, msg.internalDate) | |
historyId = Math.max(historyId, msg.historyId) | |
if (historyId === msg.historyId) { | |
messageId = msg.id | |
} | |
const headers = lodash | |
.chain(msg.payload.headers) | |
.keyBy((h) => h.name.toLowerCase()) | |
.mapValues((v) => v.value) | |
.value() | |
/** @type {string} */ | |
// @ts-ignore | |
const fromAddress = addrs.parseOneAddress(headers.from).address | |
return {...msg, subject: headers.subject, fromAddress} | |
}), | |
) | |
// Remove any potential duplicates of e-mails we've been notified about | |
messages = messages.filter( | |
(msg) => | |
msg.historyId > lastUpdate.historyId && msg.id !== lastUpdate.messageId, | |
) | |
if (messages.length > 0) { | |
// Update our last e-mail settings, to use on next check | |
await lib.utils.kv['@0.1.16'].set({ | |
key: kLastUpdate, | |
value: { | |
internalDate: internalDate, | |
historyId: historyId, | |
messageId: messageId, | |
}, | |
}) | |
} | |
return messages | |
} | |
/** | |
* | |
@typedef {{ | |
id: string | |
threadId: string | |
labelIds: string[] | |
snippet: string | |
payload: { | |
partId: string | |
mimeType: string | |
filename: string | |
headers: { | |
name: string | |
value: string | |
}[] | |
body: Body | |
parts: any[] | |
} | |
sizeEstimate: number | |
historyId: string | |
internalDate: any | |
}} GmailFullMessage | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment