After a few days trying to book a Visa appointment with TLS Contact which had 0 availability and the consulate telling me to just often refresh, I decided to write a Chrome extension to check when they add them and notify me in case I would be around.
In the past I had done that with scripts after saving the cookies/tokens but this time I decided to try doing it in the browser.
Pros:
- I just need to login in a tab and let it there. It keeps refreshing so the session remains valid, but if it expired I would just need to login again.
- I get to learn extensions APIs
Cons:
- I will not be notified while not in front of my computer, however they seem to be manually adding the appointments so only during working hours
The first part was to create a content script to be run in the context of the page each time I visit a page matching the given URL. This is achieved by adding this to the manifest.json:
"content_scripts": [
{
"matches": ["https://*.tlscontact.com/*/myapp.php*"],
"js": ["contentScript.js"]
}
],
In that script I made it reload the page every 10 minutes (as the data is directly in the response from the PHP script) and when the page is loaded to parse it to find available appointments. I then used the storage API to preserve that list between reloads and compare to know if there are new appointments.
I used the sync API, meaning it is shared between my browsers, just because I can.
chrome.storage.sync.get('available', function(result) {
var av = result['available'] || {};
// Diff, log changes and notify of new ones
chrome.storage.sync.set({available: available}, function() {});
});
The next interesting part is the notifications, as user scripts are very restricted and can not use the notification API. What I had to do was to add a background script, which has more power, by adding this to the manifest.json:
"background": {
"scripts": ["background.js"],
"persistent": false
},
Now when the content script wants to notify of a new appointment, it sends a message:
chrome.runtime.sendMessage({Appointment: a}, function(response) {});
In the background script, I listen to those messages and create notifications:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
chrome.notifications.create(request.Appointment, {
type: 'basic',
title: 'New appointment available!',
message: request.Appointment
}, function(notificationId) {});
sendResponse({response: ""});
}
);
And that's it! It turned out to be much simpler than expected, and we booked an appointment the next day.