Skip to content

Latest commit

History

History
122 lines (101 loc) 路 5.67 KB

File metadata and controls

122 lines (101 loc) 路 5.67 KB

Notes

Random notes about internals so they don't get forgotten (and most of them not about Christine, how about that).

Creating new command functionality

  • Core functionality (message attributes etc) is all handled in connection.pike _send_recursive(). The order things are checked determines precedence.
  • Commands can be directly manipulated in the config mapping with no validation checks. This is unsupported behaviour but will probably work.
  • From the front end, commands are filtered by chan_commands.pike validate(), with the majority of flags being checked in the recursive _validate().
  • For completely new functionality, the command GUI will need a new type of element, possibly with a new colour.
    • This element needs a method of distinguishment, most commonly an attribute with a fixed value.
  • For any kind of newish feature, the command GUI probably needs a new tray item to make it easily accessible. This may also require enhancing the type to allow more flexibility. (Optional for new builtins.)
  • The classic editor needs to be enhanced.
    • Simple features can be added to the flags mapping at the top
    • More complicated features need ad-hoc code in render_command()

Commonly-used emoji

  • Gear: BUTTON({type: "button", title: "Configure"}, "\u2699")
  • Pencil: BUTTON({type: "button", class: "editbtn"}, "\u{1F589}") or U+270D WRITING HAND
  • Trashcan: BUTTON({type: "button", class: "confirmdelete", title: "Delete"}, "馃棏"),

Hopping the Bot

Prior to the /serverstatus page having the ability to directly hop the bot, this was the procedure. It is still available for situations in which a manual hop is required.

Transferring the primary instance of the bot between Gideon and Sikorsky is simple in theory, but in practice, I have some safeguards to make sure that nothing goes wrong. Follow these steps to hop the bot back and forth.

Normal operation has the active bot on Sikorsky, the active database on Sikorsky, and a read-only replica database on Gideon with an inactive bot. (Note that "inactive" does not mean idle; an inactive bot will continue to respond to web requests etc, but is not the primary bot, and will reject any websockets.) In such a situation, running ./dbctl stat should give output something like this:

rosuav@sikorsky:~/stillebot$ ./dbctl stat
* Database is read/write
* Active bot is on sikorsky.mustardmine.com
* Incoming replication active
  192.168.0.19 Active bot [idle] 
 37.61.205.138 Outgoing replication [active] 
 37.61.205.138 Active bot [idle] 
rosuav@gideon:~/stillebot$ ./dbctl stat
* Database is read-only
* Active bot is on sikorsky.mustardmine.com
* Incoming replication active
 37.61.205.138 Read-only bot [idle] 
 159.196.70.86 Outgoing replication [active] 

Note that both instances of the bot MUST connect to the read/write database, and both instances will connect to the local database, but there may or may not be the other cross-connection.

To hop the bot from Sikorsky to Gideon:

  1. On both ends, verify that ./dbctl stat looks good.
  2. Sikorsky: ./dbctl dn to set both databases read-only. We are now in a degraded state, with nothing able to be saved yet.
  3. Gideon: ./dbctl repl to ensure that all three LSNs are the same. If they aren't, wait a second or two and try again (final transactions getting settled).
  4. Gideon: ./dbctl up to bring up the database there. We will now be in a fully functional state again, but with Gideon's database being the primary instead of Sikorsky's. Check ./dbctl stat and ./dbctl repl if desired.
  5. Gideon: ./dbctl ac to activate the bot there. We are now in a safe state with both the database and the bot primarily on Gideon. If Sikorsky becomes unavailable at this time, the impact will be minimized.

Hopping back is the same with the roles reversed.

NOTE: In an emergency, if Sikorsky is already unavailable, simply running ./dbctl up followed by ./dbctl ac will bring everything up on Gideon. But unless everything had in fact been cleanly replicated before the outage, this may result in a conflict when the two databases reconnect. There's no easy fix for such a conflict, so it has to be done manually. Use of ./dbctl log may help with the detection and diagnosis here.

What Counts As Stream Ending?

Ideally, all of these definitions should be unified, and then this single definition should be published as "stream counts as offline when...".

  • The !!streamoffline special trigger happens immediately when Twitch signals that you have gone offline.
  • The !!streamreset special trigger waits 30 minutes before resetting, cancelling if you go online again within that time. (This is also available internally as the "stream-reset" signal.)
  • Twitch watch streaks only count two separate streams if there's 30 minutes between them
  • Goal bar autoreset triggers on stream-reset (and also stream-online)
  • Cooldowns reset on stream-reset, but are blocked if the stream is offline, even temporarily.
  • Twitch channel point redemptions on one-per-stream are a bit quirky. Normally, any bounce of the stream resets them; however, in some cases, it might be that the stream-offline signal isn't sent but the redemptions are available again. TODO: See whether the EventSub offline signal is in fact sent - it might just be a quirk of Stillebot's polling.
  • Delaying an echoable_message until end of stream uses the stream-reset signal.
  • Dynamic channel point costs reset every time the stream goes on/offline, without delay
  • The definition of "raided this stream" for art share permission uses the stream-reset signal.