SeenPlugin

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.

struct IRCPluginState
{
    IRCClient client;
    IRCServer server;
    IRCBot bot;
    CoreSettings settings;
    ConnectionSettings connSettings;
    IRCUser[string] users;
    IRCChannel[string] channels;
    Replay[][string] pendingReplays;
    bool hasPendingReplays;
    Replay[] readyReplays;
    Fiber[][] awaitingFibers;
    void delegate(IRCEvent)[][] awaitingDelegates;
    ScheduledFiber[] scheduledFibers;
    ScheduledDelegate[] scheduledDelegates;
    long[string] previousWhoisTimestamps;
    Update updates;
    bool* abort;
    DeferredAction[] deferredActions;
    ThreadMessage[] messages;
    ThreadMessage[] priorityMessages;
    Message[] outgoingMessages;
}

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

Members

Mixins

__anonymous
mixin IRCPluginImpl

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.

__anonymous
mixin MessagingProxy

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.

Static variables

timeBetweenSaves
auto timeBetweenSaves;

The amount of time after which seen users should be saved to disk.

Variables

seenFile
string seenFile;

The filename to which to persistently store our list of seen users between executions of the program.

seenSettings
SeenSettings seenSettings;

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.

seenUsers
RehashingAA!(long[string]) seenUsers;

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.

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.

tick
bool tick(Duration elapsed)

Tick function. Called once every main loop iteration.

selftest
Ternary selftest(Selftester tester)

Self-test function.

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.

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 channelName)

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.

tick
bool tick(Duration elapsed)

Called on each iteration of the main loop.

initialise
void initialise()

Called when the plugin is first loaded.

Ternary (from std.typecons)
public import std.typecons : Ternary;
Undocumented in source.
selftest
Ternary selftest(Selftester )

Performs self-tests against another bot.