Skip to content

Instantly share code, notes, and snippets.

@bentorkington
Created August 22, 2021 19:23
Show Gist options
  • Save bentorkington/fcb7310e2d9b4138349326f5ad815a03 to your computer and use it in GitHub Desktop.
Save bentorkington/fcb7310e2d9b4138349326f5ad815a03 to your computer and use it in GitHub Desktop.
Original prototype NZ Covid Locations of Interest bot
const axios = require("axios");
const cheerio = require("cheerio");
const crypto = require('crypto');
const fs = require('fs-extra');
const { TwitterClient } = require('twitter-api-client');
// On launch, load the list of locations that have already been tweeted
// This is a JSON object containting hashes of the names and addresses of locations.
let locations = fs.readJSONSync('./locations.json');
// Credentials for the Twitter client. In addition to your own Twitter account, you'll need to set
// set up developer access to their API in the Twitter Developer Portal. You can find a guide here:
// https://blog.shahednasser.com/simple-twitter-bot-tutorial-with-node-js/
const twitterClient = new TwitterClient({
apiKey: '<YOUR API KEY HERE>',
apiSecret: '<YOUR API SECRET HERE>',
accessToken: '<YOUR ACCESS TOKEN HERE>',
accessTokenSecret: '<YOUR ACCESS TOKEN SECRET HERE>',
});
const locationsUrl = 'https://www.health.govt.nz/our-work/diseases-and-conditions/covid-19-novel-coronavirus/covid-19-health-advice-public/contact-tracing-covid-19/covid-19-contact-tracing-locations-interest';
async function fetchHTML(url) {
// This fetches the web page, and returns the content in `data`. If it fails, (if the web server is
// temporarily unavailable, for example), it will throw an exception, which is handled in the main
// loop of the program
const { data } = await axios.get(url)
// Now that we've got the data, give it to Cheerio, which understands how to parse HTML and helps us
// find particular elements in it. Cheerio is similar to jQuery, which you may have heard of.
return cheerio.load(data)
}
function poll() {
fetchHTML(locationsUrl) // We call the above function, which returns a Cheerio object, representing the page.
.then(($) => { // `$` is the conventional variable name when working with jQuery-like syntax
// Now we want to look for HTML <table> elements containting the Locations of Interest
// When I first wrote this bot, there was one table for each region (roughly). This query
// asks Cheerio to find all elements that:
// are <table> elements, AND
// have `table-style-two` in the list of classes
const regionTables = $('table.table-style-two');
// Now we have a number of table, we want to iterate over each of them. The Cheerio `each`
// function will run a block of code once for each table it found in the step above.
// Inside that function, `i` will be the index, a number that starts at zero and increments
// for each element, and `elem` will be the table element itself.
regionTables.each((i, elem) => {
// We need to get that element, in this case a single table, and create another Cheerio
// object from it so we can search inside that.
const region = $(elem);
// Each table has a number of rows, which are represented by <tr> elements. If we only
// searched for `tr` elements, we'd get the column headers as well as the data, but
// if we restrict our search to `tr` elements that are inside `tbody` elements, we'll
// get only the data we want. Take a look at the HTML of a table to see what I mean.
const rows = region.find('tbody > tr');
// Another 'for-each' loop, the following block of code runs once for each location
// of Interest we find:
rows.each((i, elem) => {
const cells = $(elem).find('td'); // Inside each table row, get each table cell
// Make an object to store the location details:
// Look up the cell: `.eq(<COLUMN NUMBER>)
// Get the text content: `.text()`
// And trim any leading or trailing whitespace from the text: `.trim()`
const loi = {
name: cells.eq(0).text().trim(),
address: cells.eq(1).text().trim(),
day: cells.eq(2).text().trim(),
times: cells.eq(3).text().trim(),
}
// Now we create a SHA checksum of the location. This is a unique number representing
// the combination of name, address and exposure date / time. This is what we store
// to remember which locations and times we've already published.
var shasum = crypto.createHash('sha1');
var update = `${loi.name}\n${loi.address}\n${loi.day}\n${loi.times}`;
shasum.update(update);
const digest = shasum.digest('hex');
// `digest` will be some very long number like f0fe19ce85ffcce3142d12b739dbbc9a435dbbd5
// The same name, address and time will always produce the same hash, but if any of these values
// are different (e.g. if the same location is published for a different day, or if the exposure
// time is changed even by one minute) the hash will be different.
// Now, if that digest is not in our `locations.json` file, it is either a new location, or an
// old location which has had its details edited. (We actually can't tell the difference here)
if (!locations[digest]) {
// It's time to create a tweet.
// Get the details from the `loi` object we created above, and add the offical URL so people have
// something to click on to check the official site
const status = `New location: ${loi.name}, ${loi.address} on ${loi.day} ${loi.times} ${locationsUrl}`;
// Now we send the tweet, `twitterClient` does all the work:
twitterClient.tweets.statusesUpdate({ status })
.then(response => {
// The tweet was posted successfully. We're given a `response` object which contains
// details about the tweet, including a unique number called the Tweet ID
console.log("Tweeted:", status);
// Save the hash of the location to our database, with the Tweet ID as the value. This
// will allow us to find an old tweet given a name, address and time in case we need to
// take further action with it later.
locations[digest] = response.id_str;
})
.catch(err => { console.error(err); });
}
});
})
// Save the database to disk. Do this each time we scan the table. There is a slight problem
// here, see if you can figure out what it is:
fs.writeJSONSync('./locations.json', locations);
// Run this all again after a delay. `setTimeout` takes the duration to sleep in milliseconds,
// we want to sleep for one minute (which contains 60 seconds (which each contain 1000 milliseconds))
setTimeout(poll, 1000 * 60 * 1);
});
}
poll();
<ul>
<li>
<a href="#current">Current locations of interest in New Zealand</a>
<ul style="margin-bottom: 0;">
<li>
<a href="#auckland">Auckland</a>
</li>
<li>
<a href="#coromandel">Coromandel</a>
</li>
</ul>
</li>
<li>
<a href="#business">Guidance for businesses</a>
</li>
</ul>
<hr/>
<h2>
<a id="current" name="current"></a>Current locations of interest in New Zealand</h2>
<table class="table-style-two">
<caption id="Auckland" name="Auckland">
<a id="auckland" name="auckland"></a>Auckland locations of interest</caption>
<colgroup>
<col/>
<col/>
<col/>
<col/>
<col/>
</colgroup>
<thead>
<tr>
<th scope="col">Location name</th>
<th scope="col">Address</th>
<th scope="col">Day</th>
<th scope="col">Times</th>
<th scope="col">Date added</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sumthin Dumplin</td>
<td>18 Wellesley Street East, Auckland Central, 1010</td>
<td>Tuesday 3 August</td>
<td>1.45 pm - 2.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Lynn Mall</td>
<td>3058 Great North Road, New Lynn, Auckland, 0600</td>
<td>Friday 6 August</td>
<td>6.00 pm - 7.30 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Mexico Britomart</td>
<td>23 Britomart Place, Auckland Central, 1010</td>
<td>Monday 9 August</td>
<td>5.55 pm - 8.15 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Bus 97B Birkdale to Auckland CBD</td>
<td>Bus 97B</td>
<td>Tuesday 10 August</td>
<td>11.30 pm - 12.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>St Pierre&#39;s Sushi Auckland CBD</td>
<td>20 Elliott Street, Auckland Central, Auckland 1010</td>
<td>Tuesday 10 August</td>
<td>1.00 pm - 1.15 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>The Warehouse Auckland CBD&nbsp;</td>
<td>21 Elliott Street, Auckland Central, 1010</td>
<td>Tuesday 10 August</td>
<td>1.15 pm - 1.30 pm</td>
<td>18-Jan</td>
</tr>
<tr>
<td>Event Cinemas Queen Street</td>
<td>1/291 Queen Street, Auckland Central, 1010</td>
<td>Tuesday 10 August</td>
<td>1.30 pm - 4.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Gongcha Bubble Tea</td>
<td>164 Queen Street, Auckland Central, 1010</td>
<td>Tuesday 10 August</td>
<td>1.45 pm - 1.55 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>St Pierres Sushi Elliot Street</td>
<td>20 Elliott Street, Auckland Central, Auckland 1010</td>
<td>Wednesday 11 August</td>
<td>11.30 am - 12.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Event Cinemas Queen Street</td>
<td>1/291 Queen Street, Auckland Central, 1010</td>
<td>Wednesday 11 August</td>
<td>1.30 pm - 4.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Avondale College</td>
<td>51 Victor Street, Avondale, Auckland 1026</td>
<td>Thursday 12 August</td>
<td>8.45 am - 3.15 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Crumb Grey Lynn</td>
<td>Ariki Street, Grey Lynn, Auckland, 1021</td>
<td>Thursday 12 August</td>
<td>10.00 am - 10.10 am</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Glasscorp Limited Albany</td>
<td>124 Bush Road, Rosedale, Auckland 0632</td>
<td>Thursday 12 August</td>
<td>12.30 pm - 1.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Unique Hardware Rosedale</td>
<td>1/16 Arrenway Drive, Rosedale, Auckland 0632</td>
<td>Thursday 12 August</td>
<td>12.30 pm - 1.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Avondale College</td>
<td>51 Victor Street, Avondale, Auckland 1026</td>
<td>Friday 13 August</td>
<td>8.45 am - 3.15 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Starbucks Queen Street</td>
<td>220 Queen Street, City Centre, 1010</td>
<td>Friday 13 August</td>
<td>12.15 pm - 12.30 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Liquor King Ponsonby</td>
<td>254 Ponsonby Road, Ponsonby, Auckland, 1011</td>
<td>Friday 13 August</td>
<td>6.15 pm - 6.30 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Sweat Shop Brew Kitchen</td>
<td>7 Sale Street, Freemans Bay, Auckland CBD, 1010</td>
<td>Friday 13 August</td>
<td>9.00 pm - 12.00 am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Denny&#39;s CBD</td>
<td>51 Hobson Street Auckland CBD, 1010</td>
<td>Friday 13 August</td>
<td>1.00 am - 1.30 am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Albany Westfield Mall&nbsp;</td>
<td>219 Don McKinnon Drive, Albany, 0632</td>
<td>Friday 13 August</td>
<td>5.10 pm - 6.30 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Countdown Birkenhead&nbsp;</td>
<td>Cnr Highbury Pass, Birkenhead, 0626</td>
<td>Friday 13 August</td>
<td>6.00 pm - 6.30 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Black Bull Liquor Store</td>
<td>54 Northcote Road, Northcote, 0627</td>
<td>Friday 13 August</td>
<td>6.40 pm - 6.45 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Chu Thai Eatery&nbsp;</td>
<td>224 Ponsonby Road, Ponsonby, 1011</td>
<td>Friday 13 August</td>
<td>6.30 pm - 8.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Liquor King Ponsonby&nbsp;</td>
<td>254 Ponsonby Road, Ponsonby, 1011</td>
<td>Friday 13 August</td>
<td>8.15pm - 8.45 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>McDonalds Stoddard Road</td>
<td>22 Stoddard Road, Wesley, 1041</td>
<td>Friday 13 August</td>
<td>10.00 pm - 10.30 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Bar 101</td>
<td>18 Elliott Street, Auckland CBD, Auckland 1010</td>
<td>Friday 13 August</td>
<td>11.33 pm - 1.15 am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Sky City Casino</td>
<td>72 Victoria Street West Auckland Central</td>
<td>Saturday 14 August</td>
<td>1.15 am - 3.00 am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Bar 101</td>
<td>18 Elliott Street, Auckland CBD, Auckland 1010</td>
<td>Saturday 14 August</td>
<td>3.00 am - 3.15 am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>McDonalds Glenfield</td>
<td>Cnr Glenfield &amp;, Kaipatiki Road, Glenfield, 0629</td>
<td>Saturday 14 August</td>
<td>1.00 am - 1.15 am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Pak n Save Wairau Road</td>
<td>30 Wairau Road, Wairau Valley, Auckland 0627</td>
<td>Saturday 14 August</td>
<td>3.20 pm - 3.50 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Countdown Glenfield Mall</td>
<td>Cnr Bentley Ave &amp;, Glenfield Road, Glenfield,0629</td>
<td>Saturday 14 August</td>
<td>5.00 pm - 5.15 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>The Good Home Birkenhhead&nbsp;</td>
<td>83 Birkenhead Avenue, Birkenhead, 0626</td>
<td>Saturday 14 August</td>
<td>6.30 pm - 7.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Central Auckland Church of Christ</td>
<td>52 Hepburn Street, Freemans Bay, Auckland 1011</td>
<td>Sunday 15 August</td>
<td>10.15 am - 12.02 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>BP Birkenhead&nbsp;</td>
<td>172-178 Mokoia Road, Birkenhead, 0626</td>
<td>Sunday 15 August</td>
<td>10.30 am - 10.45 am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Pak n Save Wairau&nbsp;</td>
<td>30-60 Wairau Road, Glenfield, 0627</td>
<td>Sunday 15 August</td>
<td>11.00 pm - 12.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Elliot Stables</td>
<td>1/41 Elliott Street, Auckland Central, 1010</td>
<td>Sunday 15 August</td>
<td>12.10 pm - 1.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Latin Market near La Pachamama</td>
<td>Near 179a Archers Road, Glenfield, 0629</td>
<td>Sunday 15 August</td>
<td>12.30 pm - 12.45 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Glenfield Mall / Katsubi Japanese</td>
<td>Glenfield Road &amp; Downing Street, Glenfield, 0629</td>
<td>Sunday 15 August</td>
<td>1.00 pm - 2.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>The Pumphouse Theatre</td>
<td>2A Manurere Avenue, Takapuna, 0622</td>
<td>Sunday 15 August</td>
<td>1.30 pm - 7.30 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Chartwell</td>
<td>27 Chartwell Avenue, Glenfield, 0629</td>
<td>Sunday 15 August</td>
<td>5.25 pm - 5.29 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Countdown, Lynfield&nbsp;</td>
<td>570 Hillsborough Road, Mount Roskill, 1041</td>
<td>Sunday 15 August</td>
<td>8.00 pm - 8.15 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>BP Northcote</td>
<td>50 Northcote Road, Northcote, Auckland 0627</td>
<td>Sunday 15 August</td>
<td>7.15 pm - 7.30 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Devonport Pharmacy Devonport</td>
<td>33 Victoria Road, Devonport, Auckland 0624</td>
<td>Monday 16 August</td>
<td>2.15 pm - 2.30 pm</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Green Bay Takeaways</td>
<td>56B Godley Road, Green Bay, Auckland 0604</td>
<td>Monday 16 August</td>
<td>4.00 pm - 4.15 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Passion Bakery</td>
<td>34 Birkdale Road, Birkdale, Auckland 0626</td>
<td>Monday 16 August</td>
<td>12.45 pm - 1.15 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Countdown Birkenhead</td>
<td>Cnr Highbury Pass &amp; Birkenhead Ave, Birkenhead, 0626</td>
<td>Monday 16 August</td>
<td>12.30 pm - 12.45 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Pizza Hut Birkenhead&nbsp;</td>
<td>3/75 Mokoia Road, Birkenhead, 0626</td>
<td>Monday 16 August</td>
<td>1.30 pm - 2.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Warehouse New Lynn</td>
<td>7/13 Rata Street, New Lynn, Auckland 0600</td>
<td>Monday 16 August</td>
<td>7.45 am - 8.15am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Countdown Birkenhead</td>
<td>Cnr Highbury Pass &amp; Birkenhead Ave, Birkenhead, 0626</td>
<td>Monday 16 August</td>
<td>7.00 am - 7.15 am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Avondale College</td>
<td>51 Victor Street, Avondale, Auckland 1026</td>
<td>Monday 16 August</td>
<td>8.45 am - 12.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Unichem Pharmacy Birkenhead</td>
<td>Birkenhead Avenue Shop 28, Highbury Shopping Centre</td>
<td>Tuesday 17 August</td>
<td>9.15 am - 9.30 am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Auckland University of Technology</td>
<td>2 Governor Fitzroy Place, Auckland Central, Auckland 1010</td>
<td>Tuesday 17 August</td>
<td>11.30 am - 1.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Mamak Malaysian Restaurant&nbsp;</td>
<td>50 Kitchener Street, Auckland Central, 1010</td>
<td>Tuesday 17 August</td>
<td>1.15 pm - 1.30 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Remuera Exchange</td>
<td>2A Dilworth Avenue, Remura, Auckland 1050</td>
<td>Tuesday 17 August</td>
<td>1.33 pm - 1.35 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Bus 25B City Centre to Blockhouse Bay</td>
<td>Bus 25B</td>
<td>Tuesday 17 August</td>
<td>1.45 pm - 2.15 pm</td>
<td>18-Aug</td>
</tr>
</tbody>
</table>
<table class="table-style-two">
<caption>
<a id="coromandel" name="coromandel"></a>Coromandel</caption>
<colgroup>
<col/>
<col/>
<col/>
<col/>
<col/>
</colgroup>
<thead>
<tr>
<th scope="col">Location name</th>
<th scope="col">Address</th>
<th scope="col">Day</th>
<th scope="col">Times</th>
<th scope="col">Date&nbsp;added</th>
</tr>
</thead>
<tbody>
<tr>
<td>Star and Garter Hotel Coromandel</td>
<td>5 Kapanga Road, Coromandel 3506&nbsp;</td>
<td style="white-space: nowrap;">Friday 13 August</td>
<td style="white-space: nowrap;">&nbsp;6:39 pm - 7.40 pm</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Umu Cafe Coromandel</td>
<td>22 Wharf Road, Coromandel,3506</td>
<td style="white-space: nowrap;">Friday 13 August</td>
<td style="white-space: nowrap;">7:40 pm - 8.30 pm</td>
<td>17-Aug</td>
</tr>
<tr>
<td>BP Gas Station Coromandel</td>
<td>BP Gas Station, Tiki Road, Coromandel, 3056</td>
<td style="white-space: nowrap;">Saturday 14 August</td>
<td style="white-space: nowrap;">&nbsp;9:30 am - 9.40 am</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Driving Creek Railway Tours Coromandel - booking office</td>
<td>380 Driving Creek Road, Coromandel, 3506</td>
<td style="white-space: nowrap;">Saturday 14 August</td>
<td style="white-space: nowrap;">&nbsp;10:30 am - 10.50 am</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Jaks Cafe &amp; Bar Coromandel</td>
<td>104 Kapanga Road,Coromandel, 3506</td>
<td style="white-space: nowrap;">Saturday 14 August</td>
<td style="white-space: nowrap;">10:50 am - 11.30 am</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Driving Creek Railway Tours Coromandel - train tour</td>
<td>380 Driving Creek Road, Coromandel, 3506</td>
<td style="white-space: nowrap;">Saturday 14 August</td>
<td style="white-space: nowrap;">11.20 am - 1.00 pm</td>
<td>18-Aug</td>
</tr>
<tr>
<td>Hereford &#39;n&#39; a Pickle Coromandel</td>
<td>2318 Colville Road, RD 4, Colville, Coromandel 3584</td>
<td style="white-space: nowrap;">Saturday 14 August</td>
<td style="white-space: nowrap;">&nbsp;1:25 pm - 2.15 pm</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Taras Beads Coromandel</td>
<td>1/75 Kapanga Road, Coromandel, 3506</td>
<td style="white-space: nowrap;">Saturday 14 August</td>
<td style="white-space: nowrap;">3:00 pm - 3.10 pm</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Richardsons Real Estate Coromandel</td>
<td>151 Kapanga Road,&nbsp;Coromandel, 3506&nbsp;</td>
<td style="white-space: nowrap;">Saturday 14 August</td>
<td style="white-space: nowrap;">3:30 pm - 3.35 pm</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Umu Cafe Coromandel</td>
<td>22 Wharf Road, Coromandel,3506</td>
<td style="white-space: nowrap;">Saturday 14 August</td>
<td style="white-space: nowrap;">&nbsp;6:17 pm - 7.11 pm</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Star and Garter Hotel Coromandel</td>
<td>5 Kapanga Road, Coromandel 3506&nbsp;</td>
<td style="white-space: nowrap;">Saturday 14 August</td>
<td style="white-space: nowrap;">7:11 pm - 9.00 pm</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Umu Cafe Coromandel</td>
<td>22 Wharf Road, Coromandel,3506</td>
<td style="white-space: nowrap;">Sunday 15 August</td>
<td style="white-space: nowrap;">10.14 am - 11.10 am</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Taras Beads Coromandel</td>
<td>1/75 Kapanga Road, Coromandel, 3506</td>
<td style="white-space: nowrap;">Sunday 15 August</td>
<td style="white-space: nowrap;">10.00 am - 10.05 am</td>
<td>17-Aug</td>
</tr>
<tr>
<td>Woodturners Caf&eacute;</td>
<td>3815 State Highway 2 RD6 Mangatarata</td>
<td style="white-space: nowrap;">Sunday 15 August</td>
<td style="white-space: nowrap;">12.40 pm - 1.25 pm</td>
<td>17-Aug</td>
</tr>
</tbody>
</table>
@bentorkington
Copy link
Author

We were really excited when the Github feed was announced, as it had all the extra info needed to make a solid product. Alas, it's not quite ready for prime time yet.

To begin with, the Github wasn't updated as regularly as the main site, so timeliness goes out the window. Additionally, some real problems with data cleanliness were revealed, such as macrons getting crushed, turning names like Ōtāhuhu into '?t?huhu', take a look at the commit history.

Ultimately, an API is the real solution and is in the works. Rather than spend days chasing moving targets while the MoH data team are under huge pressure trying to build the plane while they fly it, the choice was made to wait until they've finished.

@idanoo
Copy link

idanoo commented Aug 22, 2021

Ah that makes sense! Didn't realise it wasn't updated as frequently. An API would be ideal haha

Either way, great work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment