ilotterytea

@teabot, the only C++ chatbot

If you don’t know what is Project Tinybot (or @teabot), that’s an IRC (with Twitch support) bot for chat rooms. More info…

Reading the source code of chatbots, you might have noticed that all of them use simple, high-level programming languages such as Python, Java, Go.

but what does @teabot use?

OF COURSE, C++!!! The most popular choice for these kind of tasks. You don’t believe me? Well, according to Github, there are at least 2.5k+ projects with twitch, chat and bot tags, but what if we add lang:c++ tag? You will get 20+ projects last updated 5-10 years ago GEEG That says a lot of my ability of choosing languages wisely…

anyways, this can’t be that bad, right?

Everyone knows that C++ applications are more lightweight and faster than GC-based languages. Yes, this fact was enough for me! At that time, the only VPS I had was very slow. It had 1GB RAM and only 1 virtual CPU core. Printing “Java” or “Python” to the console could make my server tremble with FEAR. Database + Linux + other systemd stuff could eat a lot of the RAM and leave me the scraps in the form of 100MB. The only choice here was C++ or Rust.

why not Go?

That’s the most boring ass language (Goroutines is the only thing that saved this PL) ever created and it was created by Google. That’s two red flags. The last is the brightest. Do you really think I should choose it?

why not Rust?

I knew Rust before C++ and the classes of the latter had only started in my schedule. I needed a project as a way to learn the language and @teabot was the project. The first fully working version was made in 2 weeks. It was written in C++17 and was using ixwebsocket for connections. All commands were .cpp files stored in a folder and had to be re-compiled every time on changes.

work, work, work, work, work, work, work

Even though my C++ classes ended 2 years ago, Project Tinybot was still getting updates. Last year, @teabot got Lua interpreter under the hood! Eventually, all commands were rewritten in Lua and users are allowed to run their own scripts. Debugging and creating new commands became so easy as never before! Re-compilation is not a problem. You have only to restart the bot to reload the script (There could be live-reloading tho).

However, there is still a problem in this project: it’s written in C++. Adding new features or API might be extreme demon difficulty in some cases.

Therefore, the research was started. I created bot prototypes in high-level languages mentioned before. The conclusion is… the project should stay in this state. I couldn’t find a perfect library the same as sol2 in any of those languages. Most of them were just C wrappers without sugar such as defining functions. Rust has the better library than sol2 called mlua. It supports luau, a sandboxed Lua interpreter used in Roblox. Execution limits can be set in this library which is mandatory for user-created scripts.

Althrough, I love Rust much more than C++ but this would add new problems to the project. As you know, Rust compilation folder target can be 20x larger than C++ build folder. Yes, this resolves problems with linking because every program is statically linked and doesn’t require libraries installed on the system as C++ do, but I don’t have a fucking datacenter for Rust builds. And yes, I sometimes suffer from compiling C++ projects. Computers might not have needed library and it becomes a quest searching the correct name and version of the library.

The reason I didn’t pick Rust as the language is asynchronous programming. IT IS PAIN THERE! I couldn’t remember any example but that’s for good! On the other hand, C++ is chill. Do you want to create a thread? Just create std::thread and call .join().

Coming back to that research, the decision was to rewrite fully the project. I broke @teabot down into several parts making a typical micro-service architecture. I created scriptvm for Lua scripts and singlebot for bot execution. Both of the modules are sharing core library, just a set of default bot functions and classes. For IPC, I chose rpclib which uses RPC with MsgPack.

For events, there was almost the same story. I created various event daemon prototypes in Go & Java, and even in C++. The architecture was the same as Twitch’s EventSub: bot receives events via WebSocket connections and creating events by sending requests to POST /create. I learned NATS a bit, a Pub/Sub system, but never used in practice. As deadlines came closer, I found the easiest way. I forked RSS-Bridge and created bridges for events the bot needed. @teabot already used RSS-Bridge for Telegram and Twitter events so it wasn’t a big deal to implement that. You can use my RSS-bridge fork here!

what we learned from the story?

Don’t repeat my mistakes, choose the language wisely and just write in Python unless you’re a masochist :)

This project will stay in C++ forever and my suffer will continue until I abandon it[two more years of suffering yippeeee]. The research showed that C++ has the best library for Lua, good asynchronous features (for my usecase) and the worst build system.

I like C++. It’s really like a Tsundere, it wishes you to kys spitting out the most incomprehensible error messages which God won’t understand, and loves you giving the freedom no language has.

Maybe I have the Stockholm Syndrome for C++, but nevermind…