SeenPlugin

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.

struct IRCPluginState
{
    IRCClient client;
    IRCServer server;
    IRCBot bot;
    CoreSettings settings;
    ConnectionSettings connSettings;
    Tid mainThread;
    IRCUser[string] users;
    IRCChannel[string] channels;
    Replay[][string] pendingReplays;
    bool hasPendingReplays;
    Replay[] readyReplays;
    Fiber[][] awaitingFibers;
    void delegate(IRCEvent)[][] awaitingDelegates;
    ScheduledFiber[] scheduledFibers;
    ScheduledDelegate[] scheduledDelegates;
    long nextScheduledTimestamp;
    void updateScheule();
    Update updates;
    bool* abort;
}

* 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.

version(WithSeenPlugin)
final
class SeenPlugin : IRCPlugin {}

Mixed In Members

From mixin IRCPluginImpl

isEnabled
bool isEnabled()

Introspects the current plugin, looking for a Settings-annotated struct member that has a bool annotated with Enabler, which denotes it as the bool that toggles a plugin on and off.

onEvent
void onEvent(IRCEvent event)

Forwards the supplied IRCEvent to IRCPluginImpl.onEventImpl.

this
this(IRCPluginState state)

Basic constructor for a plugin.

postprocess
void postprocess(IRCEvent event)

Lets a plugin modify an IRCEvent while it's begin constructed, before it's finalised and passed on to be handled.

initResources
void initResources()

Writes plugin resources to disk, creating them if they don't exist.

deserialiseConfigFrom
void deserialiseConfigFrom(string configFile, string[][string] missingEntries, string[][string] invalidEntries)

Loads configuration for this plugin from disk.

setSettingByName
bool setSettingByName(string setting, string value)

Change a plugin's Settings-annotated settings struct member by their string name.

printSettings
void printSettings()

Prints the plugin's Settings-annotated settings struct.

serialiseConfigInto
bool serialiseConfigInto(Appender!(char[]) sink)

Gathers the configuration text the plugin wants to contribute to the configuration file.

name
string name()

Returns the name of the plugin. (Technically it's the name of the module.)

channelSpecificCommands
IRCPlugin.CommandMetadata[string] channelSpecificCommands(string channelName)

Compile a list of our a plugin's oneliner commands.

commands
IRCPlugin.CommandMetadata[string] commands()

Forwards to IRCPluginImpl.commandsImpl.

onBusMessage
void onBusMessage(string header, Sendable content)

Proxies a bus message to the plugin, to let it handle it (or not).

Inherited Members

From IRCPlugin

CommandMetadata
struct CommandMetadata

Metadata about a IRCEventHandler.Command- and/or IRCEventHandler.Regex-annotated event handler.

state
IRCPluginState state;

An IRCPluginState instance containing variables and arrays that represent the current state of the plugin. Should generally be passed by reference.

postprocess
void postprocess(IRCEvent event)

Allows a plugin to modify an event post-parsing.

onEvent
void onEvent(IRCEvent event)

Called to let the plugin react to a new event, parsed from the server.

initResources
void initResources()

Called when the plugin is requested to initialise its disk resources.

deserialiseConfigFrom
void deserialiseConfigFrom(string configFile, string[][string] missingEntries, string[][string] invalidEntries)

Reads serialised configuration text into the plugin's settings struct.

serialiseConfigInto
bool serialiseConfigInto(Appender!(char[]) sink)

Called to let the plugin contribute settings when writing the configuration file.

setSettingByName
bool setSettingByName(string setting, string value)

Called when we want to change a setting by its string name.

setup
void setup()

Called at program start but before connection has been established.

start
void start()

Called when connection has been established.

printSettings
void printSettings()

Called when we want a plugin to print its Settings-annotated struct of settings.

teardown
void teardown()

Called during shutdown of a connection; a plugin's would-be destructor.

name
string name()

Returns the name of the plugin.

commands
CommandMetadata[string] commands()

Returns an array of the descriptions of the commands a plugin offers.

channelSpecificCommands
CommandMetadata[string] channelSpecificCommands(string )

Returns an array of the descriptions of the channel-specific commands a plugin offers.

reload
void reload()

Reloads the plugin, where such is applicable.

onBusMessage
void onBusMessage(string header, Sendable content)

Called when a bus message arrives from another plugin.

isEnabled
bool isEnabled()

Returns whether or not the plugin is enabled in its settings.

Meta