1POE::Component::IRC::PlUusgeirn(C3o)ntributed Perl DocumPeOnEt:a:tCioomnponent::IRC::Plugin(3)
2
3
4

NAME

6       POE::Component::IRC::Plugin - Provides plugin constants and
7       documentation for POE::Component::IRC
8

SYNOPSIS

10        # A simple ROT13 'encryption' plugin
11
12        package Rot13;
13
14        use strict;
15        use warnings;
16        use POE::Component::IRC::Plugin qw( :ALL );
17
18        # Plugin object constructor
19        sub new {
20            my $package = shift;
21            return bless {}, $package;
22        }
23
24        sub PCI_register {
25            my ($self, $irc) = splice @_, 0, 2;
26
27            $irc->plugin_register( $self, 'SERVER', qw(public) );
28            return 1;
29        }
30
31        # This is method is mandatory but we don't actually have anything to do.
32        sub PCI_unregister {
33            return 1;
34        }
35
36        sub S_public {
37            my ($self, $irc) = splice @_, 0, 2;
38
39            # Parameters are passed as scalar-refs including arrayrefs.
40            my $nick    = ( split /!/, ${ $_[0] } )[0];
41            my $channel = ${ $_[1] }->[0];
42            my $msg     = ${ $_[2] };
43
44            if (my ($rot13) = $msg =~ /^rot13 (.+)/) {
45                $rot13 =~ tr[a-zA-Z][n-za-mN-ZA-M];
46
47                # Send a response back to the server.
48                $irc->yield( privmsg => $channel => $rot13 );
49                # We don't want other plugins to process this
50                return PCI_EAT_PLUGIN;
51            }
52
53            # Default action is to allow other plugins to process it.
54            return PCI_EAT_NONE;
55        }
56

DESCRIPTION

58       POE::Component::IRC's plugin system has been released separately as
59       Object::Pluggable. Gleaning at its documentation is advised. The rest
60       of this document mostly describes aspects that are specific to
61       POE::Component::IRC's use of Object::Pluggable.
62

HISTORY

64       Certain individuals in #PoE on MAGNet said we didn't need to bloat the
65       PoCo-IRC code...
66
67       BinGOs, the current maintainer of the module, and I heartily agreed
68       that this is a wise choice.
69
70       One example:
71
72       Look at the magnificent new feature in 3.4 -> irc_whois replies! Yes,
73       that is a feature I bet most of us have been coveting for a while, as
74       it definitely makes our life easier. It was implemented in 30 minutes
75       or so after a request, the maintainer said. I replied by saying that
76       it's a wonderful idea, but what would happen if somebody else asked for
77       a new feature? Maybe thatfeature is something we all would love to
78       have, so should it be put in the core? Plugins allow the core to stay
79       lean and mean, while delegating additional functionality to outside
80       modules. BinGOs' work with making PoCo-IRC inheritable is wonderful,
81       but what if there were 2 modules which have features that you would
82       love to have in your bot? Inherit from both? Imagine the mess...
83
84       Here comes plugins to the rescue :)
85
86       You could say Bot::Pluggable does the job, and so on, but if this
87       feature were put into the core, it would allow PoCo-IRC to be extended
88       beyond our wildest dreams, and allow the code to be shared amongst us
89       all, giving us superior bug smashing abilities.
90
91       Yes, there are changes that most of us will moan when we go update our
92       bots to use the new $irc object system, but what if we also used this
93       opportunity to improve PoCo-IRC even more and give it a lifespan until
94       Perl8 or whatever comes along? :)
95

DESCRIPTION

97       The plugin system works by letting coders hook into the two aspects of
98       PoCo-IRC:
99
100       •   Data received from the server
101
102       •   User commands about to be sent to the server
103
104       The goal of this system is to make PoCo-IRC so easy to extend, enabling
105       it to Take Over The World! *Just Kidding*
106
107       The general architecture of using the plugins should be:
108
109        # Import the stuff...
110        use POE;
111        use POE::Component::IRC;
112        use POE::Component::IRC::Plugin::ExamplePlugin;
113
114        # Create our session here
115        POE::Session->create( ... );
116
117        # Create the IRC session here
118        my $irc = POE::Component::IRC->spawn() or die "Oh noooo! $!";
119
120        # Create the plugin
121        # Of course it could be something like $plugin = MyPlugin->new();
122        my $plugin = POE::Component::IRC::Plugin::ExamplePlugin->new( ... );
123
124        # Hook it up!
125        $irc->plugin_add( 'ExamplePlugin', $plugin );
126
127        # OOPS, we lost the plugin object!
128        my $pluginobj = $irc->plugin_get( 'ExamplePlugin' );
129
130        # We want a list of plugins and objects
131        my $hashref = $irc->plugin_list();
132
133        # Oh! We want a list of plugin aliases.
134        my @aliases = keys %{ $irc->plugin_list() };
135
136        # Ah, we want to remove the plugin
137        $plugin = $irc->plugin_del( 'ExamplePlugin' );
138
139       The plugins themselves will conform to the standard API described here.
140       What they can do is limited only by imagination and the IRC RFC's ;)
141
142        # Import the constants
143        use POE::Component::IRC::Plugin qw( :ALL );
144
145        # Our constructor
146        sub new {
147            ...
148        }
149
150        # Required entry point for PoCo-IRC
151        sub PCI_register {
152            my ($self, $irc) = @_;
153            # Register events we are interested in
154            $irc->plugin_register( $self, 'SERVER', qw( 355 kick whatever) );
155
156            # Return success
157            return 1;
158        }
159
160        # Required exit point for PoCo-IRC
161        sub PCI_unregister {
162            my ($self, $irc) = @_;
163
164            # PCI will automatically unregister events for the plugin
165
166            # Do some cleanup...
167
168            # Return success
169            return 1;
170        }
171
172        # Registered events will be sent to methods starting with IRC_
173        # If the plugin registered for SERVER - irc_355
174        sub S_355 {
175            my($self, $irc, $line) = @_;
176
177            # Remember, we receive pointers to scalars, so we can modify them
178            $$line = 'frobnicate!';
179
180            # Return an exit code
181            return PCI_EAT_NONE;
182        }
183
184        # Default handler for events that do not have a corresponding plugin
185        # method defined.
186        sub _default {
187            my ($self, $irc, $event) = splice @_, 0, 3;
188
189            print "Default called for $event\n";
190
191            # Return an exit code
192            return PCI_EAT_NONE;
193        }
194
195       Plugins can even embed their own POE sessions if they need to do fancy
196       stuff.  Below is a template for a plugin which does just that.
197
198        package POE::Plugin::Template;
199
200        use POE;
201        use POE::Component::IRC::Plugin qw( :ALL );
202
203        sub new {
204            my $package = shift;
205            my $self = bless {@_}, $package;
206            return $self;
207        }
208
209        sub PCI_register {
210            my ($self, $irc) = splice @_, 0, 2;
211
212            # We store a ref to the $irc object so we can use it in our
213            # session handlers.
214            $self->{irc} = $irc;
215
216            $irc->plugin_register( $self, 'SERVER', qw(blah blah blah) );
217
218            POE::Session->create(
219                object_states => [
220                    $self => [qw(_start _shutdown)],
221                ],
222            );
223
224            return 1;
225        }
226
227        sub PCI_unregister {
228            my ($self, $irc) = splice @_, 0, 2;
229            # Plugin is dying make sure our POE session does as well.
230            $poe_kernel->call( $self->{SESSION_ID} => '_shutdown' );
231            delete $self->{irc};
232            return 1;
233        }
234
235        sub _start {
236            my ($kernel, $self) = @_[KERNEL, OBJECT];
237            $self->{SESSION_ID} = $_[SESSION]->ID();
238            # Make sure our POE session stays around. Could use aliases but that is so messy :)
239            $kernel->refcount_increment( $self->{SESSION_ID}, __PACKAGE__ );
240            return;
241        }
242
243        sub _shutdown {
244            my ($kernel, $self) = @_[KERNEL, OBJECT];
245            $kernel->alarm_remove_all();
246            $kernel->refcount_decrement( $self->{SESSION_ID}, __PACKAGE__ );
247            return;
248        }
249

EVENT TYPES

251   SERVER hooks
252       Hooks that are targeted toward data received from the server will get
253       the exact same arguments as if it was a normal event, look at the PoCo-
254       IRC docs for more information.
255
256       NOTE: Server methods are identified in the plugin namespace by the
257       subroutine prefix of S_*. I.e. an irc_kick event handler would be:
258
259        sub S_kick {}
260
261       The only difference is instead of getting scalars, the hook will get a
262       reference to the scalar, to allow it to mangle the data. This allows
263       the plugin to modify data *before* they are sent out to registered
264       sessions.
265
266       They are required to return one of the exit codes so PoCo-IRC will know
267       what to do.
268
269       Names of potential hooks
270
271        001
272        socketerr
273        connected
274        plugin_del
275        ...
276
277       Keep in mind that they are always lowercased. Check out the OUTPUT
278       EVENTS section of POE::Component::IRC's documentation for the complete
279       list of events.
280
281   USER hooks
282       These type of hooks have two different argument formats. They are split
283       between data sent to the server, and data sent through DCC connections.
284
285       NOTE: User methods are identified in the plugin namespace by the
286       subroutine prefix of U_*. I.e. an irc_kick event handler would be:
287
288        sub U_kick {}
289
290       Hooks that are targeted to user data have it a little harder. They will
291       receive a reference to the raw line about to be sent out. That means
292       they will have to parse it in order to extract data out of it.
293
294       The reasoning behind this is that it is not possible to insert hooks in
295       every method in the $irc object, as it will become unwieldy and not
296       allow inheritance to work.
297
298       The DCC hooks have it easier, as they do not interact with the server,
299       and will receive references to the arguments specified in the DCC
300       plugin documentation regarding dcc commands.
301
302       Names of potential hooks
303
304        kick
305        dcc_chat
306        ison
307        privmsg
308        ...
309
310       Keep in mind that they are always lowercased, and are extracted from
311       the raw line about to be sent to the irc server. To be able to parse
312       the raw line, some RFC reading is in order. These are the DCC events
313       that are not given a raw line, they are:
314
315        dcc        - $nick, $type, $file, $blocksize, $timeout
316        dcc_accept - $cookie, $myfile
317        dcc_resume - $cookie
318        dcc_chat   - $cookie, @lines
319        dcc_close  - $cookie
320
321   _default
322       If a plugin has registered for an event but doesn't have a hook method
323       defined for ir, component will attempt to call a plugin's "_default"
324       method.  The first parameter after the plugin and irc objects will be
325       the handler name.
326
327        sub _default {
328            my ($self, $irc, $event) = splice @_, 0, 3;
329
330            # $event will be something like S_public or U_dcc, etc.
331            return PCI_EAT_NONE;
332        }
333
334       The "_default" handler is expected to return one of the exit codes so
335       PoCo-IRC will know what to do.
336

EXIT CODES

338   PCI_EAT_NONE
339       This means the event will continue to be processed by remaining plugins
340       and finally, sent to interested sessions that registered for it.
341
342   PCI_EAT_CLIENT
343       This means the event will continue to be processed by remaining plugins
344       but it will not be sent to any sessions that registered for it. This
345       means nothing will be sent out on the wire if it was an USER event,
346       beware!
347
348   PCI_EAT_PLUGIN
349       This means the event will not be processed by remaining plugins, it
350       will go straight to interested sessions.
351
352   PCI_EAT_ALL
353       This means the event will be completely discarded, no plugin or session
354       will see it. This means nothing will be sent out on the wire if it was
355       an USER event, beware!
356

EXPORTS

358       Exports the return constants for plugins to use in @EXPORT_OK Also, the
359       ':ALL' tag can be used to get all of them.
360

SEE ALSO

362       POE::Component::IRC
363
364       Object::Pluggable
365
366       Object::Pluggable::Pipeline
367
368       POE::Session
369

AUTHOR

371       Apocalypse <apocal@cpan.org>
372
373
374
375perl v5.32.1                      2021-01-27    POE::Component::IRC::Plugin(3)
Impressum