Last active
April 20, 2021 07:10
-
-
Save devonChurch/dfa838a12d9dd08d1f68a7e4f36e452d to your computer and use it in GitHub Desktop.
Fetch, Flatten, Sanitise and Set Testimonial Items
This file contains hidden or 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 Firestore = require("@google-cloud/firestore"); | |
const functions = require("firebase-functions"); | |
const axios = require("axios"); | |
const API_ENDPOINT = "https://services.languageperfect.com/json.rpc"; | |
const API_METHOD = "nz.co.LanguagePerfect.Services.PortalsAsync.ControlPanel.NewsPortal.GetCommunityArticlesPublic"; // prettier-ignore | |
const FIRESTORE_COLLECTION = "testimonialsFiltered"; | |
const FIRESTORE_PROJECT_ID = "testimonials-4d1e6"; | |
const COUNTRIES = [ | |
1, // International, | |
2, // New Zealand | |
3, // Australia | |
]; | |
/** | |
* Get as many testimonial items as we can that are associated with the supplied | |
* `Country` code. | |
* | |
* @note We make sure to extract the items from the response payload before resolving | |
* this async sequence. | |
*/ | |
const getRawitems = ({ Country }) => | |
axios | |
.post(API_ENDPOINT, { | |
method: API_METHOD, | |
params: [ | |
{ | |
// @note We do not have an `Infinity` or "all" value here, so in order to get every item, we ask | |
// for an enormous set and take the values that were used to attempt the quota. | |
NumberOfArticles: 99999999, | |
DepartmentIDs: [], | |
Country, | |
}, | |
], | |
}) | |
.then((response) => response.data.result.Articles); | |
/** | |
* Strip down the Back-end item structure to a reduced "slim" payload for the Front-end. | |
*/ | |
const sanitizeItems = (items) => | |
items.map((item) => ({ | |
// @note the original `ItemID` is changed to `id` when sanitising. | |
id: item.ItemID, | |
...[ | |
"AuthorFirstName", | |
"AuthorSurname", | |
"CountryName", | |
"ImageURL", | |
"PlainTextMessage", | |
"PostDate", | |
"SchoolLatitude", | |
"SchoolLongitude", | |
"SchoolName", | |
"StateAbbreviation", | |
].reduce((acc, key) => ({ ...acc, [key]: item[key] }), {}), | |
})); | |
/** | |
* Setup and hold the testimonial collection in closure. `set` items onto the collection using their | |
* `id` as the primary index. | |
* | |
* @note a `set` will either "update" or "create" an item if the `id` does not exist in the collection. | |
* | |
* @see https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document | |
*/ | |
const setItemInFirestore = (() => { | |
const firestoreCollection = new Firestore({ | |
projectId: FIRESTORE_PROJECT_ID, | |
}).collection(FIRESTORE_COLLECTION); | |
return (item) => firestoreCollection.doc(`${item.id}`).set(item); | |
})(); | |
const startSequence = async (context) => { | |
try { | |
// Get the testimonial items for each country (with independent async requests) and flatten the | |
// responses into a single "sanitized" item list. | |
const sanitizedItems = await Promise.all( | |
COUNTRIES.map((Country) => getRawitems({ Country })) | |
) | |
.then((...rawItems) => rawItems.flat(Infinity)) | |
.then(sanitizeItems); | |
// Iterate through our fetch/flattened/sanitised item list and "set" them into our Firestore | |
await Promise.all(sanitizedItems.map(setItemInFirestore)); | |
} catch (error) { | |
console.error(error); | |
} | |
}; | |
// @see https://firebase.google.com/docs/functions/schedule-functions | |
// @see https://cloud.google.com/appengine/docs/standard/python/config/cronref | |
exports.scheduledFunction = functions.pubsub | |
.schedule("every 24 hours") | |
.onRun(startSequence); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Correct codes are: