Skip to content

Instantly share code, notes, and snippets.

@jcpsantiago
Created September 10, 2022 11:58
Show Gist options
  • Save jcpsantiago/bb70713a52dc40f2734195ac82614415 to your computer and use it in GitHub Desktop.
Save jcpsantiago/bb70713a52dc40f2734195ac82614415 to your computer and use it in GitHub Desktop.
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