Instantly share code, notes, and snippets.
Created
September 10, 2022 11:58
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save jcpsantiago/bb70713a52dc40f2734195ac82614415 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
const { | |
schedule | |
} = require("@netlify/functions"); | |
const nodemailer = require("nodemailer"); | |
const { | |
GoogleSpreadsheet | |
} = require("google-spreadsheet"); | |
const axios = require("axios"); | |
const papa = require("papaparse"); | |
const doc = new GoogleSpreadsheet(process.env.GOOGLE_SHEET_ID); | |
const transporter = nodemailer.createTransport({ | |
auth: { | |
pass: process.env.EMAIL_PASSWORD, | |
user: process.env.EMAIL_ADDRESS | |
}, | |
host: "smtp.porkbun.com", | |
pool: true, | |
port: 587, | |
secure: false // true for 465, false for other ports | |
}); | |
const shipping_companies = { | |
GLS: { | |
name: "GLS", | |
url: "https://www.gls-pakete.de/en/parcel-tracking?trackingNumber=" | |
}, | |
NLPOST: { | |
name: "PostNL", | |
url: "https://postnl.post/details/?barcode=" | |
}, | |
UPS_SAVER: { | |
name: "UPS", | |
url: "https://wwwapps.ups.com/WebTracking/track?loc=en_EN&track=yes&trackNums=" | |
} | |
}; | |
const title_case = function (str) { | |
return str.toLowerCase().replace(/\b\w/g, (s) => s.toUpperCase()); | |
}; | |
const get_new_shipments = function (zencsv, shipped_refs) { | |
const sorted = zencsv.data.sort( | |
function (a, b) { | |
return new Date(a.created_at) - new Date(b.created_at); | |
} | |
); | |
const filtered = sorted.filter((obj) => { | |
return !shipped_refs.includes(obj.reference); | |
}); | |
return filtered; | |
}; | |
const email_tracking_numbers = async function (obj) { | |
console.log( | |
"Tracking code:", obj.shipment_tracking_number, | |
", shipping company:", obj.shipment_shipping_option, | |
", customer's email:", obj.shipping_address_email | |
); | |
// didn't want to spend time understanding high-level functions, so shipping_companies is injected here | |
const company_labels = Object.keys(shipping_companies); | |
if (company_labels.includes(obj.shipment_shipping_option)) { | |
console.log("Adding row to sheet, reference:", obj.reference); | |
const shipping_company = shipping_companies[obj.shipment_shipping_option]; | |
console.log("Sending email to", obj.shipping_address_email); | |
const mail_res = await transporter.sendMail({ | |
from: "[email protected]", | |
to: "[email protected]", | |
// to: obj.shipping_address_email, | |
// bcc: "[email protected]", | |
subject: "Your book is on the way!", | |
html: "<p>Dear " + obj.shipping_address_name + ",</p>" + | |
"<p>Your copy of <em>Urology: the last review</em> is on the way! " + | |
"You can track your " + shipping_company.name + " parcel with the tracking number <a href='" + | |
shipping_company.url + obj.shipment_tracking_number + "'>" + | |
obj.shipment_tracking_number + "</a>." + | |
"<p>I hope you enjoy the book, and wish you all the best for your studies!</p>" + | |
"<p>Best regards,</p>" + | |
"<p>Inês Santiago @knowuro</p>" | |
}); | |
if (mail_res.messageId) { | |
console.log("Message sent: %s", mail_res.messageId); | |
} else { | |
console.log("Couldn't send email", mail_res); | |
} | |
return mail_res; | |
} else { | |
console.log(`I don't know the ${obj.shipment_shipping_option} shipping provider`); | |
const mail_res = await transporter.sendMail({ | |
from: "[email protected]", | |
to: "[email protected]", | |
subject: "Cliente não foi avisado", | |
text: "Não sei como lidar com " + obj.shipment_shipping_option + " na encomenda " + obj.reference + "." | |
}); | |
return mail_res; | |
} | |
}; | |
const handler = async function (event, context) { | |
console.log("Hello! Just doing my scheduled job"); | |
try { | |
await doc.useServiceAccountAuth({ | |
client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL, | |
private_key: process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, "\n") | |
}); | |
await doc.loadInfo(); | |
const sheet = doc.sheetsByTitle.zenorders; | |
console.log("Fetching orders from Google Sheets"); | |
const rows = await sheet.getRows(); | |
console.log("Reducing rows into Array"); | |
const shipped_refs = rows.reduce((result, current) => { | |
return result.concat(current.reference); | |
}, []); | |
console.log("These are", shipped_refs.length, "shipped references"); | |
const axiosconfig = { | |
method: "get", | |
url: "https://api.zenfulfillment.com/orders/export?status=SHIPPED&perPage=100", | |
headers: { | |
Authorization: "ZF-API " + process.env.ZF_API_KEY | |
} | |
}; | |
const zencsv = await axios(axiosconfig) | |
.then((response) => { | |
const parsed = papa.parse(response.data, { | |
header: true | |
}); | |
return parsed; | |
}) | |
.catch(function (error) { | |
console.log(error); | |
return transporter.sendMail({ | |
from: "[email protected]", | |
to: "[email protected]", | |
subject: "Encomenda falhou!!", | |
text: error | |
}, (error, info) => { | |
if (error) { | |
console.log(error); | |
return false; | |
} else { | |
console.log("Message sent: %s", info.messageId); | |
return true; | |
} | |
}); | |
console.log(`Function failed with error: ${error}`); | |
return { | |
err: error, | |
response: { | |
statusCode: 400, | |
body: `Error: ${error.message}` | |
} | |
}; | |
}); | |
if (Object.keys(zencsv).includes("err")) { | |
return zencsv.reponse; | |
} else { | |
const new_shipments = get_new_shipments(zencsv, shipped_refs); | |
if (new_shipments.length > 0) { | |
const results = await Promise.all(new_shipments.map(email_tracking_numbers)); | |
const added_rows = await sheet.addRows(new_shipments, { | |
insert: true | |
}); | |
// FIXME: delete row in sheet for which the email failed | |
if (results.every((element) => element != false)) { | |
return { | |
statusCode: 200 | |
}; | |
} else { | |
return { | |
statusCode: 400 | |
}; | |
} | |
} else { | |
console.log("FILTERED EVERYTHING, nothing to do.."); | |
return { | |
statusCode: 200, | |
}; | |
} | |
} | |
} catch (error) { | |
console.log(`Function failed with error: ${error}`); | |
return { | |
statusCode: 400, | |
body: `Error: ${error.message}` | |
}; | |
} | |
}; | |
module.exports.handler = schedule("30 13 * * *", handler); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment