Skip to content

Instantly share code, notes, and snippets.

@evandcoleman
Last active March 26, 2021 20:34
Show Gist options
  • Save evandcoleman/2c0e4647cdb2f6fff32a55f282e236a5 to your computer and use it in GitHub Desktop.
Save evandcoleman/2c0e4647cdb2f6fff32a55f282e236a5 to your computer and use it in GitHub Desktop.
A simple Twitter bot that post NYC COVID vaccine availability
const fetch = require('node-fetch');
const Twit = require('twit');
let lastNotifiedLocations = [];
const T = new Twit({
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
access_token: process.env.TWITTER_ACCESS_TOKEN,
access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
});
async function getAppointments() {
const response = await fetch("https://services1.arcgis.com/oOUgp466Coyjcu6V/arcgis/rest/services/VaccineFinder_Production_View/FeatureServer/0/query?f=json&cacheHint=true&orderByFields&outFields=*&outSR=4326&spatialRel=esriSpatialRelIntersects&where=1%3D1");
const { features } = await response.json();
const appoints = features
.filter(x => x.attributes.AppointmentAvailability === 'Available');
const filtered = appoints
.filter(x => lastNotifiedLocations.indexOf(x.attributes.OBJECTID) === -1);
lastNotifiedLocations = appoints.map(x => x.attributes.OBJECTID);
return filtered;
}
async function postToTwitter(appointments) {
for (let { attributes } of appointments) {
const { FacilityName, Address, Address2, Borough, Zipcode, Website, ServiceType_Pfizer, ServiceType_Moderna, ServiceType_JohnsonAndJohnson } = attributes;
const brand = ServiceType_Moderna === "Yes" ? 'Moderna' : (ServiceType_Pfizer === "Yes" ? 'Pfizer' : (ServiceType_JohnsonAndJohnson === "Yes" ? 'J&J' : null));
await T.post('statuses/update', {
status: `Vaccine appointments are available at\n\n${FacilityName}${brand ? ` (${brand})` : ''}\n${Address}${Address2?.length > 0 ? `, ${Address2}` : ''}, ${Borough}, NY, ${Zipcode}\n\n${Website}`,
});
}
}
async function run() {
const appointments = await getAppointments();
console.log('[INFO]', `Found appointments at ${appointments.length} locations.`);
if (appointments.length === 0) return;
await postToTwitter(appointments);
}
try {
(async () => {
console.log('💉 vaccine-bot is running!');
setInterval(async () => {
await run();
}, 300000);
await run();
})();
} catch (error) {
console.log(error);
}
version: "3"
services:
vaccine-bot:
build:
context: .
dockerfile: Dockerfile
environment:
- TWITTER_CONSUMER_KEY=
- TWITTER_CONSUMER_SECRET=
- TWITTER_ACCESS_TOKEN=
- TWITTER_ACCESS_TOKEN_SECRET=
FROM node:14
WORKDIR /usr/src/app
COPY package*.json ./
ENV NODE_ENV production
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD [ "node", "app.js" ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment