June 7th, 2021 × #vaccine#covid19#javascript
Hasty Treat - Making a Vaccine Bot with JavaScript
Wes talks about how he built a Telegram bot using Node.js that constantly polled COVID vaccine availability APIs and notified him when appointments became available so he could quickly book one.
- Wes built vaccine availability checker bot
- Wes justified taking vaccine appointment
- Wes reverse engineered pharmacy vaccine APIs
- Wes fetched vaccine data and handled cookies
- Wes found pharmacy IDs to check
- Wes handled multi-step token authentication
- Wes cached vaccine availability hits
- Wes stored vaccine hits in memory only
- Wes used Telegram bot API for notifications
- Wes booked vaccine via bot
Transcript
Announcer
Monday. Monday. Monday.
Announcer
Open wide dev fans. Get ready to stuff your face with JavaScript, CSS, node modules, barbecue tips, get workflows, breakdancing, soft skill, web development, the hastiest, the craziest, the tastiest TS, web development treats coming in hot. Here is Wes, Barracuda, Boss, and Scott, El Toro Loco, Tolinski.
Scott Tolinski
CSM. Welcome to Syntax. In this Monday, hasty treat. We're gonna be doing another deep dive To one of Wes's interesting projects that he loves to do on these use development to better your life, Wes built a vaccine bot to help him find vaccines. So we're gonna be talking all about strategy and really just fun practical web development hacking kind of stuff. My name is Scott Lewinsky. I'm a developer from Denver, Colorado, and with me as always is the West boss. Hey, everybody.
Scott Tolinski
Hey, Wes. This episode is sponsored by 2 excellent companies. We have Sanity and Sentry.
Scott Tolinski
Wes, do you wanna take a quick second to talk about Sanity, and I will talk about Sentry? Yeah. Sanity, available at Sanity dot I o, is a structured content CMS.
Wes Bos
They are the unified content platform that powers better digital experiences. What that means is they provide a wicked set The APIs, a platform, a CMS editing UI for your website. And you can go in and you create your Content data types you create all via code. You can check all that into your your git repo. You can run it all locally, which is really, really nice. You can make your own custom React components for it. And then out the other end, you can spit out either a GraphQL API. They also have this really cool query language called Grok, Which I really appreciate that they they make it like a standard, and they open source all of that, which is super cool. It's just a really all around Good platform both from a developer as well as from a end user point of view. I always say it's like the perfect balance of It being done for you, like, it just works out of the box. You can get going as well as if you do need to go super deep and customize it and build your own inputs, you totally can. Check it out. Sanity.i0forward/ syntax.
Wes Bos
Double the free usage tier on that URL. Thanks so much to sanity for sponsoring.
Scott Tolinski
This episode is also sponsored by Century at century.io.
Scott Tolinski
Century is the error and exception handling tool that will Take you to the next level by giving you performance of metrics for all of the routes on your page. Anytime users are hitting your page, locking those, and giving you a user misery score Or just to tell you just how much users are enjoying the page load time of your site or perhaps not enjoying the page load time of your site, Which is an important metric to have. It also is a great place to keep track and log all of your errors and exceptions, view them, attach them to GitHub issues to see who they're Affecting how many people they're affecting and when they were introduced.
Wes built vaccine availability checker bot
Scott Tolinski
All of that and more at century.i0.
Scott Tolinski
Use the coupon code tasty treat, all lowercase, all one word, and you will get 2 months For free. Thank you so much for Century for sponsoring.
Scott Tolinski
Okay. Wes, these are, these are fascinating episodes for me because this is, like, kind of your bread and butter. You you What you do, whether it's bikes or vaccines or power wheels or just anything, if you have a problem, You turn to your JavaScript coding, and you make it happen. I I'm so into this. So you created a vaccine bot, which From my understand, I saw this on your Instagram stories. Was this thing, like, like, talking to you, this vaccine bot?
Wes Bos
Oh, no. Well, It kind of. So I I I built the, like, the public face of the vaccine bot to be a Telegram chat Okay. So that, like, Friends and family could join it and whatnot, and I invited my wife to it. And she's like, hi, Vaxi.
Wes Bos
And I was just sending messages as the vaccine bought via the API, and it was it It was kinda funny. Anyways That's very funny. That's very cute. This was kind of a a fun project to do, because, like, here in in Canada, We are not nearly as close to the US with, the rollout of the vaccines.
Wes Bos
And, also, it's been a bit of a mess in terms of how it's been rolled out. You can like, there's provincially. You can get them you can get them at pharmacies. You can get them at your local public health. There's pop ups. There's hot spots. There's It's insane. And just the inefficiencies between all of this mess was really, really frustrating. So let me say off the top that I felt that this was okay because I wasn't taking a vaccine from people who needed it most.
Wes Bos
They were given out to 40 plus hotspots, Racialized minorities, frontline workers, literally everybody but the young, healthy white males who can work from home. And as of couple days ago, it opened up to my age group. So almost everybody who was, in a sort of compromised spot got their own, and then it opened up to Pretty much everybody they open it up to now in this area. Everybody else can get on in.
Wes justified taking vaccine appointment
Wes Bos
Now comes the, like, the stampede of just trying to find a spot Via one of these methods where you can get a booking in and go ahead and get your vaccine. So I wrote this little bot that would hit, And I in my case, I only had to choose 3 different chains. Shoppers Drug Mart, which is like our our Walgreens or CVS, Costco Mhmm. Which has pharmacies, and the third one was Walmart, which also has pharmacies here in Canada. And all of them had websites where you could check availability of a vaccine, and they were updated frequently via the website. Just the process of Checking them was was kind of slow, and you there was, like, people who would spend their entire day calling or checking the websites, and they would get one. And And then there'd be people that have, like, a job to do, and they would be like, oh, yeah. I I still haven't been able to get one. Or, yeah, I did get one, and it's it's a month from now. And I found that really Trading that there was these inefficiencies.
Wes reverse engineered pharmacy vaccine APIs
Wes Bos
So what I did is I built a little bot that every 5 minutes would Fetch the data from these 3 websites, and I'm gonna tell you sorta, like, how I approach it because people seem to be pretty interested in, Like, how did you do it? Like, what is the process of figuring out where the data is? I don't see like, a lot of people thought that there was just some sort of vaccine API out there, And there's not. You have to reverse engineer how the websites are pulling their data, and then you have to figure out how you can Look like a person visiting the website and then pull that data yourself and and whatnot. That's one thing I think is gonna be important for people to
Scott Tolinski
Understand about a lot of these projects that you're doing like this are primarily involved around you just Spying on network requests and then kind of reverse engineering the APIs that don't necessarily exist publicly, Which is fascinating because you you've done this several times in different ways, I mean, even for your own Yeah. Website with the Instagram feed. So this seems to be like a skill that you end up
Wes Bos
We're really utilizing over and over again. Yeah. It's true. I like, I feel like I've gotten pretty good at being able to I I think it's because, like, I'm also, like, a back end developer, and I understand how the developers would have implemented their APIs. Mhmm. And then you just go through the steps of testing things and and looking at the network requests. So that's pretty much the the first step. So the first step is that you visit a website. I'll use Sharper's trademark because that was by far the simplest one. You would just visit the website, and you type in your postal code with the network tab open, And then you would see a request off to an API, and it would come back with, some JSON. And then in that JSON, it would have the store, the address.
Wes Bos
And then in there, there was a little s. It was it was actually just for using the flu shot variable. So it says, is flu shot available? And and that's the one that I figured out was They were using for the vaccine because they were displaying it on their page with that variable. Mhmm. Once you found out what that URL is, then you got to Take that URL and try to replicate that request yourself. And if you open up the Chrome DevTools, you can right click on that request And say copy as, and there's a couple options there. There's curl, which you can paste into the command line. There is Fetch. And now I I recently learned there's 1 in Chrome called fetch Node JS fetch, which is what the what you want because The Node. Js fetch will also give you all of the cookies and session IDs and headers and anything that came along with the request. It will also give you those. The normal fetch request doesn't send cookies a lot along because it assumes that you're firing it off from the browser. But If you're sending this off from a server in Node. Js, then you need to manually send the cookies along. And it's really easy to send cookies along in a fetch request with Node.
Wes Bos
F. Simply just a header with cookies, and then you concatenate all the cookies together with the semicolon.
Scott Tolinski
Yeah. So to clarify, that's just a, A property in the fetch call in your options has headers, or is it just header or headers? I don't know my Headers. There's, like, a second
Wes Bos
Argument to your fetch request, which is an options object. Mhmm. And inside of that, you often have to set the method to get or post or or put or delete.
Wes Bos
And then you also need to set any any custom headers because sometimes cookies or JWTs don't come along as cookies. They they go along as just like custom headers like x dash. You'll often see them. Yep. And I had to do that a couple times as well. A lot of people would probably ask, like, why don't you use puppeteer for this? And whenever I approach one of these things, I will always try and replicate it with just a vanilla fetch request first and almost always it can be done with a fetch request. If it can't be done because of whatever reasons, like, you need to literally emulate Clicking on buttons and hovering over things and and clicking next, next, next a couple times. Mhmm. If you have to literally do that, Then that's a good case for Puppeteer. And what Puppeteer will do is it will actually fire up a headless Chrome window for you and load the website and wait for things to load. And there's a really, really nice library in Puppeteer for doing that type of stuff. The only thing is that it's so much slower when you're doing development because you gotta wait for the browser to open. You gotta wait for the page to load, And then it loads the JavaScript, and then it fetches the request, and then it comes back. And then you gotta click the next button 3 times. And if you can just Bypass all of that by getting the the raw JSON URL. Your development time is much faster, and you don't have to worry about Where can I host this thing that also has Puppeteer installed? Mhmm. Then once you have the URL of the the thing, then you move into what I call variablizing it. So you look at the URL and you figure out what parts of this request are variables. So, Generally, this in my case, there was a pharmacy ID. There was a booking form ID. There's a vaccine ID. Mhmm. And you you just, like, take those out, and you put them all into variables. Because, Usually, store by store, that will differ or province by province or city by city. It depends on, like, what you're doing. But, basically, say, like, which part of this is a variable that's being passed in? And then bringing those out into their own variables allows allows you to loop over multiple stores and and send off that Quest. Where are you gonna get the list of stores from now? Does that 2 come later? Am I jumping the gun? No. That no. That's a great idea. Great question. So, Again, it depends.
Wes fetched vaccine data and handled cookies
Wes Bos
In my case, for Walmart, there's only 3 Walmarts within a half an hour drive of me. So All I did was I just clicked on h 3 Walmarts.
Wes found pharmacy IDs to check
Wes Bos
I looked at the dev tools, and then you saw the idea of each Walmart. Mhmm. For shoppers, there's probably A 100 pharmacies within a 1 hour drive for me. So in that case, luckily, the store IDs came from the JSON API, But then the last one, which was Costco, I had to find another API endpoint.
Wes Bos
Basically, you just you kinda sniff around. You click on, like, search for locations or something like that, and then you find another API endpoint That will get a list of stores, and sometimes you can pass a latitude and longitude. You can pass a radius, and you say, give me all the stores within this area, which was nice because the Telegram group started to get a little bit popular, and people that were from a little bit further out We're like, hey. Could you also include my city in this? And I was able to just change a couple of variables and make the scope of it a little bit larger.
Wes Bos
Once it's all variabilized, you gotta figure out if there's any, like, restrictions.
Wes Bos
So often, these API endpoints, they're just wide open. You can you can ping them all day. You can visit the URL your browser, it will load JSON, but sometimes they are protected because they don't want people doing what it is that I'm doing. So you gotta figure out, like, what is it in that request that is needed for f. To go through. So if you copy at the whole request as a Node. Js, you'll see all the cookies, all the headers. And, generally, what I'll do is I'll start deleting stuff and write rerunning it. And then at a certain point, you're gonna find out, okay, they require this one thing in order for it to work, and the rest of this is just all garbage. You can delete it all. In the case for Walmart, it was a 3 step booking process.
Wes handled multi-step token authentication
Wes Bos
And before you could check if there's a vaccine, you had to answer a bunch of questions And then choose your location and then send off the request. And it was 3 steps. And every step along the way, They gave you a new cookie and a new cross site or request forgery token.
Wes Bos
So what I had to do is I had to, like, send yes yes to these questions, and then what came back was the HTML page.
Wes Bos
And then on the HTML page, you had add a run of regex That would give me the token. And then you take that token, you make the next request with it, and that returns an HTML page. You take the token from that. And then the token from that, you send your final request. So, basically, you have to hot potato the tokens from one to another, and that's Significantly more difficult to figure those things out because there's so many moving parts.
Wes Bos
What I ended up doing for that was I probably spent 3 or 4 hours trying to re replicate the steps of requesting these tokens.
Wes Bos
And I had it working, and then it stopped working. And but that's The the nature of this type of thing is that this is not a solid API, so it can change at any at any time. So what I ended up doing is I found out you can just Do those steps in the browser, copy the cookie out of the dev tools, and that cookie was good for 24 hours. So I just, Every day, I just went in and copy pasted the tote the cookie in and out. So Oh, wow. That was a bit of a manual manual fix for that, but sometimes that is the fix For for each of them, totally. I had to cache them. So once something was available, this thing was running every 5 minutes, and it was Possible that a vaccine was available for more than 5 minutes because, like, if a pharmacist puts up vaccines on the website And then they go to the bathroom. Then 5 minutes later, they're still gonna they're still gonna be available. So I had to, like, cache them, and I just chose An array variable.
Wes Bos
Every single time there was, like, a hit on a vaccine, I stuck it into an array with a time stamp on it. And then Before I alerted of of a vaccine available, I would check if that alert had been sent in the last 24 hours, and that Stop any sort of duplicate
Wes cached vaccine availability hits
Scott Tolinski
false positives from going. Are you storing anything in the database here, or is this all being done through Telegram?
Wes Bos
Nothing's being stored. The only thing that's being stored is the the notifications, and that's just in a variable. If I restarted the app, Then that that array is gone, and sometimes you would get duplicates.
Wes stored vaccine hits in memory only
Scott Tolinski
So it's just being stored in in memory. Interesting. And, like, if I was doing this thing
Wes Bos
For a little bit more flexible, like, this code will probably be unnecessary in 4 days from now Yeah. Which is great. Like, I'm super stoked for this project to be Obsolete.
Wes Bos
This is a pop up project right here. You pop it up. Exactly. Yeah. Yeah. Pop up project. I like that. If I was doing that, I would Reach for SQLite, or there's a couple other database that are just, like, text files.
Wes Bos
And if you're Just running it on, like, a Linode or DigitalOcean server, then you can use those things because they they write to the file system, and there's no external database required. Cool. Yeah. Oh, finally, I used Node cron to rerun the function every every 5 minutes. And then I when there was a hit, I used Telegram, which I've never used Telegram before, but I was, like, looking. I was like, what's, like, a good chat software that has dead simple API? And that was Telegram after doing a little bit of research. And Telegram is like one of these it's like WhatsApp. You know? Mhmm. Like these chat rooms. Anyone can join. They have a nice invite, and then they have a whole bot API.
Wes used Telegram bot API for notifications
Wes Bos
And it was maybe, like like, 11 lines of code to actually write the bot API. And then the body API would just dump the results of the vaccine into the chat with, either a phone number or a link To book, and then, like, I had this thing running for 20 hours, and it was running, running, running. And I was at a point where I was like, I don't even know if this thing is working. And then all of a sudden, one popped up. I tapped call within a minute, and I was like, hey. Do you have I saw you put some vaccines up. And she's like, oh, yeah. Oh, Yeah. Okay. And then I booked it. And then, like, a couple days later, I got my shot. I I got one for my wife as well. So, like, I felt I was like, I really hope that I actually get one via this box. I spent, like, a day coding this thing.
Wes Bos
So I did, and and now it's at a point where, Oh, like, friends and family and friends of friends of friends are are all in the chat room sorta just waiting for new ones to pop up, and they pounce on them when that happens. Man,
Scott Tolinski
that's awesome. Whether it is tracking bicycles or any of this stuff, what we did at our household is once again, I feel like This is our answer to your programming methods. It's just Courtney relentlessly hitting websites and refresh them repeatedly until we can get backseeds.
Wes booked vaccine via bot
Wes Bos
Man, congrats, though. Congrats on finding 1 from this. Thank you. Honestly, I probably could have got one faster by just Dialing every single pharmacy all day long.
Wes Bos
But, like, where's the fun in in that type of thing? Right? Yeah. And I think sometimes people People don't realize my personality type with a lot of these things because they're like there's so there's a Twitter account called vaccine hunters, and it's funny because I I went to University is one of my good friends in university.
Scott Tolinski
He's running it for all of Canada. Oh, really? Because I I was on the I was listening to a podcast, And they had somebody who was involved in that on the podcast, a non tech podcast, a hockey podcast, by the way. Oh.
Wes Bos
Yeah. It might have been him. We Yeah. We are always coding Twitter bots and whatnot in university.
Wes Bos
And when it popped up, like, this thing has, like, a quarter 1000000 followers. I was like, I'm not surprised that that was him.
Wes Bos
Anyway, so he was like people are like, just follow that Twitter account, and, like, that's all you have to do. And then I was like, well, then, Like, that's putting me on the same plane as everybody else. You know? Like, I've gotta go 1 step before that or, also, like, this is fun for me. You know? Like, I get we get to talk about it on syntax. I get to write some code. I gotta learn a whole bunch of stuff about fetch requests. So, like, this is just my personality Where I wanna figure out how it's done.
Scott Tolinski
This is fun for me. Okay? Yeah.
Scott Tolinski
I I totally get that, though. I will I will go very roundabout ways just to do something, that gets to use my specific set of skills.
Wes Bos
I'm, Learning how to propagate hydrangea plants right now, which is, like, take 1 hydrangea and, like, duplicate them into many, many plants.
Wes Bos
And the amount of people that told me you could just buy them,
Scott Tolinski
and I was like, I know I can buy them. Yeah. Right. I know I can buy them, but I I wanna figure this out. But how many more could you get if you propagate all of them? Yeah. You know, I'm a really like snake plants. I'm a more I like landscaping. You you seen you seen my yard. I do I do some landscaping. But Looks great. Yeah. I do, I have a lot of house plants too. And I have snake plants, which are notoriously hard to kill, and yet somehow I managed to kill all of mine, which you know, I'm not good at plants. I'm just not good at Stink plants for some reason, I over love them. And, stink plants are supposed to be really easy to propagate, and I've tried Just about a 100 times to propagate them. I follow all the steps. I've watched all the YouTube videos, and I cannot get it to work. So I really hope your hydrangeas come through. I saw you were doing some propagation. I was just like, oh, man. This is how many failed propagations I've done? I should just call it a day, but,
Wes Bos
keep keep going at it. It's kinda interesting. Like, I I never thought I would be into plants, but I went down this rabbit hole. And then I also found out, you know those, like, Monstera plants that everyone's going crazy for right now? No.
Wes Bos
Though they're like these, like, huge, big leaf House plants that people have. Like, you know, you sometimes drive by someone's house, and it looks like there's a jungle in the front window. Yeah. Apparently, like, a leaf, One leaf from these monstera houseplants is going for a $150.
Wes Bos
What? And people are just using that to propagate it. Yeah. They're they're super popular right now. Okay. I've seen these. Yeah. Is this the new fiddle leaf fig? Because that was for a little while, the the one. I think so. I don't I'm not really up on houseplants. I'm sure there's a couple people listening that are like, Wes and Scott, let me tell you about houseplants,
Scott Tolinski
But I was just amazed. Oh, man. I'm up on houseplants. This I don't have one of these very, very cute plant, though. You gotta get a monstera. Apparently, they get huge.
Wes Bos
I think I wanna try it, especially if you're making a $150 a leaf. Come on.
Scott Tolinski
Start slaying leaves.
Wes Bos
Slaying leaves.
Wes Bos
Wes Bos, leaf mogul. 2 months from now, how I use JavaScript to automate a watering of my monstera farm. I know. I actually really wanna get into automating my watering and stuff. That would be really, really cool. I, ever since you talked about the wise sprinkler automation Yeah. Sprinkering. It's just been rolling around in my head about doing that to to our place, so I think I might go down that route. That's easy.
Scott Tolinski
Easy peasy.
Wes Bos
Sweet. Alright. That's it for today. Thanks so much for tuning in. Hopefully, you learned a thing or 2. And, oh, the, oh, the code for this entire Everything that I wrote is on my GitHub.
Wes Bos
It's not the best code I've ever written, but, like, that's what you do in a Health crisis. You sling together stuff.
Scott Tolinski
Also, we don't talk about how important it is enough to read code.
Scott Tolinski
So if you are at all interested in reverse engineering APIs or hacking together something like this or even schedulers or Telegram bots or anything, Go look at the code. It will make you a better developer. Even if Wes says it's not his best code, it's still gonna make you a better developer reading some code. So if you've heard all this, You kinda find some interest in it. Go read that code. That is an important skill to practice.
Scott Tolinski
Yeah. I totally agree. Sick. Cool. Well, we will catch you On Wednesday for the next Syntax. Peace. Peace.
Scott Tolinski
Head on over to Syntax dot f m for a Full archive of all of our shows. And don't forget to subscribe in your podcast player or drop a review if you like this show.