This mixes in functions that fully implement an IRCPlugin. They don't do much by themselves other than call the module's functions, as well as implement things like functions that return the plugin's name, its list of bot command words, etc. It does this by introspecting the module and implementing itself as it sees fit.
This mixin adds shorthand functions to proxy calls to kameloso.messaging functions, *partially applied* with the main thread ID, so they can easily be called with knowledge only of the plugin symbol.
The amount of time after which seen users should be saved to disk.
The filename to which to persistently store our list of seen users between executions of the program.
An instance of *settings* for the Seen plugin. We will define these below. The members of it will be saved to and loaded from the configuration file, for use in our module.
Our associative array (AA) of seen users; a dictionary keyed with users' nicknames and with values that are UNIX timestamps, denoting when that user was last *seen* online.
Forwards the supplied IRCEvent to IRCPluginImpl.onEventImpl.
Basic constructor for a plugin.
Lets a plugin modify an IRCEvent while it's begin constructed, before it's finalised and passed on to be handled.
Writes plugin resources to disk, creating them if they don't exist.
Loads configuration for this plugin from disk.
Change a plugin's Settings-annotated settings struct member by their string name.
Prints the plugin's Settings-annotated settings struct.
Gathers the configuration text the plugin wants to contribute to the configuration file.
Tick function. Called once every main loop iteration.
Self-test function.
Returns the name of the plugin. (Technically it's the name of the module.)
Compile a list of our a plugin's oneliner commands.
Forwards to IRCPluginImpl.commandsImpl.
Proxies a bus message to the plugin, to let it handle it (or not).
Metadata about a IRCEventHandler.Command- and/or IRCEventHandler.Regex-annotated event handler.
An IRCPluginState instance containing variables and arrays that represent the current state of the plugin. Should generally be passed by reference.
Allows a plugin to modify an event post-parsing.
Called to let the plugin react to a new event, parsed from the server.
Called when the plugin is requested to initialise its disk resources.
Reads serialised configuration text into the plugin's settings struct.
Called to let the plugin contribute settings when writing the configuration file.
Called when we want to change a setting by its string name.
Called at program start but before connection has been established.
Called when we want a plugin to print its Settings-annotated struct of settings.
Called during shutdown of a connection; a plugin's would-be destructor.
Returns the name of the plugin.
Returns an array of the descriptions of the commands a plugin offers.
Returns an array of the descriptions of the channel-specific commands a plugin offers.
Reloads the plugin, where such is applicable.
Called when a bus message arrives from another plugin.
Returns whether or not the plugin is enabled in its settings.
Called on each iteration of the main loop.
Called when the plugin is first loaded.
Performs self-tests against another bot.
This is your plugin to the outside world, usually the only thing publicly visible in the entire module. It only serves as a way of proxying calls to our top-level private functions, as well as to house plugin-specific and -private variables that we want to keep out of top-level scope for the sake of modularity. If the only state is in the plugin, several plugins of the same kind can technically be run alongside each other, which would allow for several bots to be run in parallel. This is not yet supported but there's fundamentally nothing stopping it.
As such it houses this plugin's *state*, notably its instance of SeenSettings and its IRCPluginState.
The IRCPluginState is a struct housing various variables that together make up the plugin's state. This is additionally where information is kept about the bot, the server, and some other meta-things about the program.
We don't declare it here; we will mix it in later with the IRCPluginImpl mixin.
* IRCPluginState.client houses information about the client itself, such as your nickname and other things related to an IRC client.
* IRCPluginState.server houses information about the server you're connected to.
* IRCPluginState.bot houses information about things that relate to an IRC bot, like which channels to join, which home channels to operate in, the list of administrator accounts, etc.
* IRCPluginState.settings is a copy of the "global" CoreSettings, which contains information about how the bot should output text, whether or not to always save to disk upon program exit, and some other program-wide settings.
* IRCPluginState.connSettings is like IRCPluginState.settings, except for values relating to the connection to the server; whether to use IPv6, paths to any certificates, and the such.
* IRCPluginState.users is an associative array keyed with users' nicknames. The value to that key is an IRCUser representing that user in terms of nickname, address, ident, services account name, and much more. This is a way to keep track of users by more than merely their name. It is however not saved at the end of the program; as everything else it is merely state and transient.
* IRCPluginState.channels is another associative array, this one with all the known channels keyed by their names. This way we can access detailed information about any known channel, given only their name.
* IRCPluginState.pendingReplays is also an associative array into which we place Replays. The main loop will pick up on these and call WHOIS on the nickname in the key. A Replay is otherwise just an IRCEvent to be played back when the WHOIS results return, as well as a delegate that invokes the function that was originally to be called. Constructing a Replay is all wrapped in a function enqueue, with the queue management handled behind the scenes.
* IRCPluginState.hasPendingReplays is merely a bool of whether or not there currently are any Replays in IRCPluginState.pendingReplays, cached to avoid associative array length lookups.
* IRCPluginState.readyReplays is an array of Replays that have seen their WHOIS request issued and the result received. Moving one from IRCPluginState.pendingReplays
to IRCPluginState.readyReplays will make the main loop pick it up, *update* the IRCEvent stored within it with what we now know of the sender and/or target, and then replay the event by invoking its delegate.
* IRCPluginState.awaitingFibers is an array of Fibers indexed by dialect.defs.IRCEvent.Types' numeric values. Fibers in the array of a particular event type will be executed the next time such an event is incoming. Think of it as fiber callbacks.
* IRCPluginState.awaitingDelegates is literally an array of callback delegates, to be triggered when an event of a matching type comes along.
* IRCPluginState.scheduledFibers is also an array of Fibers, but not one keyed on or indexed by event types. Instead they are tuples of a Fiber and a long timestamp of when they should be run. Use delay to enqueue.
* IRCPluginState.scheduledDelegates is likewise an array of delegates, to be triggered at a later point in time.
* IRCPluginState.previousWhoisTimestamps if an associative array of UNIX timestamps keyed by nickname strings. These represent when last a WHOIS was issued for the nickname.
* IRCPluginState.updates is a bitfield which represents what aspect of the bot was *changed* during processing or postprocessing. If any of the bits are set, represented by the enum values of IRCPluginState.Updates, the main loop will pick up on it and propagate it to other plugins. If these flags are not set, changes will never leave the plugin and may be overwritten by other plugins. It is mostly for internal use.
* IRCPluginState.abort is a pointer to the global abort flag. When this is set, it signals the rest of the program that we want to terminate cleanly.
* IRCPluginState.deferredActions is an array of DeferredActions; a way to defer the execution of a delegate or fiber to the main thread, to be invoked with context only it has, such as knowledge of all plugins.
* IRCPluginState.messages is an array of ThreadMessages, used by plugins to send messages up the stack to the main thread. These can signal anything from "save configuration to file" to "quit the program".
* IRCPluginState.priorityMessages is likewise an array of ThreadMessages, but these will always be processed before those in IRCPluginState.messages are.
* IRCPluginState.outgoingMessages is an array of Messages bound to be sent to the server.