Pubbot is a discord bot written in NodeJS that started as a virtual bartender. As, due to Covid-19, me and my friends moved from irl pub meets to virtual pub meets, pubbot started as a joke to enhance the ‘Discord pub’ experience. Fairly quickly however, it spiralled out of control, with feature after feature being added for no reason other than, why not?
- Serves drinks
- Makes jokes
- Gives you a bank balance
- Has a internet banking service
- Can impersonate you with Markov chains
- Has a third party API for other bots to use
- Has a granular permission system to avoid account fraud
- Has an achievement system that’s partly autonomous
For a detailed walkthrough, including how it actually does what it does see the blog posts listed at the end (Coming soon!)
Feature Overview, in order implemented
Pubbot listens to every message on our Discord server, and if it thinks someone is asking for a drink, it responds with the correct image. It also monitors for responses such as ‘thank you’.
Pubbot can also determine if you’re asking for more than one. It also keeps track of who orders what…
Pubbot remembers who ordered what, and can output a leaderboard. This has to be split into multiple messages to avoid hitting character limits set by Discord.
Every group of friends has a their share of ‘in’ jokes that don’t really make sense to anyone else. Pubbot picks up on keywords and responds with some of these in jokes.
Jeffcoin - A not-a-cryptocurrency
This is where the features start to get a little more complex. Jeffcoin is a parody cryptocurrency I implemented, which gives users a bank balance, as well as the ability to send and receive ‘Jeffcoin’ to other users. This feature in particular became the foundation of a lot of other work. Jeffcoin was initially controlled soely through Discord commands, each starting with £. More on that in a moment.
Transfers can also be ‘requested’, meaning a user can request an amount from another user, and pubbot will handling permissions and notification:
This feature was initally useless, in so far as users could transfer money too and from eachother, but there was no way to gain more Jeffcoin without getting someone to give it to you. This leads nicely into the next feature…
I added an achievement system to pubbot, which included public announcements, Jeffcoin rewards, and dynamically rendered png toast notifications. The achievement implementation is something I’m quite proud of, as the end result works really well. All achievements are defined in a JSON file, and the award images dynamically rendered based on the contents using the nodeJS library ‘jimp’.
Some of the achievements need to be awarded manually, either through secret commands or a admin dashboard I made. Other achievements such as ones that are awarded for measurable statistics (Total Jeffcoin received, sending X number of messages etc) are awarded automatically when the user meets the criteria.
A snippet of the JSON file which defines the achievements
The external API
Okay, so up until this point, pubbot had been mostly self contained. I’d decided however that in order to make the most of the Jeffcoin ‘not a cryptocurrency’ feature, pubbot needed to support third parties. This would allow other discord bots to raise transfer requests for payments to them, and instantly make payments to other users.
Because of the asynchronous nature of transaction requests, an express server is used by both pubbot and the third party bot. This is necessary as the time it takes a user to confirm a payment could be hours - far too long to hold a TCP session open waiting for a response. I’ll go into more detail about how this all actually works in blog posts.
To make it easier for future me, I then wrote a ‘pubbot library’ in nodeJS that would make it super simple to send and receive payments via pubbot in other apps. You just specify the accounts, amount, a message, and then a callback for success and a callback for failure. It works really well and is quite a clean solution.
The first bot I wrote to use this library was Joan - a turnip bot based on the game Animal Crossing. This bot allows users to play a fake stock market with their Jeffcoin, potentially making profit every week. For the project overview of Joan, and a link to the blog posts - See here. ADDLINK
Now I had people actually using their Jeffcoin - It became a race to make the most profit. Once again this inspired me to add yet another feature, and the most complex so far.
Jeffcoin.online is a live website where users can log in via Pubbot (not via Discord, which would work differently) and view their Jeffcoin balance, transaction history, and outstanding transfer requests. It also features a bunch of fake adverts because why not.
Because of the complexity of this part, I’ll be writing it up as it’s own project and blog posts (Coming soon), but here’s a brief overview:
If you visit https://jeffcoin.online you’ll see a landing page for the fictitious bank. If you press login, you’ll get to the login page.
Here the user must message pubbot ‘!login’ to get a code they can paste into the login box, or alternatively they can just click the generated URL. The code expires within 60 seconds, and works in a similar manor to OAuth2.0, and the ‘magic link’ approach that services like Slack or Monzo use.
Once logged in, the user can see their balance, recent transactions, and even confirm or deny transfer requests.
It all works, and the APIs are served from the same express server on pubbot that powers the intra-bot API. The login system is secure (enough), and users’ sessions are limited to 24 hours. This is one of the more interesting features of pubbot, and certainly one of the more fun ones.
Markov chain generation
After implementing Jeffcoin.online, I fancied a go at something a bit different. After opting in, pubbot stores everything you say in the discord server, and can use Markov chains to impersonate you. It works with varying degrees of success, but no matter how coherent the generated sentence is, it’s almost always entertaining.
It’s a very similar effect to mashing the predictive text button on an Android keyboard.
Instant payment API & Permissions system
Following the external intra-bot API I implemented, which worked well, I wanted to add an instant payment API. This would allow a third party bot to instantly take a Jeffcoin payment from the user’s account, which is more suited to working in an API workflow. No more waiting for the user to confirm.
However, because I like to fix problems I can see coming down the road, I didn’t want any third party bot that has API access to be able to take money from people, as such, I built a permissions system into the API, so users can authorise third party bots with a given scope.
This API was implemented as part of another bot I wrote called PixelPlace, which is a pixel-by-pixel drawing canvas that any discord user can draw on. Check it out here (Writeup coming soon)
That’s everything that pubbot comprises at the moment, though as more features are added I’ll update this project page.
Check out the project pages (and blog posts) on my other discord bots - Joan and Pixel Place (Writeup coming soon)