|
function getValueFromMatchAtIndex(match, index) { |
|
if (match && match.length > index) { |
|
return match[index]; |
|
} |
|
} |
|
|
|
function parseAmount(amountStr) { |
|
return amountStr && parseFloat(amountStr.replace(',', '')) || undefined; |
|
} |
|
|
|
const accountsMap = { |
|
chase: { |
|
match2: (from) => from.indexOf('chase') >= 0, |
|
fields: (body) => { |
|
const accountMatch = body.match(/Account<\/td>(.|\s)+?>((.|\s)+?)</m); |
|
const merchantMatch = body.match(/Merchant<\/td>(.|\s)+?>((.|\s)+?)</m); |
|
const amountMatch = body.match(/Amount<\/td>(.|\s)+?>\$((.|\s)+?)</m); |
|
const account = getValueFromMatchAtIndex(accountMatch, 2); |
|
let merchant = getValueFromMatchAtIndex(merchantMatch, 2); |
|
const amount = parseAmount(getValueFromMatchAtIndex(amountMatch, 2)); |
|
|
|
if (merchant.indexOf('AMZN') >= 0) { |
|
merchant = 'Amazon'; |
|
} |
|
const ynabAccount = (account && account.indexOf('1234') >= 0) |
|
? { account: 'ynab-chase-account-id', name: 'Chase Fredom' } |
|
: (account && account.indexOf('5678') >= 0) |
|
? { account: 'ynab-amazon-account-id', name: 'Amazon Prime' } |
|
: undefined; |
|
return { ...ynabAccount, merchant, amount }; |
|
} |
|
}, |
|
amazon: { |
|
match2: (from) => from.indexOf('chase') >= 0 |
|
}, |
|
citi: { |
|
match2: (from) => from.indexOf('citi') >= 0, |
|
fields: (body) => { |
|
const merchant = getValueFromMatchAtIndex(body.match(/Merchant<\/span>(.|\s)+?>\b((.|\s)*?)<\/span/m), 2); |
|
const amount = parseAmount(getValueFromMatchAtIndex(body.match(/Amount(.|\s)+?\$(.|\s)*?([\d\,\.]*)</m), 3)); |
|
|
|
const account = 'ynab-city-account-id'; |
|
|
|
return { account, merchant, amount, name: 'Citi' } |
|
} |
|
} |
|
} |
|
|
|
function processEmails() { |
|
Logger.log('Starting to process emails'); |
|
const toProcessLabelName = 'ynab-to-process'; |
|
const processedLabelName = 'ynab-processed'; |
|
const toProcessLabel = GmailApp.getUserLabelByName(toProcessLabelName); |
|
const processedLabel = GmailApp.getUserLabelByName(processedLabelName) || GmailApp.createLabel(processedLabelName); |
|
|
|
Logger.log(`Starting to iterate over ${toProcessLabel.getThreads().length} emails`); |
|
toProcessLabel.getThreads().forEach(email => { |
|
Logger.log('Starting on email') |
|
const success = email |
|
.getMessages() |
|
.map(processEmailMessage) |
|
.reduce((prev, cur) => prev && Math.round(cur.getResponseCode() / 100) === 2, true); |
|
Logger.log('Finished email with status:', success); |
|
if (success) { |
|
email |
|
.removeLabel(toProcessLabel) |
|
.addLabel(processedLabel) |
|
.moveToArchive() |
|
.refresh(); |
|
} else { |
|
Logger.log('Failed to process email thread'); |
|
} |
|
}); |
|
} |
|
|
|
function processEmailMessage(message) { |
|
Logger.log('Starting to process message'); |
|
const accountName = Object.keys(accountsMap) |
|
.filter(a => accountsMap[a].match2(message.getFrom())) |
|
.shift(); |
|
if (!accountName) { |
|
Logger.log(`Failed find account for email from ${message.getFrom()}`); |
|
return false; |
|
} |
|
Logger.log(`Found account '${accountName}'`); |
|
|
|
const account = accountsMap[accountName]; |
|
const fields = account.fields(message.getBody()); |
|
Logger.log('Fields are:', fields) |
|
|
|
const transaction = { |
|
budgetId: <ynab-budget-id>, |
|
accountId: fields.account, |
|
amount: fields.amount * -1, |
|
payeeName: fields.merchant, |
|
approved: false |
|
}; |
|
Logger.log(transaction); |
|
// submit ynab transaction |
|
return enterTransaction(transaction); |
|
} |
|
|
|
function enterTransaction({ budgetId, accountId, amount, payeeName, approved = false, cleared } = transaction) { |
|
var transactionData = { |
|
transaction: { |
|
account_id: accountId, |
|
date: Utilities.formatDate(new Date(), "UTC", "yyyy-MM-dd"), |
|
amount: parseInt(amount * 1000), |
|
payee_name: payeeName, |
|
memo: 'Entered automatically by Google Apps Script automation', |
|
cleared, |
|
approved |
|
} |
|
}; |
|
|
|
var options = { |
|
method: 'POST', |
|
payload: JSON.stringify(transactionData), |
|
headers: headers |
|
}; |
|
var transactionUrl = url + '/budgets/' + budgetId + '/transactions'; |
|
return UrlFetchApp.fetch(transactionUrl, options); |
|
} |
Hey there. I could really use a little more detailed instructions on what exactly to modify in your script to have this work with my own bank account. Thanks!!