Making a Discord Vaccine Bot
Tags: java, discord, bot, vaccine
Published: 2021-02-19 13:58:44

I recently made [a Discord bot](https://github.com/williambl/vaccine-bot) that tracks the UK vaccine rollout, using Java, [JDA](https://github.com/DV8FromTheWorld/JDA), and the [coronavirus.data.gov.uk](https://coronavirus.data.gov.uk/) API.

### First Ideas

I'd been browsing the excellent [UK Coronavirus dashboard](https://coronavirus.data.gov.uk), and I saw the '[developers' guide](https://coronavirus.data.gov.uk/details/developers-guide)' link.

I gave it a quick look over, saw that it didn't require registering for an API key or anything, and had an idea: make a Discord bot to spread vaccine positivity in my group chats :)

### JDA and Java

I've done work on Discord bots for communities using JDA before, so I knew I'd use that for this project just because I had familiarity with it.

Regarding language, I had the option to either use Java or Kotlin - I went with Java just because it tends to be quicker for Gradle to set up a Java project (not having to download the latest Kotlin stdlib), but I do much prefer Kotlin and for most purposes will use that.

### First attempts

My first attempt was very basic, and amounted to something similar to this:

```java
private static final String API_URL = "[...]";
private static final Timer TIMER = new Timer();

private static JDA bot;

public static void main(String[] args) {
    try {
        bot = JDABuilder.createDefault(args[0])
                .setActivity(Activity.watching("the vaccine rollout"))
                .build();

        TIMER.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                checkStats(bot, args[1]);
            }
        }, 2000, 1000 * 60 * 60 * 24);

    } catch (LoginException e) { [...] }
}

private static void checkStats(JDA bot, String channelId) {
    long amount;
    try {
        amount = JsonParser.parseReader(new InputStreamReader(new GZIPInputStream(new URL(API_URL).openStream()))).getAsJsonObject().getAsJsonArray("data").get(0).getAsJsonObject().get("value").getAsLong();
    } catch (IOException e) { [...] }

    channel.sendMessage(":tada: **Good news!**\nThere have now been "+amount+" vaccinations in the UK!").queue();
}
```

This worked, but was a bit barebones.

It does three things:
 - sets up a bot with JDA, with the token given from the first command-line argument (`JDABuilder.createDefault(args[0])`)
 - sets the bot's activity as "watching the vaccine rollout" (`setActivity(Activity.watching("the vaccine rollout"))`)
 - sets a timer, which every 24 hours (`1000 * 60 * 60 * 24` milliseconds) checks the vaccination count and sends a message to a channel as given in the second argument (`checkStats` function)

I took me an hour or so to get to this point. Most of the time was spent trying to work out why the input I was receiving was garbled.

Because I hadn't read this: ![All API responses are compressed using GZip. The request client must therefore accept GZip encoded content.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3151s8vgh134sbheu4xf.png)


RTFM, folks.

One `GZIPInputStream` later, everything was working! But what else could I do?

### Extra features

The next thing I did was percentage calculation, just done by dividing by `680000` (roughly 0.01 times the UK population). There were decimal place mishaps at first:

![vaccine bot reporting first as '1%', then '154%', then finally the correct '15%', to reactions of "that's not right", "that's definitely not right", "154%? seems legit to me", and finally "that's better"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3qkrlnz6wesfvmcc3on1.png)

But it eventually worked well.

I later added the count as words, which someone said they could parse more easily than the numerals:

> There have now been 10971047 (that's ten million nine hundred seventy-one thousand forty-seven) vaccinations in the UK! That's 16% of the population!

I used a library called '[tradukisto](https://github.com/allegro/tradukisto)' to do the work for me. It also supports other languages than English, which is cool.

I also later added a command, `,vaccinebot`, to get an immediate count:
![the bot being triggered by the ',vaccinebot' command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl7z8lvv4nxl7grzn4b3.png)

### Conclusion

This was a fun quick project, and it's had an uplifting impact on my friends: ![people saying 'past the 12 million mark!!' and 'my mum is part of that number :)' as a response to Vaccine Bot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6wjxkg2dfdmern27skqd.png)

If anyone else wants to run an instance of it, [the code is available](https://github.com/williambl/vaccine-bot).

I'm grateful that Public Health England have made the COVID data available via an accessible and documented API, and that the [COVID dashboard website](https://coronavirus.data.gov.uk/) exists.