SciOlyID
June 2019 – Ongoing Live on the web
SciOlyID is a group of Discord bots and associated services dedicated to helping students practice specimen identification for Science Olympiad events. What started out as a small summer project helping a friend has quickly grown to be used by thousands of students across the country, and even a partnership with the 2022 National Science Olympiad Tournament!
This project is by far my biggest and longest-running (4+ years!), both in terms of users reached and complexity. This also means I’ve learned a ton along the way, from web design to copy writing to DevOps to systems administration to bot developing. I’ve grown a lot since the start of this project, and I can’t wait to see what’s next!
Scope
SciOlyID consists of four active Discord bots (with one more out of rotation) and a website for those who don’t want to use Discord. Internally, there are a few APIs communicating with the frontend, with APIs and bots hosted on a VPS, with build systems deploying the application from GitHub.
All the code is fully open source, and a full list of GitHub repos is available on the SciOlyID website.
Bots
Bird-ID is a Discord bot I created along with another student to help competitors study for the Ornithology Science Olympiad event. The bot pulls images and songs from the Macaulay Library and supports all of the Macaulay library filters, custom bird lists, scoring, racing, and much more. This was the original bot that we started out with.
Based on Bird-ID, I later created Treebo (for the Forestry event), Fossil-ID (for the Fossils event), RFTS Bot (for the Reach for the Stars event), and Minerobo (for the Rocks and Minerals event). These later bots are created using sciolyid
, a Python package I made to consolidate code into one place. Each bot inherits the base code, with custom configuration that makes them unique. Since Bird-ID is slightly more complicated (with sound support being the main thing), it remains its own codebase.
Image Fetching
Birds have the appeal of being adorable, somewhat easily photographed, and also everywhere, so the Macaulay Library is a great resource with tons of images. Fossils, rocks, and stars aren’t so lucky. Since I couldn’t find any good image sources, images are contributed by users of the bot. To make this easier, I created a Flask-based API for sciolyid
that powers a web interface allowing images to be easily uploaded to the bots by users.
It turns out that this isn’t great for copyright reasons, so for Minerobo, I scraped sources for Creative Commons licensed images and used the API to have users validate the found images instead.
Treebo fetches images from iNaturalist, a crowdsourced dataset with a lot of images of various species. I also implemented a way of fetching the original observation from iNaturalist after the image is shown, allowing them to contribute back if they want, but without giving away any hints or answers.
Web Practice
Bird-ID has a Flask web API too, which interfaces with a website designed by another student that allows ID practice without the Discord client.
I later converted the Flask API to FastAPI and eventually rewrote the website to bring all the information and services into one place. The website rewrite was in preparation for partnering with the 2022 National Science Olympiad Tournament, hosted at Caltech.
Deployment
In the very very beginning, the single Discord bot we had was running on Repl.it, which we quickly realized wasn’t great for scalability. We decided to move to the Heroku free tier, but we eventually outgrew that too. It didn’t make sense to pay for Heroku, so I bought a cheap VPS from GalaxyGate, and everything has been living on that since.
Since I really liked the flow of Heroku (just push to GitHub and it deploys automatically), I wanted something similar for the VPS. That’s when I came across Dokku, which builds and deploys each service in its own Docker container. It also supports database services like Redis!
For deploying all these services, I created custom GitHub actions to push code to the server. We use Sentry for error monitoring and alerting, so there’s also an action for creating a new Sentry release.