Skip to content

Container and Plugins

Filip edited this page Jul 4, 2019 · 2 revisions

Container

Container is TwitchScope that (additionally to TwitchScopes) provides IrcState (Connection status), connect and disconnect functions and ability to add Plugins relevant to that container. Containers can be perceived as closed environment where all events go through plugins that can alter (or filter) them.

MainScope is Container. That's why you can add plugins in its context without declaring container on your own.

TmiK provides basic builder function container. Container relies on MainScope (or other TmiStateProvider) so it's must be called only inside its context.

Plugins

Plugins provide an easy plug&play functionality to your code. They may be similar to TwitchScope because they can filter or map incoming and outgoing messages but Plugins don't have body (context). For example TmiK provides Reconnect plugin that observes connection states and tries to reconnect (and rejoin channels) when you go offline. Or imagine Greeter plugin that observers all incoming messages and if it sees new user it sends welcome message
All incoming and outgoing messages goes through all plugins and each plugin can filter out or alter each message. In addition to that plugins can send messages or connect/disconnect to/from Twitch

Creating custom plugin

TmiK provides only Reconnect plugin so let's look at it and figure out how it works.

Declaration and initialization

Plugin is an object that inherits TwitchPlugin interface. Here is function that creates TwitchPlugin object

fun Container.Reconnect(attempts: Int = 0, interval: Long = 10_000) = object : TwitchPlugin {
    override val name = "reconnect"

    // Logic here ...
}

Above we see that every plugin has its name for identification. Inside the plugin we can override several functions that let us filter and/or map incoming and outgoing messages. (filterIncoming, filterOutgoing, mapIncoming, mapOutgoing, onConnectionStateChange)

Logic

Now we can observe connection state by overriding onConnectionStateChange so when we see that connection went down, we try to reconnect.

override fun onConnectionStateChange(newState: IrcState) {
    // Ignore current state and connecting state
    if (currState == newState || newState == CONNECTING) return

    currState = newState
    if (newState == DISCONNECTED) // when we disconnect, try to connect again
        tryToConnect()
    else if (newState == CONNECTED) { // when we connect, rejoin all channels that we were connected before
        rejoinChannels()
    }
}

Result

So now we have plugin that looks at connection status and when it goes down, it tries to reconnect. Look at Reconnect plugin to see the specific implementation with code not present here. (observing JOIN and PART events for determining channels to rejoin and reconnecting logic itself)