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.
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 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.
This is your plugin to the outside world, 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 where information is kept about the bot, the server, and some metathings allowing us to send messages to the server. We don't define it here; we 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.mainThread is the *thread ID* of the thread running the main loop. We indirectly use it to send strings to the server by way of concurrency messages, but it is usually not something you will have to deal with directly.
* 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.nextScheduledFibers is also a UNIX timestamp, here of when the next ScheduledFiber in IRCPluginState.scheduledFibers *or* the next ScheduledDelegate in IRCPluginState.scheduledDelegates
is due to be processed. Caching it here means we won't have to walk through the arrays to find out as often.
* IRCPluginState.updateSchedule merely iterates all scheduled fibers and delegates, caching the time at which the next one should trigger in IRCPluginState.nextScheduledFibers.
* 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 bool. When this is set, it signals the rest of the program that we want to terminate cleanly.