pbot/lib/PBot/Core/EventDispatcher.pm

136 lines
4.3 KiB
Perl
Raw Normal View History

2021-06-19 06:23:34 +02:00
# File: EventDispatcher.pm
#
# Purpose: Registers event handlers and dispatches events to them.
#
2021-07-21 07:44:51 +02:00
# Note: PBot::Core::EventDispatcher has no relation to PBot::Core::EventQueue.
2021-06-19 06:23:34 +02:00
2021-07-11 00:00:22 +02:00
# SPDX-FileCopyrightText: 2021 Pragmatic Software <pragma78@gmail.com>
# SPDX-License-Identifier: MIT
License project under MPL2 This patch adds the file LICENSE which is the verbatim copy of the Mozilla Public License Version 2.0 as retreived from https://www.mozilla.org/media/MPL/2.0/index.815ca599c9df.txt on 2017-03-05. This patch also places license headers for the MPL2 type A variant of the license header in the following files: PBot/AntiFlood.pm PBot/BanTracker.pm PBot/BlackList.pm PBot/BotAdminCommands.pm PBot/BotAdmins.pm PBot/ChanOpCommands.pm PBot/ChanOps.pm PBot/Channels.pm PBot/Commands.pm PBot/DualIndexHashObject.pm PBot/EventDispatcher.pm PBot/FactoidCommands.pm PBot/FactoidModuleLauncher.pm PBot/Factoids.pm PBot/HashObject.pm PBot/IRCHandlers.pm PBot/IgnoreList.pm PBot/IgnoreListCommands.pm PBot/Interpreter.pm PBot/LagChecker.pm PBot/Logger.pm PBot/MessageHistory.pm PBot/MessageHistory_SQLite.pm PBot/NickList.pm PBot/PBot.pm PBot/Plugins.pm PBot/Plugins/AntiAway.pm PBot/Plugins/AntiKickAutoRejoin.pm PBot/Plugins/AntiRepeat.pm PBot/Plugins/AntiTwitter.pm PBot/Plugins/AutoRejoin.pm PBot/Plugins/Counter.pm PBot/Plugins/Quotegrabs.pm PBot/Plugins/Quotegrabs/Quotegrabs_Hashtable.pm PBot/Plugins/Quotegrabs/Quotegrabs_SQLite.pm PBot/Plugins/UrlTitles.pm PBot/Plugins/_Example.pm PBot/Refresher.pm PBot/Registerable.pm PBot/Registry.pm PBot/RegistryCommands.pm PBot/SQLiteLogger.pm PBot/SQLiteLoggerLayer.pm PBot/SelectHandler.pm PBot/StdinReader.pm PBot/Timer.pm PBot/Utils/ParseDate.pm PBot/VERSION.pm build/update-version.pl modules/acronym.pl modules/ago.pl modules/c11std.pl modules/c2english.pl modules/c2english/CGrammar.pm modules/c2english/c2eng.pl modules/c99std.pl modules/cdecl.pl modules/cfaq.pl modules/cjeopardy/IRCColors.pm modules/cjeopardy/QStatskeeper.pm modules/cjeopardy/Scorekeeper.pm modules/cjeopardy/cjeopardy.pl modules/cjeopardy/cjeopardy_answer.pl modules/cjeopardy/cjeopardy_filter.pl modules/cjeopardy/cjeopardy_hint.pl modules/cjeopardy/cjeopardy_qstats.pl modules/cjeopardy/cjeopardy_scores.pl modules/cjeopardy/cjeopardy_show.pl modules/codepad.pl modules/compiler_block.pl modules/compiler_client.pl modules/compiler_vm/Diff.pm modules/compiler_vm/cc modules/compiler_vm/compiler_client.pl modules/compiler_vm/compiler_server.pl modules/compiler_vm/compiler_server_vbox_win32.pl modules/compiler_vm/compiler_server_watchdog.pl modules/compiler_vm/compiler_vm_client.pl modules/compiler_vm/compiler_vm_server.pl modules/compiler_vm/compiler_watchdog.pl modules/compiler_vm/languages/_c_base.pm modules/compiler_vm/languages/_default.pm modules/compiler_vm/languages/bash.pm modules/compiler_vm/languages/bc.pm modules/compiler_vm/languages/bf.pm modules/compiler_vm/languages/c11.pm modules/compiler_vm/languages/c89.pm modules/compiler_vm/languages/c99.pm modules/compiler_vm/languages/clang.pm modules/compiler_vm/languages/clang11.pm modules/compiler_vm/languages/clang89.pm modules/compiler_vm/languages/clang99.pm modules/compiler_vm/languages/clangpp.pm modules/compiler_vm/languages/clisp.pm modules/compiler_vm/languages/cpp.pm modules/compiler_vm/languages/freebasic.pm modules/compiler_vm/languages/go.pm modules/compiler_vm/languages/haskell.pm modules/compiler_vm/languages/java.pm modules/compiler_vm/languages/javascript.pm modules/compiler_vm/languages/ksh.pm modules/compiler_vm/languages/lua.pm modules/compiler_vm/languages/perl.pm modules/compiler_vm/languages/python.pm modules/compiler_vm/languages/python3.pm modules/compiler_vm/languages/qbasic.pm modules/compiler_vm/languages/scheme.pm modules/compiler_vm/languages/server/_c_base.pm modules/compiler_vm/languages/server/_default.pm modules/compiler_vm/languages/server/c11.pm modules/compiler_vm/languages/server/c89.pm modules/compiler_vm/languages/server/c99.pm modules/compiler_vm/languages/server/clang.pm modules/compiler_vm/languages/server/clang11.pm modules/compiler_vm/languages/server/clang89.pm modules/compiler_vm/languages/server/clang99.pm modules/compiler_vm/languages/server/cpp.pm modules/compiler_vm/languages/server/freebasic.pm modules/compiler_vm/languages/server/haskell.pm modules/compiler_vm/languages/server/java.pm modules/compiler_vm/languages/server/qbasic.pm modules/compiler_vm/languages/server/tendra.pm modules/compiler_vm/languages/sh.pm modules/compiler_vm/languages/tendra.pm modules/compliment modules/cstd.pl modules/define.pl modules/dice_roll.pl modules/excuse.sh modules/expand_macros.pl modules/fnord.pl modules/funnyish_quote.pl modules/g.pl modules/gdefine.pl modules/gen_cfacts.pl modules/gencstd.pl modules/get_title.pl modules/getcfact.pl modules/google.pl modules/gspy.pl modules/gtop10.pl modules/gtop15.pl modules/headlines.pl modules/horoscope modules/horrorscope modules/ideone.pl modules/insult.pl modules/love_quote.pl modules/man.pl modules/map.pl modules/math.pl modules/prototype.pl modules/qalc.pl modules/random_quote.pl modules/seen.pl modules/urban modules/weather.pl modules/wikipedia.pl pbot.pl pbot.sh It is highly recommended that this list of files is reviewed to ensure that all files are the copyright of the sole maintainer of the repository. If any files with license headers contain the intellectual property of anyone else, it is recommended that a request is made to revise this patch or that the explicit permission of the co-author is gained to allow for the license of the work to be changed. I (Tomasz Kramkowski), the contributor, take no responsibility for any legal action taken against the maintainer of this repository for incorrectly claiming copyright to any work not owned by the maintainer of this repository.
2017-03-05 22:33:31 +01:00
2021-07-21 07:44:51 +02:00
package PBot::Core::EventDispatcher;
use parent 'PBot::Core::Class';
2021-06-19 06:23:34 +02:00
use PBot::Imports;
2021-07-24 04:22:25 +02:00
use PBot::Core::Utils::PriorityQueue;
sub initialize {
2020-02-15 23:38:32 +01:00
my ($self, %conf) = @_;
# hash table of event handlers
$self->{handlers} = {};
}
# add an event handler
#
# priority ranges from 0 to 100. 0 is the highest priority, i.e. an handler with
# priority 0 will handle events first. 100 is the lowest priority and will handle
2021-07-21 07:00:30 +02:00
# events last. priority defaults to 50 if omitted.
#
# NickList reserves 0 and 100 to ensure its list is populated by JOINs, etc,
# before any handlers need to consult its list, or depopulated by PARTs, QUITs,
# KICKs, etc, after any other handlers need to consult its list.
sub register_handler {
my ($self, $event_name, $subref, $priority) = @_;
# get the package of the calling subroutine
2020-02-15 23:38:32 +01:00
my ($package) = caller(0);
# internal identifier to find calling package's event handler
my $handler_id = "$package-$event_name";
my $entry = {
priority => $priority // 50,
id => $handler_id,
subref => $subref,
};
# create new priority-queue for event-name if one doesn't exist
if (not exists $self->{handlers}->{$event_name}) {
2021-07-24 04:22:25 +02:00
$self->{handlers}->{$event_name} = PBot::Core::Utils::PriorityQueue->new(pbot => $self->{pbot});
}
# add the event handler
$self->{handlers}->{$event_name}->add($entry);
# debugging
if ($self->{pbot}->{registry}->get_value('eventdispatcher', 'debug')) {
$self->{pbot}->{logger}->log("EventDispatcher: Add handler: $handler_id\n");
}
}
# remove an event handler
sub remove_handler {
my ($self, $event_name) = @_;
# get the package of the calling subroutine
2020-02-15 23:38:32 +01:00
my ($package) = caller(0);
# internal identifier to find calling package's event handler
my $handler_id = "$package-$event_name";
# remove the event handler
if (exists $self->{handlers}->{$event_name}) {
my $handlers = $self->{handlers}->{$event_name};
for (my $i = 0; $i < $handlers->count; $i++) {
my $handler = $handlers->get($i);
if ($handler->{id} eq $handler_id) {
$handlers->remove($i--);
}
}
# remove root event-name key if it has no more handlers
if (not $self->{handlers}->{$event_name}->count) {
delete $self->{handlers}->{$event_name};
2020-02-15 23:38:32 +01:00
}
}
# debugging
if ($self->{pbot}->{registry}->get_value('eventdispatcher', 'debug')) {
$self->{pbot}->{logger}->log("EventDispatcher: Remove handler: $handler_id\n");
}
}
# send an event to its handlers
sub dispatch_event {
my ($self, $event_name, $event_data) = @_;
2020-02-15 23:38:32 +01:00
# debugging flag
my $debug = $self->{pbot}->{registry}->get_value('eventdispatcher', 'debug') // 0;
2020-02-15 23:38:32 +01:00
2021-07-08 05:15:01 +02:00
# undef means no handlers have handled this event
my $dispatch_result= undef;
2020-02-15 23:38:32 +01:00
# if the event-name has handlers
if (exists $self->{handlers}->{$event_name}) {
# then dispatch the event to each one
foreach my $handler ($self->{handlers}->{$event_name}->entries) {
# debugging
if ($debug) {
$self->{pbot}->{logger}->log("Dispatching $event_name to handler $handler->{id}\n");
2020-02-15 23:38:32 +01:00
}
2021-07-08 05:15:01 +02:00
# invoke an event handler. a handler may return undef to indicate
# that it decided not to handle this event.
my $handler_result = eval { $handler->{subref}->($event_name, $event_data) };
2021-07-08 05:15:01 +02:00
# check for exception
if (my $exception = $@) {
$self->{pbot}->{logger}->log("Exception in event handler: $exception");
} else {
# update $dispatch_result only when handler result is a defined
# value so we remember if any handlers have handled this event.
$dispatch_result = $handler_result if defined $handler_result;
}
2020-02-15 23:38:32 +01:00
}
}
2021-07-08 05:15:01 +02:00
# return undef if no handlers have handled this event; otherwise the return
# value of the last event handler to handle this event.
return $dispatch_result;
}
1;