xtlbot: twitch moderation in Lua

A few weeks ago I promised a writeup of  xtlbot, which is a twitch moderation bot written in Lua. While it might not be as feature packed as NightBot or MooBot (for example, it has no web interface), it is open source. Even without modifying the core sourcecode, you can easily add new functionality through the use of plugins.

Features

  • Easy to use plugin api
  • Permission system
  • Easy to customize
  • Open source (MIT)

Setup

Setting up xtlbot is fairly easy. You first need to make sure you have luarocks + lua 5.1 installed. You can then run these commands to install all the dependencies:

luarocks install irc-engine
luarocks install lsqlite3
luarocks install luasocket
luarocks install luafilesystem

Next, you can run the configuration script:

lua configuration.lua

You might have to use lua5.1 in place of the lua command depending on your installation.

The configuration script will ask you for details about the user xtlbot should run as along with the name of the channel xtlbot should participate in. It will then ask for the name of the twitch user it should set as the first administrator. Finally, it will ask you which plugins it should enable initially. You’re ready to start xtlbot! Run this command:

lua xtlbot.lua

The bot will start listening to your channel. You can test it by running !ping to see if you get a response.

Creating Plugins

xtlbot’s core can’t do much by itself. The majority of functionality is provided through the use of plugins. Plugins that come with xtlbot include polls, raffles, a chat filter, timed announcements, custom commands, and a basic points system.

xtlbot’s plugin api is incredibly simple, making it really easy to write new plugins. For example, this is all it takes to send a message every 30 seconds:

local core = require("src.core")
local lang = require("src.lang")
local socket = require("socket")

local plugin = {}

local last_message_time = 0

local function message_loop()
    local currentTime = socket.gettime()
    if currentTime > last_message_time + 30 then
        core.send(lang.myplugin.message)
        last_message_time = currentTime
    end
end

function plugin.init()
    core.hook_loop(message_loop)
end

return plugin
local lang = {
  message = "Hello twitch!"
}

return lang

This also demonstrates the usage of the message system (lang) to make it easy for users of xtlbot to customize messages in the config files.

More complex plugins are also possible. xtlbot contains a few functions for plugins to hook into (for example, the hook_loop used above) and an sqlite3 database for storing data.

Adding a Command

Here’s a quick example of how to create a command:

local core = require("src.core")
local lang = require("src.lang")
local commands = require("src.commands")

local plugin = {}

local function cmd_hello(user, args)
    core.send_to_user(user.name, lang.mycommand.hello)
end

function plugin.init()
    commands.register("hello", "say hi", cmd_hello, nil) -- we use nil for the last argument to say everyone can use this command.
                                                         -- if you want to restrict the command, then put a string containing the
                                                         -- name of the permission in place of nil.
end

return plugin
local lang = {
  hello = "Hi there!"
}

return lang

Enabling Plugins

Something I neglected to mention was how to actually enable plugins. Other than just placing the plugin files in their corresponding directories, you need to also add the name of the plugin to the table in config/plugins.lua. Once you’ve done that, you can run xtlbot and it will have all the plugins you specified!

Are we there yet?

xtlbot works, and is pretty hard to crash or break (all commands and hooks throwing errors won’t crash the bot), but it hasn’t been tested on a large channel yet. Additionally, a single installation of xtlbot can only be run on a single channel at a time (running two instances from the same installation will cause issues with sqlite3).

Engines are fun

It’s been a while since I’ve posted anything. I’ve been really busy with schoolwork, plus an upcoming event that I’m helping to run on campus.

A few months ago I started working on a game engine in private. I never really got anywhere with it, but I did create a decent framework I could build on. In the past few weeks, I decided to pick it up again and actually get it to do something interesting.

Wake

The name of the engine is Wake, and it is still under heavily development. It is mostly meant as a learning experience for me, but I hope it will be of some use to others as well. It uses SFML for windowing and input and GLM for mathematics. Other libraries will be added in the future, especially ones for asset loading.

Wake’s architecture is fairly simple. It is made up of a few different manager classes (singletons), each of which deals with a subsystem of the engine. There’s the InputManager which handles input, GEngine which deals with the main loop and window management, the LogManager which handles logging, and the World which is, well, the game world.

Actors + Components

On the topic of the world, I took quite a bit of inspiration from Unreal Engine. I like their setup of Actors and Components. It seems to be a good compromise between the monolithic entity systems that can be found in Source engine and the everything is a component mentality of Unity.

If you don’t know what the actor/component system is, I’ll explain it. Actors take the place of monolithic entities. They are anything that can be placed in the world, and they can have their own logic. Everything you see in the world has to have an actor associated with it. Components are reusable classes that can be held by actors.

I’ll be posting more about Wake as I work on it. For now, go take a look at the repository on github!

Short update on Haunt

Hey there! I just wanted to post a quick update on Haunt. When I started the project, I hadn’t really looked at much of the horror genre in gaming. Now, however, I’ve been looking more and more at the genre and I’ve decided I want to go in a bit more of a unique direction with Haunt. Procedurally generated horror is great, but Haunt is hardly the first to go down this path. I want to be able to brand it with something unique, something to call it my own. I’m not going to say what my plans are at the moment, as I’m still working out details on where the project is going. What I’ve shown here will stay as it is, and the base concept of Haunt will stay the same. The flow of the game, however, is very likely to change. Sorry if I’m being cryptic, but I really want to try to keep things under wraps for now.

I have one other thing to add, which is that I will likely have a few people helping me with assets over the next few weeks. I’m really excited about this, especially since I’m hardly an artist. This hasn’t been finalized yet, but things are looking pretty good at the moment.

That’s all for now. Thanks for reading!

-Sam