Skip to content

Instantly share code, notes, and snippets.

@xpcoffee
Created September 8, 2024 09:34
Show Gist options
  • Save xpcoffee/f1131c99db0fa1b4c77c88e5561bc09d to your computer and use it in GitHub Desktop.
Save xpcoffee/f1131c99db0fa1b4c77c88e5561bc09d to your computer and use it in GitHub Desktop.
Google Apps Script to add notes from emails to journal entries in a github repo
// This script allows me to email myself notes and this appends them to my daily notes in my private note repo
/**
* Worlflow
*/
function syncEmailNotes() {
const { content, noteMessages } = getNotesFromEmails()
if (content.length === 0) {
Logger.log("No notes found in inbox. Stopping.")
return
} else {
Logger.log("Found " + noteMessages.length + " notemails.")
}
appendToDailyNote("[email protected]", content)
archiveThreads(noteMessages)
}
/**
* Gmail
*/
NOTE_SENDER_EMAIL = "<your-email>@gmail.com"
NOTE_TAG = "#notemail"
function getNotesFromEmails() {
const threads = GmailApp.getInboxThreads()
const noteMessages = threads.reduce(extractNotes, [])
let content = ""
for (let i = 0; i < noteMessages.length; i++) {
body = noteMessages[i].message.getPlainBody()
content += "\n\n" + splitBodyToBulletNotes(body)
}
return { content, noteMessages }
}
/**
* @param {string} body
*/
function splitBodyToBulletNotes(body) {
return body.split("\n").filter(line => line.trim().length > 0).map(line => `- ${line.trim()} ${NOTE_TAG}`).join("\n")
}
/**
* returns both messsages and threads to allow threads to be archived later
* @param {{message: GmailApp.GmailMessage; thread: GmailApp.GmailThread}[]} acc message accumulator
* @param {GmailApp.GmailThread} thread
*/
function extractNotes(acc, thread) {
Logger.log(thread.getFirstMessageSubject() + " " + thread.getMessages()[0].getFrom())
if (!thread.getFirstMessageSubject().toLowerCase().includes("notes")) {
return acc
}
const message = thread.getMessages()[0]
if (!message.getFrom().includes(NOTE_SENDER_EMAIL)) {
return acc
}
acc.push({ message, thread })
return acc
}
/**
* @param {{message: GmailApp.GmailMessage; thread: GmailApp.GmailThread}[]} threadMessages
*/
function archiveThreads(threadMessages) {
for (let i = 0; i < threadMessages.length; i++) {
threadMessages[i].thread.moveToArchive()
}
}
/**
* Github
*/
const REPO = "xpcoffee/notes" // private repo
const GIT_API_URL = `https://api.github.com/repos/${REPO}/contents/`
const REPO_COMMITER = { "name": "<your-commiter-name>", "email": "<your-comitter-email>@gmail.com" }
function appendToDailyNote(sender, newContent) {
const date = Utilities.formatDate(new Date(), "CET", "yyyy-MM-dd")
const dailyNoteFileName = `journal/${date}.md`
const url = GIT_API_URL + dailyNoteFileName
const fileResult = getFile(url)
switch (fileResult.status) {
case 200:
// append to file
const content = fileResult.content + "\n\n" + newContent
updateFile({ url, sha: fileResult.sha, content })
break
case 404:
// create new file if it doesn't already exist
const noteHeader = `#${date}\n\n`
updateFile({ url, content: noteHeader + newContent })
break
default:
Logger.error(fileResult)
return
}
Logger.log("Successfully updated " + dailyNoteFileName)
}
function getFile(url) {
Logger.log(`Fetching ${url}`)
var urlFetchOptions = {
"method": "GET",
"headers": {
"Accept": "Accept: application/vnd.github+json",
"Authorization": `Bearer ${getGitToken()}`,
"X-GitHub-Api-Version": "2022-11-28",
},
"redirect": "follow",
"muteHttpExceptions": true
}
var resp = JSON.parse(UrlFetchApp.fetch(url, urlFetchOptions).getContentText())
if (resp.status !== undefined && resp.status !== 200) {
return resp
}
const contentBlob = Utilities.base64Decode(resp.content, Utilities.Charset.UTF_8)
const content = Utilities.newBlob(contentBlob).getDataAsString()
return {
status: 200,
content,
sha: resp.sha
}
}
function updateFile({ url, sha, content }) {
// log out content for now just in case its useful in debugging edits over time. remove after we have confidence in script
Logger.log((sha ? `Updating ${url}` : `Creating ${url}`) + ` with ${content} -> ${Utilities.base64Encode(content)}`)
const body = {
"message": "Updating notes from emails",
"committer": REPO_COMMITER,
"content": Utilities.base64Encode(content),
}
if (sha) {
body.sha = sha
}
var urlFetchOptions = {
"method": "PUT",
"headers": {
"Accept": "Accept: application/vnd.github+json",
"Authorization": `Bearer ${getGitToken()}`,
"X-GitHub-Api-Version": "2022-11-28",
},
"redirect": "follow",
"payload": JSON.stringify(body),
}
UrlFetchApp.fetch(url, urlFetchOptions)
}
function getGitToken() {
// generate new auth token for your repo at https://github.com/settings/tokens?type=beta
// save in apps script project settings
return PropertiesService.getScriptProperties().getProperty("GithubAuthToken")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment