Thursday, July 23, 2015


The Ghost of Leg_Bot sent me here! What's the deal?

Well, since ufokraana elected to abandon leg_bot, and as there was evidently a need for it, I, Anaerin, have elected to update and host the bot, under the new name "Ghost_of_Leg_Bot". It's database is the final snapshot that ufokraana posted, so all your statistics and the like should still be in place.

That's cool... What about the Web API?

Well, as there's a new host, there's a new URL. currently, the web interface can be found at - which, incidentally, is where the API can also be found for on-stream counters. The website there will be re-skinned (eventually), but for now it's a direct copy of the old site.
Update! The URL has been changed (and is reflected above). Old links will still work, however.

Isn't Leg_Bot open source?

I believe so. And I have had to make (more than) a few changes to it (to keep up-to-date with changes to the node.js library 'sequelize', as well as adding features detailed below). So I have done what any responsible open-source developer should do: Forked the repo, and am publishing my changes on GitHub.

So how are you hosting it?

The Ghost_of_Leg_Bot is currently residing on a Windows Azure Virtual machine. If you would like to donate towards it's continued upkeep, feel free to drop me a tip.

What new features are there? 

Yes, that's right, new features too!

Dynamic Counters

Counters are now dynamic - any mod can use the counter commands
  • !counter add <command> "<single>" "<plural>"
  • !counter remove <command>
to add and remove counters. Note, when a counter is removed, all the statistics logged for that counter are removed as well.
For example:

!counter add butt "butt" "butts"
!counter add warcrime "incident of friendly fire" "acts of incidental genocide"
!counter remove butt


The connection is now automatically set to keep alive, which should help with (some of) twitch's twitchiness.


The anti-spam system is now in place. If the bot is in your room, and set as mod, it'll do it's best to apply it's anti-spam rules. If anything matches, it'll timeout the user in question on a sliding scale: 4^numtimeouts. So, 1, 4, 16, 64... seconds.

Dynamic joining and parting

What's that? You want the bot in your channel? Well, there's no longer a need to hassle me - just join it's channel (ghost_of_leg_bot) and say !join. It will then join your room and start doing it's magic. If it's in your room, and you don't want it cluttering your chat with it's spam anymore, join it's channel and tell it !part, and it will leave.

Calendar Watching

On the fanstreamer calendar, but not gotten ghost_of_leg_bot in your channel? It's okay, ghost_of_leg_bot will now watch for twitch updates from any stream mentioned in the calendar. It won't join their channels, but it will be watching twitch, so you can be represented in it's !live report, and on the live page.

Statistics, by Game and by Channel

We keep track of a lot of stats. Now you can see what we keep track of, by game or by channel, at

Advice editing 

There's a lot of advice in the ghost_of_leg_bot, and not all of it is good advice. Help separate the wheat from the chaff, and vote on the advice ghost_of_leg_bot dispenses at


Got a message you find yourself often repeating? Have something you'd like said every so often? Try barks!

  • !bark add <command> "<message>" <Mod only (true or false)> [Interval (optional, in minutes)]
  • !bark remove <command>
For example:

!bark add promo "Check out my donation page at" false
!bark add modsonly "This message can only be triggered by mods" true
!bark add motd "Message of the day, repeats every hour" false 60
!bark add butt "Mods are away, post butts!" false
!bark remove butt

Note: For technical reasons, editing your barks will re-set the timers of any intervals, as will ghost_of_leg_bot's connection derping for some reason.

Also, barks can now be triggered from the API: "<channel name>/barks/<bark name>" Use this to give your "thanks/support/patreon etc" messages when you bring up your ending screen.


Yes, Ghost_of_Leg_Bot now supports whispers. Error messages will be sent via whisper, and if the whisper fails for some reason it'll do it's best to find where you are and notice you there instead. To ensure whispers get through, make sure you follow the bot.

Some commands also work through whispers (those that aren't dependent on a channel), so mostly the basic ones, !nextfan and !nextlrr and !live.

Dice Rolling

Yeah, ghost_of_leg_bot does dice rolling too. Just type !roll and a D&D-style dice roll, and it will report the result to you. For example, "!roll 2d20" might get you the response "Rolled 2d20 and got 20 (1,19)"


For those of you with an overlay, especially one in HTML (And if you don't have one, may I recommend this set of JavaScript building blocks as a starting point?) ghost_of_leg_bot now supports websockets. Simply connect a websocket to ws://<channel> (For example, ws:// and you will get notifications when the game changes and when stats change. For example:

{action: 'GameChanged', game: 'Creative'}
{action: 'StatChanged', stat: 'death', value: 20}
{action: 'GameChanged', game: ''}

This should help updates to the overlay come a lot faster, helping chat interactions somewhat.

Seen Tracking

Want to know when the last time someone spoke, or did something, in ghost_of_leg_bot's purview? Ask it!
!seen Anaerin


You asked for it, so quotes are now available. (Currently disabled for cantwearhats and hpbraincase, as they have their own quote-supporting bots):
  • !quote
Returns a random quote.
  • !quote count
Returns the number of quotes available.
  • !quote <number>
Returns the specified quote. For example:
!quote 3
  • !quote bytext <search string>
Searches the quotes for something with "<Search String>" in it, and returns a random matching result. For example:
!quote bytext flying monkeys
  • !quote byauthor <author name>
Searches for quotes written by <author name> and returns a random result. For example:
!quote byauthor senstaku
  • !quote bygame <game name>
Searches for quotes that took place while <game name> was playing and returns a random result. For example:
!quote bygame Batman Arkham City
  • !quote bychannel <channel name>
Searches for quotes that too place in <channel name> and returns a random result. For example:
!quote bychannel admiralmemo
  • !quote bydate <date>
Searches for quotes logged on <date> and returns them. Note: Timezones are a thing. For example:
!quote bydate 2016-03-11
  • !quote add <quote> (author) [date]
MOD ONLY - Adds a quote to the database, returning the ID on a successful add. If the author is not specified, it is assumed to be the person logging the quote, if the date is not specified, it is assumed to be now.
For example:
!quote add This is how quotes work (Anaerin) [2016-03-11]
!quote add Not everything has to be specified [2016-03-12]
!quote add In fact, you can leave everything out.
  • !quote mod <ID> <quote> (author) [date]
MOD ONLY - Modifies quote # ID. If the Author or Date are not specified, they are not changed.
For example:
!quote mod 2 Now quote 2 has other things (Anaerin) [2016-03-11]
!quote mod 7 You can leave those other arguments off, too.
!quote mod 3 But you must have the ID and the quote text.
  • !quote del <id>
MOD ONLY - Removes quote #ID from the database. For example:
!quote del 6
  • !quote <search term>
Attempts to do an "intelligent" search, returning a random result where the text, author or game match the specified term. For example: !quote batman

AWS Support

Support for the new AWS cluster is in testing right now. Hopefully it's stable enough to use.

No comments:

Post a Comment