html/dau.pl
1 ################################################################################
2 # $Id: dau.pl 273 2008-02-03 15:27:25Z heidinger $
3 ################################################################################
4 #
5 # dau.pl - write like an idiot
6 #
7 ################################################################################
8 # Author
9 ################################################################################
10 #
11 # Clemens Heidinger <heidinger@dau.pl>
12 #
13 ################################################################################
14 # Changelog
15 ################################################################################
16 #
17 # dau.pl has a built-in changelog (--changelog switch)
18 #
19 ################################################################################
20 # Credits
21 ################################################################################
22 #
23 # - Robert Hennig: For the original dau shell script. Out of this script,
24 # merged with some other small Perl and shell scripts and aliases arised the
25 # first version of dau.pl for irssi.
26 #
27 ################################################################################
28 # Documentation
29 ################################################################################
30 #
31 # dau.pl has a built-in documentation (--help switch)
32 #
33 ################################################################################
34 # License
35 ################################################################################
36 #
37 # Licensed under the BSD license
38 #
39 ################################################################################
40 # Website
41 ################################################################################
42 #
43 # http://dau.pl/
44 #
45 # Additional information, DAU.pm, the dauomat and the dauproxy
46 #
47 ################################################################################
48
49 use 5.6.0;
50 use File::Basename;
51 use File::Path;
52 use IPC::Open3;
53 use Irssi 20021107.0841;
54 use Irssi::TextUI;
55 use locale;
56 use POSIX;
57 use re 'eval';
58 use strict;
59 use Tie::File;
60 use vars qw($VERSION %IRSSI);
61
62 $VERSION = '2.4.3';
63 #$VERSION = '2.4.3 SVN ($LastChangedRevision: 273 $)';
64 %IRSSI = (
65 authors => 'Clemens Heidinger',
66 changed => '$LastChangedDate: 2008-02-03 16:27:25 +0100 (Sun, 03 Feb 2008) $',
67 commands => 'dau',
68 contact => 'heidinger@dau.pl',
69 description => 'write like an idiot',
70 license => 'BSD',
71 modules => 'File::Basename File::Path IPC::Open3 POSIX Tie::File',
72 name => 'DAU',
73 sbitems => 'daumode',
74 url => 'http://dau.pl/',
75 );
76
77 ################################################################################
78 # Register commands
79 ################################################################################
80
81 Irssi::command_bind('dau', \&command_dau);
82
83 ################################################################################
84 # Register settings
85 # setting changed/added => change/add it here
86 ################################################################################
87
88 # boolean
89 Irssi::settings_add_bool('misc', 'dau_away_quote_reason', 1);
90 Irssi::settings_add_bool('misc', 'dau_away_reminder', 0);
91 Irssi::settings_add_bool('misc', 'dau_babble_verbose', 1);
92 Irssi::settings_add_bool('misc', 'dau_color_choose_colors_randomly', 1);
93 Irssi::settings_add_bool('misc', 'dau_cowsay_print_cow', 0);
94 Irssi::settings_add_bool('misc', 'dau_figlet_print_font', 0);
95 Irssi::settings_add_bool('misc', 'dau_silence', 0);
96 Irssi::settings_add_bool('misc', 'dau_statusbar_daumode_hide_when_off', 0);
97 Irssi::settings_add_bool('misc', 'dau_tab_completion', 1);
98
99 # Integer
100 Irssi::settings_add_int('misc', 'dau_babble_history_size', 10);
101 Irssi::settings_add_int('misc', 'dau_babble_verbose_minimum_lines', 2);
102 Irssi::settings_add_int('misc', 'dau_cool_maximum_line', 2);
103 Irssi::settings_add_int('misc', 'dau_cool_probability_eol', 20);
104 Irssi::settings_add_int('misc', 'dau_cool_probability_word', 20);
105 Irssi::settings_add_int('misc', 'dau_remote_babble_interval_accuracy', 90);
106
107 # String
108 Irssi::settings_add_str('misc', 'dau_away_away_text', '$N is away now: [ $reason ]. Away since: $Z. I am currently not available at $T @ $chatnet (sry 4 amsg)!');
109 Irssi::settings_add_str('misc', 'dau_away_back_text', '$N is back: [ $reason ]. Away time: [ $time ]. I am available again at $T @ $chatnet (sry 4 amsg)!');
110 Irssi::settings_add_str('misc', 'dau_away_options',
111 "--parse_special --bracket -left '!---?[' -right ']?---!' --color -split capitals -random off -codes 'light red; yellow'," .
112 "--parse_special --bracket -left '--==||{{' -right '}}||==--' --color -split capitals -random off -codes 'light red; light cyan'," .
113 "--parse_special --bracket -left '--==||[[' -right ']]||==--' --color -split capitals -random off -codes 'yellow; light green'"
114 );
115 Irssi::settings_add_str('misc', 'dau_away_reminder_interval', '1 hour');
116 Irssi::settings_add_str('misc', 'dau_away_reminder_text', '$N is still away: [ $reason ]. Away time: [ $time ] (sry 4 amsg)');
117 Irssi::settings_add_str('misc', 'dau_babble_options_line_by_line', '--nothing');
118 Irssi::settings_add_str('misc', 'dau_babble_options_preprocessing', '');
119 Irssi::settings_add_str('misc', 'dau_color_codes', 'blue; green; red; magenta; yellow; cyan');
120 Irssi::settings_add_str('misc', 'dau_cool_eol_style', 'random');
121 Irssi::settings_add_str('misc', 'dau_cowsay_cowlist', '');
122 Irssi::settings_add_str('misc', 'dau_cowsay_cowpath', &def_dau_cowsay_cowpath);
123 Irssi::settings_add_str('misc', 'dau_cowsay_cowpolicy', 'allow');
124 Irssi::settings_add_str('misc', 'dau_cowsay_cowsay_path', &def_dau_cowsay_cowsay_path);
125 Irssi::settings_add_str('misc', 'dau_cowsay_cowthink_path', &def_dau_cowsay_cowthink_path);
126 Irssi::settings_add_str('misc', 'dau_daumode_channels', '');
127 Irssi::settings_add_str('misc', 'dau_delimiter_string', ' ');
128 Irssi::settings_add_str('misc', 'dau_figlet_fontlist', 'mnemonic,term,ivrit');
129 Irssi::settings_add_str('misc', 'dau_figlet_fontpath', &def_dau_figlet_fontpath);
130 Irssi::settings_add_str('misc', 'dau_figlet_fontpolicy', 'allow');
131 Irssi::settings_add_str('misc', 'dau_figlet_path', &def_dau_figlet_path);
132 Irssi::settings_add_str('misc', 'dau_files_away', '.away');
133 Irssi::settings_add_str('misc', 'dau_files_babble_messages', 'babble_messages');
134 Irssi::settings_add_str('misc', 'dau_files_cool_suffixes', 'cool_suffixes');
135 Irssi::settings_add_str('misc', 'dau_files_root_directory', "$ENV{HOME}/.dau");
136 Irssi::settings_add_str('misc', 'dau_files_substitute', 'substitute.pl');
137 Irssi::settings_add_str('misc', 'dau_language', 'en');
138 Irssi::settings_add_str('misc', 'dau_moron_eol_style', 'random');
139 Irssi::settings_add_str('misc', 'dau_parse_special_list_delimiter', ' ');
140 Irssi::settings_add_str('misc', 'dau_random_options',
141 '--substitute --boxes --uppercase,' .
142 "--substitute --color -split capitals -random off -codes 'light red; yellow'," .
143 "--substitute --color -split capitals -random off -codes 'light red; light cyan'," .
144 "--substitute --color -split capitals -random off -codes 'yellow; light green'," .
145 '--substitute --color --uppercase,' .
146 '--substitute --cool,' .
147 '--substitute --delimiter,' .
148 '--substitute --dots --moron,' .
149 '--substitute --leet,' .
150 '--substitute --mix,' .
151 '--substitute --mixedcase --bracket,' .
152 '--substitute --moron --stutter --uppercase,' .
153 '--substitute --moron -omega on,' .
154 '--substitute --moron,' .
155 '--substitute --uppercase --underline,' .
156 '--substitute --words --mixedcase'
157 );
158 Irssi::settings_add_str('misc', 'dau_remote_babble_channellist', '');
159 Irssi::settings_add_str('misc', 'dau_remote_babble_channelpolicy', 'deny');
160 Irssi::settings_add_str('misc', 'dau_remote_babble_interval', '1 hour');
161 Irssi::settings_add_str('misc', 'dau_remote_channellist', '');
162 Irssi::settings_add_str('misc', 'dau_remote_channelpolicy', 'deny');
163 Irssi::settings_add_str('misc', 'dau_remote_deop_reply', 'you are on my shitlist now @ $nick');
164 Irssi::settings_add_str('misc', 'dau_remote_devoice_reply', 'you are on my shitlist now @ $nick');
165 Irssi::settings_add_str('misc', 'dau_remote_op_reply', 'thx 4 op @ $nick');
166 Irssi::settings_add_str('misc', 'dau_remote_permissions', '000000');
167 Irssi::settings_add_str('misc', 'dau_remote_question_regexp', '%%%DISABLED%%%');
168 Irssi::settings_add_str('misc', 'dau_remote_question_reply', 'EDIT_THIS_ONE');
169 Irssi::settings_add_str('misc', 'dau_remote_voice_reply', 'thx 4 voice @ $nick');
170 Irssi::settings_add_str('misc', 'dau_standard_messages', 'hi @ all');
171 Irssi::settings_add_str('misc', 'dau_standard_options', '--random');
172 Irssi::settings_add_str('misc', 'dau_words_range', '1-4');
173
174 ################################################################################
175 # Register signals
176 # (Note that most signals are set dynamical in the subroutine signal_handling)
177 ################################################################################
178
179 Irssi::signal_add_last('setup changed', \&signal_setup_changed);
180 Irssi::signal_add_last('window changed' => sub { Irssi::statusbar_items_redraw('daumode') });
181 Irssi::signal_add_last('window item changed' => sub { Irssi::statusbar_items_redraw('daumode') });
182
183 ################################################################################
184 # Register statusbar items
185 ################################################################################
186
187 Irssi::statusbar_item_register('daumode', '', 'statusbar_daumode');
188
189 ################################################################################
190 # Global variables
191 ################################################################################
192
193 # Timer used by --away
194
195 our %away_timer;
196
197 # babble
198
199 our %babble;
200
201 # --command -in
202
203 our $command_in;
204
205 # The command to use for the output (MSG f.e.)
206
207 our $command_out;
208
209 # '--command -out' used?
210
211 our $command_out_activated;
212
213 # Counter for the subroutines entered
214
215 our $counter_subroutines;
216
217 # Counter for the switches
218 # --me --moron: --me would be 0, --moron 1
219
220 our $counter_switches;
221
222 # daumode
223
224 our %daumode;
225
226 # daumode activated?
227
228 our $daumode_activated;
229
230 # Help text
231
232 our %help;
233 $help{options} = <<END;
234 %9--away%9
235 Toggle away mode
236
237 %9-channels%9 %U'#channel1/network1, #channel2/network2, ...'%U:
238 Say away message in all those %Uchannels%U
239
240 %9-interval%9 %Utime%U:
241 Remind channel now and then that you're away
242
243 %9-reminder%9 %Uon|off%U:
244 Turn reminder on or off
245
246 %9--babble%9
247 Babble a message.
248
249 %9-at%9 %Unicks%U:
250 Comma separated list of nicks to babble at.
251 \$nick1, \$nick2 and so forth of the babble line will be replaced
252 by those nicks.
253
254 %9-cancel%9 %Uon|off%U:
255 Cancel active babble
256
257 %9-filter%9 %Uregular expression%U:
258 Only let through if the babble matches the %Uregular expression%U
259
260 %9-history_size%9 %Un%U:
261 Set the size of the history for this one babble to %Un%U
262
263 %9--boxes%9
264 Put words in boxes
265
266 %9--bracket%9
267 Bracket the text
268
269 %9-left%9 %Ustring%U:
270 Left bracket
271
272 %9-right%9 %Ustring%U:
273 Right bracket
274
275 %9--changelog%9
276 Print the changelog
277
278 %9--chars%9
279 Only one character each line
280
281 %9--color%9
282 Write in colors
283
284 %9-codes%9 %Ucodes%U:
285 Overrides setting dau_color_codes
286
287 %9-random%9 %Uon|off%U:
288 Choose color randomly from setting dau_color_codes resp.
289 %9--color -codes%9 or take one by one in the exact order given.
290
291 %9-split%9
292 %Ucapitals%U: Split by capitals
293 %Uchars%U: Every character another color
294 %Ulines%U: Every line another color
295 %Uparagraph%U: The whole paragraph in one color
296 %Urchars%U: Some characters one color
297 %Uwords%U: Every word another color
298
299 %9--command%9
300 %9-in%9 %Ucommand%U:
301 Feed dau.pl with the output (the public message)
302 that %Ucommand%U produces
303
304 %9-out%9 %Ucommand%U:
305 %Utopic%U for example will set a dauified topic
306
307 %9--cool%9
308 Be \$cool[tm]!!!!11one
309
310 %9-eol_style%9 %Ustring%U:
311 Override setting dau_cool_eol_style
312
313 %9-max%9 %Un%U:
314 \$Trademarke[tm] only %Un%U words per line tops
315
316 %9-prob_eol%9 %U0-100%U:
317 Probability that "!!!11one" or something like that will be put at EOL.
318 Set it to 100 and every line will be.
319 Set it to 0 and no line will be.
320
321 %9-prob_word%9 %U0-100%U:
322 Probability that a word will be \$trademarked[tm].
323 Set it to 100 and every word will be.
324 Set it to 0 and no word will be.
325
326 %9--cowsay%9
327 Use cowsay to write
328
329 %9-arguments%9 %Uarguments%U:
330 Pass any option to cowsay, f.e. %U'-b'%U or %U'-e XX'%U.
331 Look in the cowsay manualpage for details.
332
333 %9-cow%9 %Ucow%U:
334 The cow to use
335
336 %9-think%9 %Uon|off%U:
337 Thinking instead of speaking
338
339 %9--create_files%9
340 Create files and directories of all dau_files_* settings
341
342 %9--daumode%9
343 Toggle daumode.
344 Works on a per channel basis!
345
346 %9-modes_in%9 %Umodes%U:
347 All incoming messages will be dauified and the
348 specified modes are used by dau.pl.
349
350 %9-modes_out%9 %Umodes%U:
351 All outgoing messages will be dauified and the
352 specified modes are used by dau.pl.
353
354 %9-perm%9 %U[01][01]%U:
355 Dauify incoming/outgoing messages?
356
357 %9--delimiter%9
358 Insert a delimiter-string after each character
359
360 %9-string%9 %Ustring%U:
361 Override setting dau_delimiter_string. If this string
362 contains whitespace, you should quote the string with
363 single quotes.
364
365 %9--dots%9
366 Put dots... after words...
367
368 %9--figlet%9
369 Use figlet to write
370
371 %9-font%9 %Ufont%U:
372 The font to use
373
374 %9--help%9
375 Print help
376
377 %9-setting%9 %Usetting%U:
378 More information about a specific setting
379
380 %9--leet%9
381 Write in leet speech
382
383 %9--long_help%9
384 Long help, i.e. examples, more about some features, ...
385
386 %9--me%9
387 Send a CTCP ACTION instead of a PRIVMSG
388
389 %9--mix%9
390 Mix all the characters in a word except for the first and last
391
392 %9--mixedcase%9
393 Write in mixed case
394
395 %9--moron%9
396 Write in uppercase, mix in some typos, perform some
397 substitutions on the text, ... Just write like a
398 moron
399
400 %9-eol_style%9 %Ustring%U:
401 Override setting dau_moron_eol_style
402
403 %9-level%9 %Un%U:
404 %Un%U gives the level of stupidity applied to text,
405 the higher the stupider.
406 %U0%U is the minimum, %U1%U currently only implemented for dau_language = de.
407
408 %9-omega%9 %Uon|off%U:
409 The fantastic omega mode
410
411 %9-typo%9 %Uon|off%U:
412 Mix in random typos
413
414 %9-uppercase%9 %Uon|off%U:
415 Uppercase text
416
417 %9--nothing%9
418 Do nothing
419
420 %9--parse_special%9
421 Parse for special metasequences and substitute them.
422
423 %9-irssi_variables%9 %Uon|off%U:
424 Parse irssi special variables like \$N
425
426 %9-list_delimiter%9 %Ustring%U:
427 Set the list delimiter used for \@nicks and \@opnicks to %Ustring%U.
428
429 The special metasequences are:
430
431 - \\n:
432 real newline
433 - \$nick1 .. \$nickN:
434 N different randomly selected nicks
435 - \@nicks:
436 All nicks in channel
437 - \$opnick1 .. \$opnickN:
438 N different randomly selected opnicks
439 - \@opnicks:
440 All nicks in channel with operator status
441 - \$?{ code }:
442 the (perl)code will be evaluated and the last expression
443 returned will replace that metasequence
444 - irssis special variables like \$C for the current
445 channel and \$N for your current nick
446
447 Quoting:
448
449 - \\\$: literal \$
450 - \\\\: literal \\
451
452 %9--random%9
453 Let dau.pl choose the options randomly. Get these options from the setting
454 dau_random_options.
455
456 %9-verbose%9 %Uon|off%U:
457 Print what options --random has chosen
458
459 %9--reverse%9
460 Reverse the input string
461
462 %9--stutter%9
463 Stutter a bit
464
465 %9--substitute%9
466 Apply own substitutions from file
467
468 %9--underline%9
469 Underline text
470
471 %9--uppercase%9
472 Write in upper case
473
474 %9--words%9
475 Only a few words each line
476 END
477
478 # Containing irssi's 'cmdchars'
479
480 our $k = Irssi::parse_special('$k');
481
482 # Remember your nick mode
483
484 our %nick_mode;
485
486 # All the options
487
488 our %option;
489
490 # print() the message or not?
491
492 our $print_message;
493
494 # Queue holding the switches
495
496 our %queue;
497
498 # Remember the last switches used by --random so that they don't repeat
499
500 our $random_last;
501
502 # Signals
503
504 our %signal = (
505 'complete word' => 0,
506 'daumode in' => 0,
507 'event 404' => 0,
508 'event privmsg' => 0,
509 'nick mode changed' => 0,
510 'send text' => 0,
511 );
512
513 # All switches that may be given at commandline
514
515 our %switches = (
516
517 # These switches may be combined
518
519 combo => {
520 boxes => { 'sub' => \&switch_boxes },
521 bracket => {
522 'sub' => \&switch_bracket,
523 left => { '*' => 1 },
524 right => { '*' => 1 },
525 },
526 chars => { 'sub' => \&switch_chars },
527 color => {
528 'sub' => \&switch_color,
529 codes => { '*' => 1 },
530 random => {
531 off => 1,
532 on => 1,
533 },
534 'split' => {
535 capitals => 1,
536 chars => 1,
537 lines => 1,
538 paragraph => 1,
539 rchars => 1,
540 words => 1,
541 },
542 },
543 command => {
544 'sub' => \&switch_command,
545 in => { '*' => 1 },
546 out => { '*' => 1 },
547 },
548 cool => {
549 'sub' => \&switch_cool,
550 eol_style => {
551 suffixes => 1,
552 exclamation_marks => 1,
553 random => 1,
554 },
555 max => { '*' => 1 },
556 prob_eol => { '*' => 1 },
557 prob_word => { '*' => 1 },
558 },
559 cowsay => {
560 'sub' => \&switch_cowsay,
561 arguments => { '*' => 1 },
562 think => {
563 off => 1,
564 on => 1,
565 },
566 },
567 delimiter => {
568 'sub' => \&switch_delimiter,
569 string => { '*' => 1 },
570 },
571 dots => { 'sub' => \&switch_dots },
572 figlet => { 'sub' => \&switch_figlet },
573 me => { 'sub' => \&switch_me },
574 mix => { 'sub' => \&switch_mix },
575 moron => {
576 'sub' => \&switch_moron,
577 eol_style => {
578 nothing => 1,
579 random => 1,
580 },
581 level => { '*' => 1 },
582 omega => {
583 off => 1,
584 on => 1,
585 },
586 typo => {
587 off => 1,
588 on => 1,
589 },
590 uppercase => {
591 off => 1,
592 on => 1,
593 },
594 },
595 leet => { 'sub' => \&switch_leet },
596 mixedcase => { 'sub' => \&switch_mixedcase },
597 nothing => { 'sub' => \&switch_nothing },
598 parse_special => {
599 'sub' => \&switch_parse_special,
600 irssi_variables => {
601 off => 1,
602 on => 1,
603 },
604 list_delimiter => { '*' => 1 },
605 },
606 'reverse' => { 'sub' => \&switch_reverse },
607 stutter => { 'sub' => \&switch_stutter },
608 substitute => { 'sub' => \&switch_substitute },
609 underline => { 'sub' => \&switch_underline },
610 uppercase => { 'sub' => \&switch_uppercase },
611 words => { 'sub' => \&switch_words },
612 },
613
614 # The following switches must not be combined
615
616 nocombo => {
617 away => {
618 'sub' => \&switch_away,
619 channels => { '*' => 1 },
620 interval => { '*' => 1 },
621 reminder => {
622 on => 1,
623 off => 1,
624 },
625 },
626 babble => {
627 'sub' => \&switch_babble,
628 at => { '*' => 1 },
629 cancel => {
630 on => 1,
631 off => 1,
632 },
633 filter => { '*' => 1 },
634 history_size => { '*' => 1 },
635 },
636 changelog => { 'sub' => \&switch_changelog },
637 create_files => { 'sub' => \&switch_create_files },
638 daumode => {
639 'sub' => \&switch_daumode,
640 modes_in => { '*' => 1 },
641 modes_out => { '*' => 1 },
642 perm => {
643 '00' => 1,
644 '01' => 1,
645 '10' => 1,
646 '11' => 1,
647 },
648 },
649 help => {
650 'sub' => \&switch_help,
651
652 # setting changed/added => change/add it here
653
654 setting => {
655 # boolean
656 dau_away_quote_reason => 1,
657 dau_away_reminder => 1,
658 dau_babble_verbose => 1,
659 dau_color_choose_colors_randomly => 1,
660 dau_cowsay_print_cow => 1,
661 dau_figlet_print_font => 1,
662 dau_silence => 1,
663 dau_statusbar_daumode_hide_when_off => 1,
664 dau_tab_completion => 1,
665
666 # Integer
667 dau_babble_history_size => 1,
668 dau_babble_verbose_minimum_lines => 1,
669 dau_cool_maximum_line => 1,
670 dau_cool_probability_eol => 1,
671 dau_cool_probability_word => 1,
672 dau_remote_babble_interval_accuracy => 1,
673
674 # String
675 dau_away_away_text => 1,
676 dau_away_back_text => 1,
677 dau_away_options => 1,
678 dau_away_reminder_interval => 1,
679 dau_away_reminder_text => 1,
680 dau_babble_options_line_by_line => 1,
681 dau_babble_options_preprocessing => 1,
682 dau_color_codes => 1,
683 dau_cool_eol_style => 1,
684 dau_cowsay_cowlist => 1,
685 dau_cowsay_cowpath => 1,
686 dau_cowsay_cowpolicy => 1,
687 dau_cowsay_cowsay_path => 1,
688 dau_cowsay_cowthink_path => 1,
689 dau_daumode_channels => 1,
690 dau_delimiter_string => 1,
691 dau_figlet_fontlist => 1,
692 dau_figlet_fontpath => 1,
693 dau_figlet_fontpolicy => 1,
694 dau_figlet_path => 1,
695 dau_files_away => 1,
696 dau_files_babble_messages => 1,
697 dau_files_cool_suffixes => 1,
698 dau_files_root_directory => 1,
699 dau_files_substitute => 1,
700 dau_language => 1,
701 dau_moron_eol_style => 1,
702 dau_parse_special_list_delimiter => 1,
703 dau_random_options => 1,
704 dau_remote_babble_channellist => 1,
705 dau_remote_babble_channelpolicy => 1,
706 dau_remote_babble_interval => 1,
707 dau_remote_channellist => 1,
708 dau_remote_channelpolicy => 1,
709 dau_remote_deop_reply => 1,
710 dau_remote_devoice_reply => 1,
711 dau_remote_op_reply => 1,
712 dau_remote_permissions => 1,
713 dau_remote_question_regexp => 1,
714 dau_remote_question_reply => 1,
715 dau_remote_voice_reply => 1,
716 dau_standard_messages => 1,
717 dau_standard_options => 1,
718 dau_words_range => 1,
719 },
720 },
721 long_help => { 'sub' => \&switch_long_help },
722 random => { 'sub' => \&switch_random,
723 verbose => {
724 off => 1,
725 on => 1,
726 },
727 },
728 },
729 );
730
731 ################################################################################
732 # Code run once at start
733 ################################################################################
734
735 print CLIENTCRAP "dau.pl $VERSION loaded. For help type %9${k}dau --help%9 or %9${k}dau --long_help%9";
736
737 signal_setup_changed();
738 build_nick_mode_struct();
739 signal_handling();
740
741 ################################################################################
742 # Subroutines (commands)
743 ################################################################################
744
745 sub command_dau {
746 my ($data, $server, $witem) = @_;
747 my $output;
748
749 $output = parse_text($data, $witem);
750
751 unless (defined($server) && $server && $server->{connected}) {
752 $print_message = 1;
753 }
754 unless ((defined($witem) && $witem &&
755 ($witem->{type} eq 'CHANNEL' || $witem->{type} eq 'QUERY')))
756 {
757 $print_message = 1;
758 }
759
760 if ($daumode_activated) {
761
762 if (defined($witem) && $witem &&
763 ($witem->{type} eq 'CHANNEL' || $witem->{type} eq 'QUERY'))
764 {
765 my $modes_set = 0;
766
767 # daumode set with parameters (modes_in)
768
769 if ($queue{0}{daumode}{modes_in}) {
770 $daumode{channels_in}{$server->{tag}}{$witem->{name}} = 1;
771 $daumode{channels_in_modes}{$server->{tag}}{$witem->{name}} =
772 $queue{0}{daumode}{modes_in};
773 $modes_set = 1;
774 }
775
776 # daumode set with parameters (modes_out)
777
778 if ($queue{0}{daumode}{modes_out}) {
779 $daumode{channels_out}{$server->{tag}}{$witem->{name}} = 1;
780 $daumode{channels_out_modes}{$server->{tag}}{$witem->{name}} =
781 $queue{0}{daumode}{modes_out};
782 $modes_set = 1;
783 }
784
785 # daumode set without parameters
786
787 if (!$daumode{channels_in}{$server->{tag}}{$witem->{name}} &&
788 !$daumode{channels_out}{$server->{tag}}{$witem->{name}} &&
789 !$modes_set)
790 {
791 $daumode{channels_in}{$server->{tag}}{$witem->{name}} = 1;
792 $daumode{channels_out}{$server->{tag}}{$witem->{name}} = 1;
793 $daumode{channels_in_modes}{$server->{tag}}{$witem->{name}} = '';
794 $daumode{channels_out_modes}{$server->{tag}}{$witem->{name}} = '';
795 }
796
797 # daumode unset
798
799 elsif (($daumode{channels_in}{$server->{tag}}{$witem->{name}} ||
800 $daumode{channels_out}{$server->{tag}}{$witem->{name}}) &&
801 !$modes_set)
802 {
803 $daumode{channels_in}{$server->{tag}}{$witem->{name}} = 0;
804 $daumode{channels_out}{$server->{tag}}{$witem->{name}} = 0;
805 $daumode{channels_in_modes}{$server->{tag}}{$witem->{name}} = '';
806 $daumode{channels_out_modes}{$server->{tag}}{$witem->{name}} = '';
807 }
808
809
810 # the perm-option overrides everything
811
812 # perm: 00
813
814 if ($queue{0}{daumode}{perm} eq '00') {
815 $daumode{channels_in}{$server->{tag}}{$witem->{name}} = 0;
816 $daumode{channels_out}{$server->{tag}}{$witem->{name}} = 0;
817 $daumode{channels_in_modes}{$server->{tag}}{$witem->{name}} = '';
818 $daumode{channels_out_modes}{$server->{tag}}{$witem->{name}} = '';
819 }
820
821 # perm: 01
822
823 if ($queue{0}{daumode}{perm} eq '01') {
824 $daumode{channels_in}{$server->{tag}}{$witem->{name}} = 0;
825 $daumode{channels_out}{$server->{tag}}{$witem->{name}} = 1;
826 $daumode{channels_in_modes}{$server->{tag}}{$witem->{name}} = '';
827 }
828
829 # perm: 10
830
831 if ($queue{0}{daumode}{perm} eq '10') {
832 $daumode{channels_in}{$server->{tag}}{$witem->{name}} = 1;
833 $daumode{channels_out}{$server->{tag}}{$witem->{name}} = 0;
834 $daumode{channels_out_modes}{$server->{tag}}{$witem->{name}} = '';
835 }
836
837 # perm: 11
838
839 if ($queue{0}{daumode}{perm} eq '11') {
840 $daumode{channels_in}{$server->{tag}}{$witem->{name}} = 1;
841 $daumode{channels_out}{$server->{tag}}{$witem->{name}} = 1;
842 }
843
844 Irssi::statusbar_items_redraw('daumode');
845 }
846
847 # Signal handling (for daumode and signal 'send text')
848
849 signal_handling();
850
851 return;
852 }
853
854 # MSG (or CTCP ACTION) $output to active channel/query-window
855
856 {
857 no strict 'refs';
858
859 $output = $output || '';
860 output_text($witem, $witem->{name}, $output);
861 }
862 }
863
864 ################################################################################
865 # Subroutines (switches, must not be combined)
866 ################################################################################
867
868 sub switch_away {
869 my ($reason, $channel_rec, $reminder, $interval) = @_;
870 my $output;
871 my $time;
872 my $status = 'away';
873
874 ################################################################################
875 ################################################################################
876 # Get and handle options
877 ################################################################################
878 ################################################################################
879
880 ################################################################################
881 # "/dau --away -interval <interval>" resp. dau_away_reminder_interval setting
882 ################################################################################
883
884 # If called from command line, i.e. not by the
885 # "/dau --away -channels '<channels>'" workaround, $interval will be defined
886 # here
887 if (!defined($interval)) {
888 $interval = time_parse(return_option('away', 'interval', $option{dau_away_reminder_interval}));
889 }
890 if ($interval < 10 || $interval > 1000000000) {
891 print_err('Invalid value for away timer!');
892 return;
893 }
894
895 ################################################################################
896 # setting dau_away_options
897 ################################################################################
898
899 my $options = return_random_list_item($option{dau_away_options});
900
901 ################################################################################
902 # "/dau --away -reminder <on|off>" resp. dau_away_reminder setting
903 ################################################################################
904
905 # If called from command line, i.e. not by "/dau --away -channels '<channels>'"
906 # workaround, $reminder will be defined here
907 if (!defined($reminder)) {
908 $reminder = return_option('away', 'reminder', $option{dau_away_reminder});
909 }
910
911 # on -> 1, off -> 0
912 if ($reminder eq 'on' || $reminder == 1) {
913 $reminder = 1;
914 } else {
915 $reminder = 0;
916 }
917
918 ################################################################################
919 # "/dau --away -channels '<channels>'"
920 ################################################################################
921
922 # Go through all channels and for each call this subroutine again with
923 # $reminder and $interval as additional parameter as those otherwise would be
924 # lost. Sad world.
925
926 my $channels = return_option('away', 'channels');
927 # If not deleted, the program may loop here.
928 undef($queue{0}{away}{channels});
929 while ($channels =~ m{([^/]+)/([^,]+),?\s*}g) {
930 my $channel = $1;
931 my $network = $2;
932
933 my $server_rec = Irssi::server_find_tag($network);
934 my $channel_rec = $server_rec->channel_find($channel);
935
936 if (defined($channel_rec) && $channel_rec &&
937 ($channel_rec->{type} eq 'CHANNEL' || $channel_rec->{type} eq 'QUERY'))
938 {
939 switch_away($reason, $channel_rec, $reminder, $interval);
940 }
941
942 }
943 # "/dau --away -channels '<channels>'" first run => exit
944 return if ($channels);
945
946 ################################################################################
947 # Now we are clear (from -channels)...
948 ################################################################################
949
950 # Normal "/dau --away" (i.e. no -channels), but called from non
951 # channel/query window => exit
952 unless (defined($channel_rec) && $channel_rec &&
953 ($channel_rec->{type} eq 'CHANNEL' || $channel_rec->{type} eq 'QUERY'))
954 {
955 return;
956 }
957
958 my $channel = $channel_rec->{name};
959 my $network = $channel_rec->{server}->{tag};
960 my $id = "$channel/$network";
961
962 ################################################################################
963 # Open file
964 ################################################################################
965
966 my $file = "$option{dau_files_root_directory}/$option{dau_files_away}";
967 my @file;
968 unless (tie(@file, 'Tie::File', $file)) {
969 print_err("Cannot tie $file!");
970 return;
971 }
972
973 ################################################################################
974 # Go through/edit file
975 ################################################################################
976
977 # Format:
978 # channel | network | time | options | reminder | interval | reason
979 my $i = 0;
980 foreach my $line (@file) {
981 if ($line =~ m{^\Q$channel\E\x02\Q$network\E\x02(\d+)\x02([^\x02]*)\x02(?:\d)\x02(?:\d+)\x02(.*)}) {
982 $time = $1;
983 $options = $2;
984 $reason = $3;
985 $status = 'back';
986 last;
987 }
988 $i++;
989 }
990
991 if ($status eq 'away' && $reason eq '') {
992 print_out('Please set reason for your being away!');
993 return;
994 }
995
996 if ($status eq 'away') {
997 push(@file, "$channel\x02$network\x02" . time . "\x02$options\x02$reminder\x02$interval\x02$reason");
998 $output = $option{dau_away_away_text};
999 }
1000
1001 if ($status eq 'back') {
1002 splice(@file, $i, 1);
1003 $output = $option{dau_away_back_text};
1004 }
1005
1006 ################################################################################
1007 # Special variables
1008 ################################################################################
1009
1010 # $time
1011
1012 if ($status eq 'back') {
1013 my $difference = time_diff_verbose(time, $time);
1014 $output =~ s/\$time/$difference/g;
1015 }
1016
1017 # $reason
1018
1019 if ($option{dau_away_quote_reason}) {
1020 $reason =~ s/\\/\\\\/g;
1021 $reason =~ s/\$/\\\$/g;
1022 }
1023 $output =~ s/\$reason/$reason/g;
1024
1025 ################################################################################
1026 # Write changes back to file
1027 ################################################################################
1028
1029 untie(@file);
1030
1031 ################################################################################
1032 # The reminder timer
1033 ################################################################################
1034
1035 if ($status eq 'away' && $reminder) {
1036 $away_timer{$id} = Irssi::timeout_add($interval, \&timer_away_reminder, $id);
1037 } else {
1038 Irssi::timeout_remove($away_timer{$id});
1039 }
1040
1041 ################################################################################
1042 # Print message to channel
1043 ################################################################################
1044
1045 $output = parse_text("$options $output", $channel_rec);
1046 output_text($channel_rec, $channel_rec->{name}, $output);
1047
1048 return;
1049 }
1050
1051 sub switch_babble {
1052 my ($data, $channel) = @_;
1053 my $text;
1054
1055 # Cancel babble?
1056
1057 if (lc(return_option('babble', 'cancel')) eq 'on') {
1058 if (defined($babble{timer_writing})) {
1059 Irssi::timeout_remove($babble{timer_writing});
1060 undef($babble{timer_writing});
1061
1062 if ($babble{remote}) {
1063 timer_remote_babble_reset();
1064 }
1065
1066 print_out("Babble cancelled.");
1067 }
1068 return;
1069 }
1070
1071 # Filters
1072
1073 my @filter = ();
1074 my $option_babble_at = return_option('babble', 'at');
1075 my $option_babble_filter = return_option('babble', 'filter');
1076 my $option_babble_history_size = return_option('babble', 'history_size', $option{dau_babble_history_size});
1077
1078 if ($option_babble_filter) {
1079 push(@filter, $option_babble_filter);
1080 }
1081
1082 # If something is babbling right now, exit
1083
1084 if (defined($babble{timer_writing})) {
1085 print_err("You are already babbling something!");
1086 return;
1087 }
1088
1089 # get text from file
1090
1091 if ($option_babble_at) {
1092 my @nicks;
1093 foreach my $nick (split(/\s*,\s*/, $option_babble_at)) {
1094 push(@nicks, $nick);
1095 }
1096 if (@nicks > 0) {
1097 for (my $i = 1; $i <= $#nicks + 1; $i++) {
1098 push(@filter, '\$nick' . $i);
1099 }
1100 }
1101
1102 $text = &babble_get_text($channel, \@filter, \@nicks, $option_babble_history_size);
1103 } else {
1104 $text = &babble_get_text($channel, \@filter, undef, $option_babble_history_size);
1105 }
1106
1107 # babble only in channels
1108
1109 unless (defined($channel) && $channel && $channel->{type} eq 'CHANNEL') {
1110 print_out('%9--babble%9 will only work in channel windows!');
1111 return;
1112 }
1113
1114 # Start the babbling
1115
1116 babble_start($channel, $text, 0);
1117
1118 return;
1119 }
1120
1121 sub switch_changelog {
1122 my $output;
1123 $print_message = 1;
1124
1125 $output = &fix(<<" END");
1126 CHANGELOG
1127
1128 2002-05-05 release 0.1.0
1129 initial release
1130
1131 2002-05-06 release 0.1.1
1132 maintenance release
1133
1134 2002-05-11 release 0.2.0
1135 new feature: %9--delimiter%9
1136
1137 2002-05-12 release 0.3.0
1138 new feature: %9--mixedcase%9
1139
1140 2002-05-17 release 0.4.0
1141 %9--delimiter%9 revised
1142
1143 2002-05-20 release 0.4.1
1144 some nice new substitutions for %9--moron%9
1145
1146 2002-05-24 release 0.5.0
1147 new settings for %9--figlet%9
1148
1149 2002-06-15 release 0.6.0
1150 new settings for %9--figlet%9
1151
1152 2002-06-16 release 0.6.1
1153 maintenance release
1154
1155 2002-06-16 release 0.6.2
1156 maintenance release
1157
1158 2002-06-17 release 0.7.0
1159 new stuff for %9--moron%9
1160
1161 2002-06-19 release 0.8.0
1162 new feature: %9--dots%9
1163
1164 2002-06-23 release 0.9.0
1165 new "reply to question" remote feature
1166
1167 2002-06-23 release 0.9.1
1168 maintenance release
1169
1170 2002-06-29 release 0.9.2
1171 maintenance release
1172
1173 2002-07-23 release 0.9.3
1174 maintenance release
1175
1176 2002-07-28 release 1.0.0
1177 - Tabcompletion for the switches
1178 - new feature: %9--changelog%9
1179 - new feature: %9--help%9
1180 - new feature: %9--leet%9
1181 - new feature: %9--reverse%9
1182
1183 2002-07-28 release 1.0.1
1184 maintenance release
1185
1186 2002-09-01 release 1.0.2
1187 maintenance release
1188
1189 2002-09-03 release 1.0.3
1190 new switch for %9--figlet%9: %9-font%9
1191
1192 2002-09-03 release 1.0.4
1193 maintenance release
1194
1195 2002-09-03 release 1.0.5
1196 maintenance release
1197
1198 2002-09-09 release 1.1.0
1199 You can combine switches now!
1200
1201 2002-11-22 release 1.2.0
1202 - new setting: %9dau_moron_eol_style%9
1203 - new setting: %9dau_standard_messages%9
1204 - new setting: %9dau_standard_options%9
1205 - new remote features: Say something on (de)op/(de)voice
1206 - new switch for %9--delimiter%9: %9-string%9
1207 - new switch for %9--moron%9: %9-eol_style%9
1208 - new feature: %9--color%9
1209 - new feature: %9--daumode%9
1210 - new feature: %9--random%9
1211 - new feature: %9--stutter%9
1212 - new feature: %9--uppercase%9
1213 - new statusbar item: %9daumode%9
1214
1215 2002-11-27 release 1.2.1
1216 maintenance release
1217
1218 2002-12-15 release 1.2.2
1219 maintenance release
1220
1221 2003-01-12 release 1.3.0
1222 - new setting: %9dau_files_root_directory%9
1223 - %9--moron%9: randomly transpose letters with letters
1224 next to them at the keyboard
1225 - new switch for %9--moron%9: %9-uppercase%9
1226 - new feature: %9--create_files%9
1227
1228 2003-01-17 release 1.4.0
1229 - %9--color%9 revised
1230 - new remote feature: babble
1231
1232 2003-01-18 release 1.4.1
1233 maintenance release
1234
1235 2003-01-20 release 1.4.2
1236 new setting: %9dau_statusbar_daumode_hide_when_off%9
1237
1238 2003-02-01 release 1.4.3
1239 maintenance release
1240
1241 2003-02-09 release 1.4.4
1242 maintenance release
1243
1244 2003-02-16 release 1.4.5
1245 maintenance release
1246
1247 2003-03-16 release 1.4.6
1248 maintenance release
1249
1250 2003-05-01 release 1.5.0
1251 - new setting: %9dau_tab_completion%9
1252 - new feature: %9--bracket%9
1253
1254 2003-06-13 release 1.5.1
1255 new feature: %9--underline%9
1256
1257 2003-07-16 release 1.5.2
1258 new feature: %9--boxes%9
1259
1260 2003-08-16 release 1.5.3
1261 maintenance release
1262
1263 2003-09-14 release 1.5.4
1264 maintenance release
1265
1266 2003-11-16 release 1.6.0
1267 - Incoming messages can be dauified now!
1268 - daumode statusbar item revised
1269
1270 2004-03-25 release 1.7.0
1271 - new setting: %9dau_babble_options_line_by_line%9
1272 - new setting: %9dau_files_babble_messages%9
1273 - new switch for %9--color%9: %9-split paragraph%9
1274 - new switch for %9--command%9: %9-in%9
1275 - new switch for %9--moron%9: %9-omega%9
1276 - new feature: %9--cowsay%9
1277 - new feature: %9--mix%9 (by Martin Kihlgren <zond\@troja.ath.cx>)
1278
1279 2004-04-01 release 1.7.1
1280 - new setting: %9dau_remote_babble_channellist%9
1281 - new setting: %9dau_remote_babble_channelpolicy%9
1282 - new setting: %9dau_remote_babble_interval_accuracy%9
1283
1284 2004-04-02 release 1.7.2
1285 maintenance release
1286
1287 2004-04-05 release 1.7.3
1288 maintenance release
1289
1290 2004-05-01 release 1.8.0
1291 - new feature: %9--babble%9
1292 - %9--help%9 revised
1293
1294 2004-06-24 release 1.8.1
1295 - new setting: %9dau_babble_verbose%9
1296 - new setting: %9dau_babble_verbose_minimum_lines%9
1297
1298 2004-07-10 release 1.8.2
1299 maintenance release
1300
1301 2004-07-25 release 1.8.3
1302 maintenance release
1303
1304 2004-09-14 release 1.8.4
1305 maintenance release
1306
1307 2004-10-18 release 1.8.5
1308 maintenance release
1309
1310 2004-11-07 release 1.8.6
1311 maintenance release
1312
1313 2005-01-28 release 1.9.0
1314 - new setting: %9dau_cowsay_cowthink_path%9
1315 - new switch for %9--cowsay%9: %9-arguments%9
1316 - new switch for %9--cowsay%9: %9-think%9
1317
1318 2005-06-05 release 2.0.0
1319 - new setting: %9dau_color_choose_colors_randomly%9
1320 - new setting: %9dau_color_codes%9
1321 - new setting: %9dau_language%9
1322 - new setting: %9dau_remote_question_regexp%9
1323 - new switch for %9--bracket%9: %9-left%9
1324 - new switch for %9--bracket%9: %9-right%9
1325 - new switch for %9--color%9: %9-codes%9
1326 - new switch for %9--color%9: %9-random%9
1327 - new switch for %9--color%9: %9-split capitals%9
1328 - new feature: %9--away%9
1329 - new feature: %9--cool%9
1330 - new feature: %9--long_help%9
1331 - new feature: %9--parse_special%9
1332
1333 2005-07-01 release 2.1.0
1334 - new switch for %9--babble%9: %9-at%9
1335 - %9--color%9: Support for background colors
1336 - %9--color -codes%9: You may use now the color names
1337 instead of the numeric color codes
1338
1339 2005-07-24 release 2.1.1
1340 maintenance release
1341
1342 2005-08-02 release 2.1.2
1343 maintenance release
1344
1345 2005-11-01 release 2.1.3
1346 maintenance release
1347
1348 2006-03-11 release 2.1.4
1349 maintenance release
1350
1351 2006-05-21 release 2.1.5
1352 new switch for %9--babble%9: %9-filter%9
1353
1354 2006-10-25 release 2.1.6
1355 new switch for %9--babble%9: %9-cancel%9
1356
1357 2006-11-25 release 2.2.0
1358 new feature: %9--substitute%9
1359
1360 2007-03-07 release 2.3.0
1361 - new setting: %9dau_daumode_channels%9
1362 - new switch for %9--moron%9: %9-level%9
1363 - new switch for %9--moron%9: %9-typo%9
1364 - new switch for %9--random%9: %9-verbose%9
1365
1366 2007-03-08 release 2.3.1
1367 maintenance release
1368
1369 2007-03-11 release 2.3.2
1370 maintenance release
1371
1372 2007-03-18 release 2.3.3
1373 maintenance release
1374
1375 2007-06-02 release 2.4.0
1376 - new setting: %9dau_babble_history_size%9
1377 - new switch for %9--babble%9: %9-history_size%9
1378
1379 2007-06-26 release 2.4.1
1380 maintenance release
1381
1382 2007-10-11 release 2.4.2
1383 maintenance release
1384
1385 2008-02-03 release 2.4.3
1386 maintenance release
1387 END
1388
1389 return $output;
1390 }
1391
1392 sub switch_create_files {
1393
1394 # create directory dau_files_root_directory if not found
1395
1396 if (-f $option{dau_files_root_directory}) {
1397 print_err("$option{dau_files_root_directory} is a _file_ => aborting");
1398 return;
1399 }
1400 if (-d $option{dau_files_root_directory}) {
1401 print_out('directory dau_files_root_directory already exists - no need to create it');
1402 } else {
1403 if (mkpath([$option{dau_files_root_directory}])) {
1404 print_out("creating directory $option{dau_files_root_directory}/");
1405 } else {
1406 print_err("failed creating directory $option{dau_files_root_directory}/");
1407 }
1408 }
1409
1410 # create file dau_files_substitute if not found
1411
1412 my $file1 = "$option{dau_files_root_directory}/$option{dau_files_substitute}";
1413
1414 if (-e $file1) {
1415
1416 print_out("file $file1 already exists - no need to create it");
1417
1418 } else {
1419
1420 if (open(FH1, "> $file1")) {
1421
1422 print FH1 &fix(<<' END');
1423 # dau.pl - http://dau.pl/
1424 #
1425 # This is the file --moron will use for your own substitutions.
1426 # You can use any perlcode in here.
1427 # $_ contains the text you can work with.
1428 # $_ has to contain the data to be returned to dau.pl at the end.
1429 END
1430
1431 print_out("$file1 created. you should edit it now!");
1432
1433 } else {
1434
1435 print_err("cannot write $file1: $!");
1436
1437 }
1438
1439 if (!close(FH1)) {
1440 print_err("cannot close $file1: $!");
1441 }
1442 }
1443
1444 # create file dau_files_babble_messages if not found
1445
1446 my $file2 = "$option{dau_files_root_directory}/$option{dau_files_babble_messages}";
1447
1448 if (-e $file2) {
1449
1450 print_out("file $file2 already exists - no need to create it");
1451
1452 } else {
1453
1454 if (open(FH1, "> $file2")) {
1455
1456 print FH1 &fix(<<' END');
1457 END
1458
1459 print_out("$file2 created. you should edit it now!");
1460
1461 } else {
1462
1463 print_err("cannot write $file2: $!");
1464
1465 }
1466
1467 if (!close(FH1)) {
1468 print_err("cannot close $file2: $!");
1469 }
1470 }
1471
1472 # create file dau_files_cool_suffixes if not found
1473
1474 my $file3 = "$option{dau_files_root_directory}/$option{dau_files_cool_suffixes}";
1475
1476 if (-e $file3) {
1477
1478 print_out("file $file3 already exists - no need to create it");
1479
1480 } else {
1481
1482 if (open(FH1, "> $file3")) {
1483
1484 print FH1 &fix(<<' END');
1485 END
1486
1487 print_out("$file3 created. you should edit it now!");
1488
1489 } else {
1490
1491 print_err("cannot write $file3: $!");
1492
1493 }
1494
1495 if (!close(FH1)) {
1496 print_err("cannot close $file3: $!");
1497 }
1498 }
1499
1500 return;
1501 }
1502
1503 sub switch_daumode {
1504 $daumode_activated = 1;
1505 }
1506
1507 sub switch_help {
1508 my $output;
1509 my $option_setting = return_option('help', 'setting');
1510 $print_message = 1;
1511
1512 if ($option_setting eq '') {
1513 $output = &fix(<<" END");
1514 %9OPTIONS%9
1515
1516 $help{options}
1517 END
1518 }
1519
1520 # setting changed/added => change/add them below
1521
1522 # boolean
1523
1524 elsif ($option_setting eq 'dau_away_quote_reason') {
1525 $output = &fix(<<" END");
1526 %9dau_away_quote_reason%9 %Ubool
1527
1528 If turned on, %9--parse_special%9 will not be able to replace
1529 variables which probably aren't one anyway.
1530 END
1531 }
1532 elsif ($option_setting eq 'dau_away_reminder') {
1533 $output = &fix(<<" END");
1534 %9dau_away_reminder%9 %Ubool
1535
1536 Turn the reminder message of %9--away%9 on or off.
1537 END
1538 }
1539 elsif ($option_setting eq 'dau_babble_verbose') {
1540 $output = &fix(<<" END");
1541 %9dau_babble_verbose%9 %Ubool
1542
1543 Before babbling print a message how many lines will be babbled and
1544 when finished a notification message.
1545 END
1546 }
1547 elsif ($option_setting eq 'dau_color_choose_colors_randomly') {
1548 $output = &fix(<<" END");
1549 %9dau_color_choose_colors_randomly%9 %Ubool
1550
1551 Choose colors randomly from setting dau_color_codes resp.
1552 %9--color -codes%9 or take one by one in the exact order given.
1553 END
1554 }
1555 elsif ($option_setting eq 'dau_cowsay_print_cow') {
1556 $output = &fix(<<" END");
1557 %9dau_cowsay_print_cow%9 %Ubool
1558
1559 Print a message which cow will be used.
1560 END
1561 }
1562 elsif ($option_setting eq 'dau_figlet_print_font') {
1563 $output = &fix(<<" END");
1564 %9dau_figlet_print_font%9 %Ubool
1565
1566 Print a message which font will be used.
1567 END
1568 }
1569 elsif ($option_setting eq 'dau_silence') {
1570 $output = &fix(<<" END");
1571 %9dau_silence%9 %Ubool
1572
1573 Don't print any information message. This does not include
1574 error messages.
1575 END
1576 }
1577 elsif ($option_setting eq 'dau_statusbar_daumode_hide_when_off') {
1578 $output = &fix(<<" END");
1579 %9dau_statusbar_daumode_hide_when_off%9 %Ubool
1580
1581 Hide statusbar item when daumode is turned off.
1582 END
1583 }
1584 elsif ($option_setting eq 'dau_tab_completion') {
1585 $output = &fix(<<" END");
1586 %9dau_tab_completion%9 %Ubool
1587
1588 Perhaps someone wants to disable TAB completion for the
1589 ${k}dau-command because he/she doesn't like it or wants
1590 to give the CPU a break (don't know whether it has much
1591 influence)
1592 END
1593 }
1594
1595 # Integer
1596
1597 elsif ($option_setting eq 'dau_babble_history_size') {
1598 $output = &fix(<<" END");
1599 %9dau_babble_history_size%9 %Uinteger
1600
1601 Number of lines to store in the babble history.
1602 dau.pl will babble no line the history is holding.
1603 END
1604 }
1605 elsif ($option_setting eq 'dau_babble_verbose_minimum_lines') {
1606 $output = &fix(<<" END");
1607 %9dau_babble_verbose_minimum_lines%9 %Uinteger
1608
1609 Minimum lines necessary to produce the output of the verbose
1610 information.
1611 END
1612 }
1613 elsif ($option_setting eq 'dau_cool_maximum_line') {
1614 $output = &fix(<<" END");
1615 %9dau_cool_maximum_line%9 %Uinteger
1616
1617 Trademarke[tm] or do \$this only %Un%U words per line tops.
1618 END
1619 }
1620 elsif ($option_setting eq 'dau_cool_probability_eol') {
1621 $output = &fix(<<" END");
1622 %9dau_cool_probability_eol%9 %Uinteger
1623
1624 Probability that "!!!11one" or something like that will be put at EOL.
1625 Set it to 100 and every line will be.
1626 Set it to 0 and no line will be.
1627 END
1628 }
1629 elsif ($option_setting eq 'dau_cool_probability_word') {
1630 $output = &fix(<<" END");
1631 %9dau_cool_probability_word%9 %Uinteger
1632
1633 Probability that a word will be trademarked[tm].
1634 Set it to 100 and every word will be.
1635 Set it to 0 and no word will be.
1636 END
1637 }
1638 elsif ($option_setting eq 'dau_remote_babble_interval_accuracy') {
1639 $output = &fix(<<" END");
1640 %9dau_remote_babble_interval_accuracy%9 %Uinteger
1641
1642 Value expressed as a percentage how accurate the timer of
1643 the babble feature should be.
1644
1645 Legal values: 1-100
1646
1647 %U100%U would result in a very accurate timer.
1648 END
1649 }
1650
1651 # String
1652
1653 elsif ($option_setting eq 'dau_away_away_text') {
1654 $output = &fix(<<" END");
1655 %9dau_away_away_text%9 %Ustring
1656
1657 The text to say when using %9--away%9.
1658
1659 Special Variables:
1660
1661 \$reason: Your away reason.
1662 END
1663 }
1664 elsif ($option_setting eq 'dau_away_back_text') {
1665 $output = &fix(<<" END");
1666 %9dau_away_back_text%9 %Ustring
1667
1668 The text to say when you return.
1669
1670 Special Variables:
1671
1672 \$reason: Your away reason.
1673 \$time: The time you've been away.
1674 END
1675 }
1676 elsif ($option_setting eq 'dau_away_reminder_interval') {
1677 $output = &fix(<<" END");
1678 %9dau_away_reminder_interval%9 %Ustring
1679
1680 Remind the channel that you're away! Repeat the message
1681 in the given interval.
1682 END
1683 }
1684 elsif ($option_setting eq 'dau_away_reminder_text') {
1685 $output = &fix(<<" END");
1686 %9dau_away_reminder_text%9 %Ustring
1687
1688 The text to say when you remind the channel that you're away.
1689
1690 Special Variables:
1691
1692 \$reason: Your away reason.
1693 \$time: The time you've been away.
1694 END
1695 }
1696 elsif ($option_setting eq 'dau_away_options') {
1697 $output = &fix(<<" END");
1698 %9dau_away_options%9 %Ustring
1699
1700 Options %9--away%9 will use.
1701 END
1702 }
1703 elsif ($option_setting eq 'dau_babble_options_line_by_line') {
1704 $output = &fix(<<" END");
1705 %9dau_babble_options_line_by_line%9 %Ustring
1706
1707 One single babble may contain several lines. The options
1708 specified in this setting are used for every line.
1709 END
1710 }
1711 elsif ($option_setting eq 'dau_babble_options_preprocessing') {
1712 $output = &fix(<<" END");
1713 %9dau_babble_options_preprocessing%9 %Ustring
1714
1715 The options specified in this setting are applied to the
1716 whole babble before anything else. Later, the options of
1717 the setting %9dau_babble_options_line_by_line%9 are
1718 applied to every line of the babble.
1719 END
1720 }
1721 elsif ($option_setting eq 'dau_color_codes') {
1722 $output = &fix(<<" END");
1723 %9dau_color_codes%9 %Ustring
1724
1725 Specify the color codes to use, seperated by semicolons.
1726 Example: %Ugreen; red; blue%U. You may use the color code (one
1727 or two digits) or the color names. So either
1728 %U2%U or %Ublue%U is ok. You can set a background color too:
1729 %Ured,green%U and you will write with red on a green
1730 background.
1731 For a complete list of the color codes and names look at
1732 formats.txt in the irssi documentation.
1733 END
1734 }
1735 elsif ($option_setting eq 'dau_cool_eol_style') {
1736 $output = &fix(<<" END");
1737 %9dau_cool_eol_style%9 %Ustring
1738
1739 %Uexclamation_marks%U: !!!11one
1740 %Urandom%U: Choose one style randomly
1741 %Usuffixes%U: Suffixes from file
1742 END
1743 }
1744 elsif ($option_setting eq 'dau_cowsay_cowlist') {
1745 $output = &fix(<<" END");
1746 %9dau_cowsay_cowlist%9 %Ustring
1747
1748 Comma separated list of cows. Checkout
1749 %9${k}dau --help -setting dau_cowsay_cowpolicy%9
1750 to see what this setting is good for.
1751 END
1752 }
1753 elsif ($option_setting eq 'dau_cowsay_cowpath') {
1754 $output = &fix(<<" END");
1755 %9dau_cowsay_cowpath%9 %Ustring
1756
1757 Path to the cowsay-cows (*.cow).
1758 END
1759 }
1760 elsif ($option_setting eq 'dau_cowsay_cowpolicy') {
1761 $output = &fix(<<" END");
1762 %9dau_cowsay_cowpolicy%9 %Ustring
1763
1764 Specifies the policy used to handle the cows in
1765 dau_cowsay_cowpath. If set to %Uallow%U, all cows available
1766 will be used by the command. You can exclude some cows by
1767 setting dau_cowsay_cowlist. If set to %Udeny%U, no cows but
1768 the ones listed in dau_cowsay_cowlist will be used by the
1769 command. Useful if you have many annoying cows in your
1770 cowpath and you want to permit only a few of them.
1771 END
1772 }
1773 elsif ($option_setting eq 'dau_cowsay_cowsay_path') {
1774 $output = &fix(<<" END");
1775 %9dau_cowsay_cowsay_path%9 %Ustring
1776
1777 Should point to the cowsay executable.
1778 END
1779 }
1780 elsif ($option_setting eq 'dau_cowsay_cowthink_path') {
1781 $output = &fix(<<" END");
1782 %9dau_cowsay_cowthink_path%9 %Ustring
1783
1784 Should point to the cowthink executable.
1785 END
1786 }
1787 elsif ($option_setting eq 'dau_daumode_channels') {
1788 $output = &fix(<<" END");
1789 %9dau_daumode_channels%9 %U<channel>/<network>:<switches>, ...%U
1790
1791 Automatically enable the daumode for some channels.
1792 %U#foo/bar:-modes_out '--substitute'%U would automatically
1793 set the daumode on #foo in network bar to modify outgoing
1794 messages with --substitute.
1795 END
1796 }
1797 elsif ($option_setting eq 'dau_delimiter_string') {
1798 $output = &fix(<<" END");
1799 %9dau_delimiter_string%9 %Ustring
1800
1801 Tell %9--delimiter%9 which delimiter to use.
1802 END
1803 }
1804 elsif ($option_setting eq 'dau_figlet_fontlist') {
1805 $output = &fix(<<" END");
1806 %9dau_figlet_fontlist%9 %Ustring
1807
1808 Comma separated list of fonts. Checkout
1809 %9${k}dau --help -setting dau_figlet_fontpolicy%9
1810 to see what this setting is good for. Use the program
1811 `showfigfonts` shipped with figlet to find these fonts.
1812 END
1813 }
1814 elsif ($option_setting eq 'dau_figlet_fontpath') {
1815 $output = &fix(<<" END");
1816 %9dau_figlet_fontpath%9 %Ustring
1817
1818 Path to the figlet-fonts (*.flf).
1819 END
1820 }
1821 elsif ($option_setting eq 'dau_figlet_fontpolicy') {
1822 $output = &fix(<<" END");
1823 %9dau_figlet_fontpolicy%9 %Ustring
1824
1825 Specifies the policy used to handle the fonts in
1826 dau_figlet_fontpath. If set to %Uallow%U, all fonts available
1827 will be used by the command. You can exclude some fonts by
1828 setting dau_figlet_fontlist. If set to %Udeny%U, no fonts but
1829 the ones listed in dau_figlet_fontlist will be used by the
1830 command. Useful if you have many annoying fonts in your
1831 fontpath and you want to permit only a few of them.
1832 END
1833 }
1834 elsif ($option_setting eq 'dau_figlet_path') {
1835 $output = &fix(<<" END");
1836 %9dau_figlet_path%9 %Ustring
1837
1838 Should point to the figlet executable.
1839 END
1840 }
1841 elsif ($option_setting eq 'dau_files_away') {
1842 $output = &fix(<<" END");
1843 %9dau_files_away%9 %Ustring
1844
1845 The file with the away messages.
1846 _Must_ be in dau_files_root_directory.
1847 END
1848 }
1849 elsif ($option_setting eq 'dau_files_babble_messages') {
1850 $output = &fix(<<" END");
1851 %9dau_files_babble_messages%9 %Ustring
1852
1853 The file with the babble messages.
1854 _Must_ be in dau_files_root_directory.
1855 %9${k}dau --create_files%9 will create it.
1856
1857 Format of the file: Newline separated plain text.
1858 The text will be sent through %9--parse_special%9 as well.
1859 END
1860 }
1861 elsif ($option_setting eq 'dau_files_cool_suffixes') {
1862 $output = &fix(<<" END");
1863 %9dau_files_cool_suffixes%9 %Ustring
1864
1865 %9--cool%9 takes randomly one line out of this file
1866 and puts it at the end of the line.
1867 This file _must_ be in dau_files_root_directory.
1868 %9${k}dau --create_files%9 will create it.
1869
1870 Format of the file: Newline separated plain text.
1871 END
1872 }
1873 elsif ($option_setting eq 'dau_files_root_directory') {
1874 $output = &fix(<<" END");
1875 %9dau_files_root_directory%9 %Ustring
1876
1877 Directory in which all files for dau.pl will be stored.
1878 %9${k}dau --create_files%9 will create it.
1879 END
1880 }
1881 elsif ($option_setting eq 'dau_files_substitute') {
1882 $output = &fix(<<" END");
1883 %9dau_files_substitute%9 %Ustring
1884
1885 Your own substitutions file. _Must_ be in
1886 dau_files_root_directory.
1887 %9${k}dau --create_files%9 will create it.
1888 END
1889 }
1890 elsif ($option_setting eq 'dau_language') {
1891 $output = &fix(<<" END");
1892 %9dau_language%9 %Ustring
1893
1894 %Ude%U: If you are writing in german
1895 %Uen%U: If you are writing in english
1896 END
1897 }
1898 elsif ($option_setting eq 'dau_moron_eol_style') {
1899 $output = &fix(<<" END");
1900 %9dau_moron_eol_style%9 %Ustring
1901
1902 What to do at End Of Line?
1903
1904 %Urandom%U:
1905 - !!!??!!!!!????!??????????!!!1
1906 - =
1907 ?
1908 - ?¿?
1909 %Unothing%U: do nothing
1910 END
1911 }
1912 elsif ($option_setting eq 'dau_parse_special_list_delimiter') {
1913 $output = &fix(<<" END");
1914 %9dau_parse_special_list_delimiter%9 %Ustring
1915
1916 Set the list delimiter used for \@nicks and \@opnicks to %Ustring%U.
1917 END
1918 }
1919 elsif ($option_setting eq 'dau_random_options') {
1920 $output = &fix(<<" END");
1921 %9dau_random_options%9 %Ustring
1922
1923 Comma separated list of options %9--random%9 will use. It will
1924 take randomly one item of the list. If you set it f.e. to
1925 %U--uppercase --color,--mixedcase%U,
1926 the probability of printing a colored, uppercased string hello
1927 will be 50% as well as the probabilty of printing a mixedcased
1928 string hello when typing %9${k}dau --random hello%9.
1929 END
1930 }
1931 elsif ($option_setting eq 'dau_remote_babble_channellist') {
1932 $output = &fix(<<" END");
1933 %9dau_remote_babble_channellist%9 %Ustring
1934
1935 Comma separated list of channels. You'll have to specify the
1936 ircnet too.
1937 Format: #channel1/IRCNet,#channel2/EFnet
1938 END
1939 }
1940 elsif ($option_setting eq 'dau_remote_babble_channelpolicy') {
1941 $output = &fix(<<" END");
1942 %9dau_remote_babble_channelpolicy%9 %Ustring
1943
1944 Using the default policy %Udeny%U the script won't do anything
1945 except in the channels listed in dau_remote_babble_channellist.
1946 Using the policy %Uallow%U the script will babble in all
1947 channels but the ones listed in dau_remote_babble_channellist.
1948 END
1949 }
1950 elsif ($option_setting eq 'dau_remote_babble_interval') {
1951 $output = &fix(<<" END");
1952 %9dau_remote_babble_interval%9 %Ustring
1953
1954 dau.pl will babble text in the given interval.
1955 END
1956 }
1957 elsif ($option_setting eq 'dau_remote_channellist') {
1958 $output = &fix(<<" END");
1959 %9dau_remote_channellist%9 %Ustring
1960
1961 Comma separated list of channels. You'll have to specify the
1962 ircnet too.
1963 Format: #channel1/IRCNet,#channel2/EFnet
1964 END
1965 }
1966 elsif ($option_setting eq 'dau_remote_channelpolicy') {
1967 $output = &fix(<<" END");
1968 %9dau_remote_channelpolicy%9 %Ustring
1969
1970 Using the default policy %Udeny%U the script won't do anything
1971 except in the channels listed in dau_remote_channellist. Using
1972 the policy %Uallow%U the script will reply to all channels but
1973 the ones listed in dau_remote_channellist.
1974 END
1975 }
1976 elsif ($option_setting eq 'dau_remote_deop_reply') {
1977 $output = &fix(<<" END");
1978 %9dau_remote_deop_reply%9 %Ustring
1979
1980 Comma separated list of messages (it will take randomly one
1981 item of the list) sent to channel if someone deops you (mode
1982 change -o).
1983 The string given will be processed by the same subroutine
1984 parsing the %9${k}dau%9 command.
1985
1986 Special Variables:
1987
1988 \$nick: contains the nick of the one who changed the mode
1989 END
1990 }
1991 elsif ($option_setting eq 'dau_remote_devoice_reply') {
1992 $output = &fix(<<" END");
1993 %9dau_remote_devoice_reply%9 %Ustring
1994
1995 Comma separated list of messages (it will take randomly one
1996 item of the list) sent to channel if someone devoices you (mode
1997 change -v).
1998 The string given will be processed by the same subroutine
1999 parsing the %9${k}dau%9 command.
2000
2001 Special Variables:
2002
2003 \$nick: contains the nick of the one who changed the mode
2004 END
2005 }
2006 elsif ($option_setting eq 'dau_remote_op_reply') {
2007 $output = &fix(<<" END");
2008 %9dau_remote_op_reply%9 %Ustring
2009
2010 Comma separated list of messages (it will take randomly one
2011 item of the list) sent to channel if someone ops you (mode
2012 change +o).
2013 The string given will be processed by the same subroutine
2014 parsing the %9${k}dau%9 command.
2015
2016 Special Variables:
2017
2018 \$nick: contains the nick of the one who changed the mode
2019 END
2020 }
2021 elsif ($option_setting eq 'dau_remote_permissions') {
2022 $output = &fix(<<" END");
2023 %9dau_remote_permissions%9 %U[01][01][01][01][01][01]
2024
2025 Permit or forbid the remote features.
2026
2027 First Bit:
2028 Reply to question
2029
2030 Second Bit:
2031 If someone gives you voice in a channel, thank him!
2032
2033 Third Bit:
2034 If someone gives you op in a channel, thank him!
2035
2036 Fourth Bit:
2037 If devoiced, print message
2038
2039 Fifth Bit:
2040 If deopped, print message
2041
2042 Sixth Bit:
2043 Babble text in certain intervals
2044 END
2045 }
2046 elsif ($option_setting eq 'dau_remote_question_regexp') {
2047 $output = &fix(<<" END");
2048 %9dau_remote_question_regexp%9 %Ustring
2049
2050 If someone says something matching that regular expression,
2051 act accordingly.
2052 The regexp will be sent through %9--parse_special%9.
2053 Because of that you will have to escape some characters, f.e.
2054 \\s to \\\\s for whitespace.
2055 END
2056 }
2057 elsif ($option_setting eq 'dau_remote_question_reply') {
2058 $output = &fix(<<" END");
2059 %9dau_remote_question_reply%9 %Ustring
2060
2061 Comma separated list of reply strings for the question of
2062 setting dau_remote_question_regexp (it will randomly choose one
2063 item of the list).
2064 The string given will be processed by the same subroutine
2065 parsing the %9${k}dau%9 command.
2066
2067 Special Variables:
2068
2069 \$nick: contains the nick of the one who sent the message to which
2070 dau.pl reacts
2071 END
2072 }
2073 elsif ($option_setting eq 'dau_remote_voice_reply') {
2074 $output = &fix(<<" END");
2075 %9dau_remote_voice_reply%9 %Ustring
2076
2077 Comma separated list of messages (it will take randomly one
2078 item of the list) sent to channel if someone voices you (mode
2079 change +v).
2080 The string given will be processed by the same subroutine
2081 parsing the %9${k}dau%9 command.
2082
2083 Special Variables:
2084
2085 \$nick: contains the nick of the one who changed the mode
2086 END
2087 }
2088 elsif ($option_setting eq 'dau_standard_messages') {
2089 $output = &fix(<<" END");
2090 %9dau_standard_messages%9 %Ustring
2091
2092 Comma separated list of strings %9${k}dau%9 will use if the user
2093 omits the text on the commandline.
2094 END
2095 }
2096 elsif ($option_setting eq 'dau_standard_options') {
2097 $output = &fix(<<" END");
2098 %9dau_standard_options%9 %Ustring
2099
2100 Options %9${k}dau%9 will use if the user omits them on the commandline.
2101 END
2102 }
2103 elsif ($option_setting eq 'dau_words_range') {
2104 $output = &fix(<<" END");
2105 %9dau_words_range%9 %Ui-j
2106
2107 Setup the range howmany words the command should write per line.
2108 1 <= i <= j <= 9; i, j element { 1, ... , 9 }. If i == j the command
2109 will write i words to the active window. Else it takes a random
2110 number k (element { i, ... , j }) and writes k words per
2111 line.
2112 END
2113 }
2114
2115 return $output;
2116 }
2117
2118 sub switch_long_help {
2119 my $output;
2120 $print_message = 1;
2121
2122 $output = &fix(<<" END");
2123 %9SYNOPSIS%9
2124
2125 %9${k}dau [%Uoptions%U] [%Utext%U%9]
2126
2127 %9DESCRIPTION%9
2128
2129 dau? What does that mean? It's a german acronym for %9d%9ümmster
2130 %9a%9nzunehmender %9u%9ser. In english: stupidest imaginable user.
2131
2132 With dau.pl every person can write like an idiot on the IRC!
2133
2134 %9OPTIONS%9
2135
2136 $help{options}
2137 %9EXAMPLES%9
2138
2139 %9${k}dau --uppercase --mixedcase %Ufoo bar baz%9
2140 Will write %Ufoo bar baz%U in mixed case.
2141 %Ufoo bar baz%U is sent _first_ to %9--uppercase%9, _then_ to
2142 %9--mixedcase%9.
2143 The order in which you put the options on the commandline is
2144 important!
2145 You can see what output a command produces without sending it to
2146 the active channel/query by sending it to a non-channel/query
2147 window.
2148
2149 %9${k}dau --color --figlet %Ufoo bar baz%9
2150 %9--color%9 is the first to be run and thus color codes will
2151 be inserted.
2152 The string will look like %U\\00302f\\00303o[...]%U when leaving
2153 %9--color%9.
2154 %9--figlet%9 uses then that string as its input.
2155 So you'll have finally an output like
2156 %U02f03o[...]%U in the figlet letters.
2157 You'll probably want to use %9--figlet --color%9 instead.
2158
2159 %9SPECIAL FEATURES%9
2160
2161 %9Combine the options%9
2162 You can combine most of the options! So you can write colored
2163 leet messages f.e.. Look in the EXAMPLES section above.
2164
2165 %9Babble%9
2166 dau.pl will babble text for you. It can do this on its own
2167 in certain intervals or forced by the user using %9--babble%9.
2168
2169 Related settings:
2170
2171 %9dau_babble_options_line_by_line%9
2172 %9dau_files_babble_messages%9
2173 %9dau_files_root_directory%9
2174 %9dau_remote_babble_channellist%9
2175 %9dau_remote_babble_channelpolicy%9
2176 %9dau_remote_babble_interval%9
2177 %9dau_remote_babble_interval_accuracy%9
2178 %9dau_remote_permissions%9
2179
2180 Related switches:
2181
2182 %9--babble%9
2183 %9--create_files%9
2184
2185 %9Daumode%9
2186 Dauify incoming and/or outgoing messages.
2187
2188 There is a statusbar item available displaying the current
2189 status of the daumode. Add it with
2190 %9/statusbar <bar> add [-alignment <left|right>] daumode%9
2191 You may customize the look of the statusbar item in the
2192 theme file:
2193
2194 sb_daumode = "{sb daumode I: \$0 (\$1) O: \$2 (\$3)}";
2195
2196 # \$0: will incoming messages be dauified?
2197 # \$1: modes for incoming messages
2198 # \$2: will outgoing messages be dauified?
2199 # \$3: modes for outgoing messages
2200
2201 %9Remote features%9
2202 Don't worry, dau.pl won't do anything automatically unless you
2203 unlock these features!
2204
2205 %9Babble%9
2206 dau.pl will babble text for you in certain intervals.
2207
2208 %9Reply to a question%9
2209 Answer a question as a moron would.
2210
2211 Related settings:
2212
2213 %9dau_remote_channellist%9
2214 %9dau_remote_channelpolicy%9
2215 %9dau_remote_permissions%9
2216 %9dau_remote_question_regexp%9
2217 %9dau_remote_question_reply%9
2218
2219 %9Say something on (de)op/(de)voice%9
2220 Related settings:
2221
2222 %9dau_remote_channellist%9
2223 %9dau_remote_channelpolicy%9
2224 %9dau_remote_deop_reply%9
2225 %9dau_remote_devoice_reply%9
2226 %9dau_remote_op_reply%9
2227 %9dau_remote_permissions%9
2228 %9dau_remote_voice_reply%9
2229
2230 %9TAB Completion%9
2231 There is a really clever TAB Completion included! Since
2232 commands can get very long you definitely want to use it.
2233 It will only complete syntactically correct commands so the
2234 TAB Completion isn't only a time saver, it's a control
2235 instance too. You'll be suprised to see that it even completes
2236 the figlet fonts and cows for cowsay that are available on
2237 your system.
2238
2239 %9Website%9
2240 $IRSSI{url}:
2241 Additional information, DAU.pm, the dauomat and the dauproxy.
2242 END
2243
2244 return $output;
2245 }
2246
2247 sub switch_random {
2248 my ($data, $channel_rec) = @_;
2249 my $output;
2250 my (@options, $opt, $text);
2251
2252 # Push each item of dau_random_options in the @options array.
2253
2254 while ($option{dau_random_options} =~ /\s*([^,]+)\s*,?/g) {
2255 my $item = $1;
2256 push @options, $item;
2257 }
2258
2259 # More than one item in @options. Choose one randomly but exclude
2260 # the last item chosen.
2261
2262 if (@options > 1) {
2263 @options = grep { $_ ne $random_last } @options;
2264 $opt = @options[rand(@options)];
2265 $random_last = $opt;
2266 }
2267
2268 # Exact one item in @options - take that
2269
2270 elsif (@options == 1) {
2271 $opt = $options[0];
2272 $random_last = $opt;
2273 }
2274
2275
2276 # No item in @options - call switch_moron()
2277
2278 else {
2279 $opt = '--moron';
2280 }
2281
2282 # dauify it!
2283
2284 unless (lc(return_option('random', 'verbose')) eq 'off') {
2285 print_out("%9--random%9 has chosen %9$opt%9", $channel_rec);
2286 }
2287 $text .= $opt . ' ' . $data;
2288 $output = parse_text($text, $channel_rec);
2289
2290 return $output;
2291 }
2292
2293 ################################################################################
2294 # Subroutines (switches, may be combined)
2295 ################################################################################
2296
2297 sub switch_boxes {
2298 my $data = shift;
2299
2300 # handling punctuation marks:
2301 # they will be put in their own box later
2302
2303 $data =~ s%(\w+)([,.?!;:]+)%
2304 $1 . ' ' . join(' ', split(//, $2))
2305 %egx;
2306
2307 # separate words (by whitespace) and put them in a box
2308
2309 $data =~ s/(\s*)(\S+)(\s*)/$1\[$2\]$3/g;
2310
2311 return $data;
2312 }
2313
2314 sub switch_bracket {
2315 my $data = shift;
2316 my $output;
2317
2318 my $option_left = return_option('bracket', 'left');
2319 my $option_right = return_option('bracket', 'right');
2320
2321 my %brackets = (
2322 '((' => '))',
2323 '-=(' => ')=-',
2324 '-=[' => ']=-',
2325 '-={' => '}=-',
2326 '-=|(' => ')|=-',
2327 '-=|[' => ']|=-',
2328 '-=|{' => '}|=-',
2329 '.:>' => '<:.',
2330 );
2331
2332 foreach (keys %brackets) {
2333 for my $times (2 .. 3) {
2334 my $pre = $_;
2335 my $post = $brackets{$_};
2336 $pre =~ s/(.)/$1 x $times/eg;
2337 $post =~ s/(.)/$1 x $times/eg;
2338
2339 $brackets{$pre} = $post;
2340 }
2341 }
2342
2343 $brackets{'!---?['} = ']?---!';
2344 $brackets{'(qp=>'} = '<=qp)';
2345 $brackets{'----->'} = '<-----';
2346
2347 my ($left, $right);
2348 if ($option_left && $option_right) {
2349 $left = $option_left;
2350 $right = $option_right;
2351 } else {
2352 $left = (keys(%brackets))[int(rand(keys(%brackets)))];
2353 $right = $brackets{$left};
2354 }
2355
2356 $output = "$left $data $right";
2357
2358 return $output;
2359 }
2360
2361 sub switch_chars {
2362 my $data = shift;
2363 my $output;
2364
2365 foreach my $char (split //, $data) {
2366 $output .= "$char\n";
2367 }
2368 return $output;
2369 }
2370
2371 sub switch_command {
2372 my ($data, $channel_rec) = @_;
2373
2374 # -out <command>
2375
2376 $command_out = return_option('command', 'out');
2377 $command_out_activated = 1;
2378
2379 # -in <command>
2380
2381 $command_in = '';
2382 my $option_command_in = return_option('command', 'in');
2383
2384 if ($option_command_in) {
2385 return unless (defined($channel_rec) && $channel_rec);
2386
2387 # Deactivate daumode for a brief moment
2388 $signal{'send text'} = 0;
2389 Irssi::signal_remove('send text', 'signal_send_text');
2390
2391 # Capture the output
2392 Irssi::signal_add_first('command msg', 'signal_command_msg');
2393 $channel_rec->command("$option_command_in $data");
2394 Irssi::signal_remove('command msg', 'signal_command_msg');
2395
2396 # Reactivate daumode
2397 signal_handling();
2398
2399 return $command_in;
2400 }
2401
2402 return $data;
2403 }
2404
2405 sub switch_color {
2406 my $data = shift;
2407 my (@all_colors, @colors, $output, $split);
2408
2409 ################################################################################
2410 # Hack to support UTF-8
2411 ################################################################################
2412
2413 if (Irssi::settings_get_str('term_charset') =~ /utf-?8/i) {
2414 eval {
2415 require Encode;
2416 $data = Encode::decode("utf-8", $data);
2417 };
2418 }
2419
2420 ################################################################################
2421 # Get options
2422 ################################################################################
2423
2424 my $option_color_split = return_option('color', 'split', 'words');
2425 my $option_color_codes = return_option('color', 'codes', $option{dau_color_codes});
2426 my $option_color_random = return_option('color', 'random', $option{dau_color_choose_colors_randomly});
2427 if ($option_color_random eq 'on' || $option_color_random == 1) {
2428 $option_color_random = 1;
2429 } else {
2430 $option_color_random = 0;
2431 }
2432
2433 ################################################################################
2434 # color name -> color code
2435 ################################################################################
2436
2437 $option_color_codes =~ s/\blight green\b/09/gi;
2438 $option_color_codes =~ s/\bgreen\b/03/gi;
2439 $option_color_codes =~ s/\blight red\b/04/gi;
2440 $option_color_codes =~ s/\bred\b/05/gi;
2441 $option_color_codes =~ s/\blight cyan\b/11/gi;
2442 $option_color_codes =~ s/\bcyan\b/10/gi;
2443 $option_color_codes =~ s/\blight blue\b/12/gi;
2444 $option_color_codes =~ s/\bblue\b/02/gi;
2445 $option_color_codes =~ s/\blight magenta\b/13/gi;
2446 $option_color_codes =~ s/\bmagenta\b/06/gi;
2447 $option_color_codes =~ s/\blight grey\b/15/gi;
2448 $option_color_codes =~ s/\bgrey\b/14/gi;
2449
2450 $option_color_codes =~ s/\bwhite\b/00/gi;
2451 $option_color_codes =~ s/\bblack\b/01/gi;
2452 $option_color_codes =~ s/\borange\b/07/gi;
2453 $option_color_codes =~ s/\byellow\b/08/gi;
2454
2455 ################################################################################
2456 # Produce @all_colors
2457 ################################################################################
2458
2459 # <color code>5 shall be a colored 5
2460
2461 $option_color_codes =~ s/(\d+)/sprintf('%02d', $1)/eg;
2462
2463 # Fill @all_colors and do error checking
2464
2465 my @all_colors = split(/\s*;\s*/, $option_color_codes);
2466 foreach my $code (@all_colors) {
2467 if ($code !~ /^\d+(,\d+)?$/) {
2468 print_err("Incorrect color code '$code'!");
2469 return $data;
2470 }
2471 }
2472 if (@all_colors == 0) {
2473 print_err('No color code found.');
2474 return $data;
2475 }
2476 @colors = @all_colors;
2477
2478 ################################################################################
2479 # "-split capitals"
2480 ################################################################################
2481
2482 if ($option_color_split eq 'capitals') {
2483 $output = $data;
2484 my ($color1, $color2);
2485 if ($option_color_random) {
2486 $color1 = $colors[rand(@colors)];
2487 @colors = grep { $_ ne $color1 } @colors unless (@colors == 1);
2488 $color2 = $colors[rand(@colors)];
2489 } else {
2490 if (@colors == 1) {
2491 $color1 = $color2 = $colors[0];
2492 } else {
2493 $color1 = $colors[0];
2494 $color2 = $colors[1];
2495 }
2496 }
2497
2498 $output =~ s/([[:upper:][:punct:]]+|\b\S)/\003${color1}${1}\003${color2}/g;
2499
2500 # Remove needless color codes
2501 $output =~ s/\003(?:$color1|$color2)( *)\003(?:$color1|$color2)/$1/g;
2502 $output =~ s/\003(?:$color1|$color2)$//;
2503 }
2504
2505 ################################################################################
2506 # Not "-split capitals"
2507 ################################################################################
2508
2509 else {
2510 if ($option_color_split eq 'chars') {
2511 $split = '';
2512 } elsif ($option_color_split eq 'lines') {
2513 $split = "\n";
2514 } elsif ($option_color_split eq 'words') {
2515 $split = '\s+';
2516 } elsif ($option_color_split eq 'rchars') {
2517 $split = '.' x rand(10);
2518 } elsif ($option_color_split eq 'paragraph') {
2519 $split = "\n";
2520 } else {
2521 $split = '\s+';
2522 }
2523
2524 my $i = 0;
2525 my $background = 0;
2526 my $color;
2527 for (split /($split)/, $data) {
2528 if (/^\s*$/) {
2529 $output .= $_;
2530 next;
2531 }
2532 if ($option_color_random) {
2533 $color = $colors[rand(@colors)];
2534
2535 $output .= "\017" if ($background && $color !~ /,/);
2536 $output .= "\003" . $color . $_;
2537
2538 if ($color =~ /,/) {
2539 $background = 1;
2540 } else {
2541 $background = 0;
2542 }
2543
2544 if ($option_color_split eq 'paragraph') {
2545 @colors = ($color);
2546 } else {
2547 @colors = grep { $_ ne $color } @all_colors unless (@all_colors == 1);
2548 }
2549 } else {
2550 $color = $colors[($i++ % ($#colors + 1))];
2551
2552 if ($option_color_split eq 'paragraph') {
2553 $color = $colors[0];
2554 }
2555
2556 $output .= "\017" if ($background && $color !~ /,/);
2557 $output .= "\003" . $color . $_;
2558
2559 if ($color =~ /,/) {
2560 $background = 1;
2561 } else {
2562 $background = 0;
2563 }
2564 }
2565 }
2566 }
2567
2568 return $output;
2569 }
2570
2571 sub switch_cool {
2572 my ($data, $channel) = @_;
2573 my $output;
2574
2575 ################################################################################
2576 # Get the options
2577 ################################################################################
2578
2579 my $option_eol_style = return_option('cool', 'eol_style', $option{dau_cool_eol_style});
2580
2581 my $option_max = return_option('cool', 'max', $option{dau_cool_maximum_line});
2582 if (!defined($option_max) || int($option_max) < 0) {
2583 $option_max = INT_MAX;
2584 }
2585
2586 my $option_prob_eol = return_option('cool', 'prob_eol', $option{dau_cool_probability_eol});
2587 if (!defined($option_prob_eol) || int($option_prob_eol) < 0 || int($option_prob_eol) > 100) {
2588 $option_prob_eol = 20;
2589 }
2590
2591 my $option_prob_word = return_option('cool', 'prob_word', $option{dau_cool_probability_word});
2592 if (!defined($option_prob_word) || int($option_prob_word) < 0 || int($option_prob_word) > 100) {
2593 $option_prob_word = 20;
2594 }
2595
2596 ################################################################################
2597 # Insert the trademarks and dollar signs
2598 ################################################################################
2599
2600 my $max = $option_max;
2601 foreach my $line (split /(\n)/, $data) {
2602 foreach my $word (split /(\s)/, $line) {
2603 if ($max > 0 && (rand(100) <= $option_prob_word) && $word =~ /^(\w+)([[:punct:]])?$/) {
2604 $word = "${1}[tm]${2}";
2605 $max--;
2606 }
2607 if ($max > 0 && (rand(100) <= $option_prob_word) && $word =~ /^(\w+(?:\[tm\])?)([[:punct:]])?$/) {
2608 $word = "\$${1}${2}";
2609 $max--;
2610 }
2611 $output .= $word;
2612 }
2613 $max = $option_max;
2614 }
2615
2616 ################################################################################
2617 # Reversed smileys
2618 ################################################################################
2619
2620 my $hat = '[(<]';
2621 my $eyes = '[:;%]';
2622 my $nose = '[-]';
2623 my $mouth = '[)(><\[\]{}|]';
2624
2625 $output =~ s{($hat?$eyes$nose?$mouth+)}{
2626 # Supposed to be read from the right to the left.
2627 # Therefore reverse all parenthesis characters:
2628
2629 my $tr = $1;
2630 $tr =~ tr/()<>[]\{\}/)(><][\}\{/;
2631
2632 # Reverse the rest
2633
2634 reverse($tr);
2635 }egox;
2636
2637 ################################################################################
2638 # EOL modifications
2639 ################################################################################
2640
2641 my $style = $option_eol_style;
2642 if ($option_eol_style eq 'random') {
2643 if (int(rand(2)) && $output !~ /[?!]$/) {
2644 $style = 'exclamation_marks';
2645 } else {
2646 $style = 'suffixes';
2647 }
2648 }
2649
2650 # If there is no suffixes file, go for the exclamation marks
2651
2652 my $file = "$option{dau_files_root_directory}/$option{dau_files_cool_suffixes}";
2653 unless (-e $file && -r $file && !(-z $file)) {
2654 $style = 'exclamation_marks';
2655 }
2656
2657 # Skip EOL modifications?
2658
2659 if (int(rand(100)) > $option_prob_eol) {
2660 $style = 'none';
2661 }
2662
2663 # Style determined. Act accordingly:
2664
2665 if ($style eq 'exclamation_marks') {
2666 my @eol;
2667 if ($option{dau_language} eq 'de') {
2668 @eol = ("eins", "shifteins", "elf", "hundertelf", "tausendeinhundertundelf");
2669 for (1 .. 5) {
2670 push(@eol, "eins");
2671 push(@eol, "elf");
2672 }
2673 } else {
2674 @eol = ("one", "shiftone", "eleven");
2675 for (1 .. 5) {
2676 push(@eol, "one");
2677 push(@eol, "eleven");
2678 }
2679 }
2680
2681 $output =~ s/\s*([,.?!])*\s*$//;
2682 $output .= '!' x (3 + int(rand(3)));
2683 $output .= '1' x (3 + int(rand(3)));
2684 $output .= $eol[rand(@eol)] x (1 + int(rand(1)));
2685 $output .= $eol[rand(@eol)] x (int(rand(2)));
2686 } elsif ($style eq 'suffixes') {
2687 my $suffix;
2688 if (-e $file && -r $file) {
2689 $/ = "\n";
2690 @ARGV = ($file);
2691 srand;
2692 rand($.) < 1 && ($suffix = switch_parse_special($_, $channel)) while <>;
2693 }
2694 $output =~ s/\s*$//;
2695
2696 if ($output =~ /^\s*$/) {
2697 $output = $suffix;
2698 } else {
2699 $output .= " " . $suffix;
2700 }
2701 }
2702
2703 return $output;
2704 }
2705
2706 sub switch_cowsay {
2707 my $data = shift;
2708 my ($binarypath, $output, @cows, %cow, $cow, @cache1, @cache2);
2709 my $skip = 1;
2710 my $think = return_option('cowsay', 'think');
2711
2712 my $executable_name;
2713 if ($think eq 'on') {
2714 $binarypath = $option{dau_cowsay_cowthink_path};
2715 $executable_name = 'cowthink';
2716 } else {
2717 $binarypath = $option{dau_cowsay_cowsay_path};
2718 $executable_name = 'cowsay';
2719 }
2720
2721 if (-e $binarypath && !(-f $binarypath)) {
2722 print_err("dau_cowsay_${executable_name}_path has to point to the $executable_name executable.");
2723 return;
2724 } elsif (!(-e $binarypath)) {
2725 print_err("$executable_name not found. Install it and set dau_cowsay_${executable_name}_path.");
2726 return;
2727 }
2728
2729 if (return_option('cowsay', 'cow')) {
2730 $cow = return_option('cowsay', 'cow');
2731 } else {
2732 while ($option{dau_cowsay_cowlist} =~ /\s*([^,\s]+)\s*,?/g) {
2733 $cow{$1} = 1;
2734 }
2735 foreach my $cow (keys %{ $switches{combo}{cowsay}{cow} }) {
2736 if (lc($option{dau_cowsay_cowpolicy}) eq 'allow') {
2737 push(@cows, $cow)
2738 unless ($cow{$cow});
2739 } elsif (lc($option{dau_cowsay_cowpolicy}) eq 'deny') {
2740 push(@cows, $cow)
2741 if ($cow{$cow});
2742 } else {
2743 print_err('Invalid value for dau_cowsay_cowpolicy');
2744 return;
2745 }
2746 }
2747 if (@cows == 0) {
2748 print_err('Cannot find any cowsay cow.');
2749 return;
2750 }
2751 $cow = $cows[rand(@cows)];
2752 }
2753
2754 # Run cowsay or cowthink
2755
2756 local(*HIS_IN, *HIS_OUT, *HIS_ERR);
2757 my @arguments;
2758 my $option_arguments = return_option('cowsay', 'arguments');
2759 if ($option_arguments) {
2760 @arguments = split(/ /, $option_arguments);
2761 }
2762 my $childpid = open3(*HIS_IN, *HIS_OUT, *HIS_ERR, $binarypath, '-f', $cow, @arguments);
2763
2764 print HIS_IN $data or return;
2765 close(HIS_IN) or return;
2766
2767 my @errlines = <HIS_ERR>;
2768 my @outlines = <HIS_OUT>;
2769 close(HIS_ERR) or return;
2770 close(HIS_OUT) or return;
2771
2772 waitpid($childpid, 0);
2773 if ($?) {
2774 print_err("That child exited with wait status of $?");
2775 }
2776
2777 # Error during execution? Print errors and return
2778
2779 unless (@errlines == 0) {
2780 print_err('Error during execution of cowsay');
2781 foreach my $line (@errlines) {
2782 print_err($line);
2783 }
2784 return;
2785 }
2786
2787 if ($option{dau_cowsay_print_cow}) {
2788 print_out("Using cowsay cow $cow");
2789 }
2790
2791 foreach (@outlines) {
2792 chomp;
2793 if (/^\s*$/ && $skip) {
2794 next;
2795 } else {
2796 $skip = 0;
2797 }
2798 push(@cache1, $_);
2799 }
2800 $skip = 1;
2801 foreach (reverse @cache1) {
2802 chomp;
2803 if (/^\s*$/ && $skip) {
2804 next;
2805 } else {
2806 $skip = 0;
2807 }
2808 push(@cache2, $_);
2809 }
2810 foreach (reverse @cache2) {
2811 $output .= "$_\n";
2812 }
2813
2814 return $output;
2815 }
2816
2817 sub switch_delimiter {
2818 my $data = shift;
2819 my $output;
2820 my $option_delimiter_string = return_option('delimiter', 'string', $option{dau_delimiter_string});
2821
2822 foreach my $char (split //, $data) {
2823 $output .= $char . $option_delimiter_string;
2824 }
2825 return $output;
2826 }
2827
2828 sub switch_dots {
2829 my $data = shift;
2830
2831 $data =~ s/[.]*\s+/
2832 if (rand(10) < 3) {
2833 (rand(10) >= 5 ? ' ' : '')
2834 .
2835 ('...' . '.' x rand(5))
2836 .
2837 (rand(10) >= 5 ? ' ' : '')
2838 } else { ' ' }
2839 /egox;
2840 rand(10) >= 5 ? $data .= ' ' : 0;
2841 $data .= ('...' . '.' x rand(10));
2842
2843 return $data;
2844 }
2845
2846 sub switch_figlet {
2847 my $data = shift;
2848 my $skip = 1;
2849 my ($output, @fonts, %font, $font, @cache1, @cache2);
2850
2851 if (-e $option{dau_figlet_path} && !(-f $option{dau_figlet_path})) {
2852 print_err('dau_figlet_path has to point to the figlet executable.');
2853 return;
2854 } elsif (!(-e $option{dau_figlet_path})) {
2855 print_err('figlet not found. Install it and set dau_figlet_path.');
2856 return;
2857 }
2858
2859 if (return_option('figlet', 'font')) {
2860 $font = return_option('figlet', 'font');
2861 } else {
2862 while ($option{dau_figlet_fontlist} =~ /\s*([^,\s]+)\s*,?/g) {
2863 $font{$1} = 1;
2864 }
2865 foreach my $font (keys %{ $switches{combo}{figlet}{font} }) {
2866 if (lc($option{dau_figlet_fontpolicy}) eq 'allow') {
2867 push(@fonts, $font)
2868 unless ($font{$font});
2869 } elsif (lc($option{dau_figlet_fontpolicy}) eq 'deny') {
2870 push(@fonts, $font)
2871 if ($font{$font});
2872 } else {
2873 print_err('Invalid value for dau_figlet_fontpolicy.');
2874 return;
2875 }
2876 }
2877 if (@fonts == 0) {
2878 print_err('Cannot find figlet fonts.');
2879 return;
2880 }
2881 $font = $fonts[rand(@fonts)];
2882 }
2883
2884 # Run figlet
2885
2886 local(*HIS_IN, *HIS_OUT, *HIS_ERR);
2887
2888 my $childpid = open3(*HIS_IN, *HIS_OUT, *HIS_ERR, $option{dau_figlet_path}, '-f', $font);
2889
2890 print HIS_IN $data or return;
2891 close(HIS_IN) or return;
2892
2893 my @errlines = <HIS_ERR>;
2894 my @outlines = <HIS_OUT>;
2895 close(HIS_ERR) or return;
2896 close(HIS_OUT) or return;
2897
2898 waitpid($childpid, 0);
2899 if ($?) {
2900 print_err("That child exited with wait status of $?");
2901 }
2902
2903 # Error during execution? Print errors and return
2904
2905 unless (@errlines == 0) {
2906 print_err('Error during execution of figlet');
2907 foreach my $line (@errlines) {
2908 print_err($line);
2909 }
2910 return;
2911 }
2912
2913 if ($option{dau_figlet_print_font}) {
2914 print_out("Using figlet font $font");
2915 }
2916
2917 foreach (@outlines) {
2918 chomp;
2919 if (/^\s*$/ && $skip) {
2920 next;
2921 } else {
2922 $skip = 0;
2923 }
2924 push(@cache1, $_);
2925 }
2926 $skip = 1;
2927 foreach (reverse @cache1) {
2928 chomp;
2929 if (/^\s*$/ && $skip) {
2930 next;
2931 } else {
2932 $skip = 0;
2933 }
2934 push(@cache2, $_);
2935 }
2936 foreach (reverse @cache2) {
2937 $output .= "$_\n";
2938 }
2939
2940 return $output;
2941 }
2942
2943 sub switch_leet {
2944 my $data = shift;
2945
2946 $_ = $data;
2947
2948 s'fucker'f@#$er'gi;
2949 s/hacker/h4x0r/gi;
2950 s/sucker/sux0r/gi;
2951 s/fear/ph34r/gi;
2952
2953 s/\b(\w+)ude\b/${1}00d/gi;
2954 s/\b(\w+)um\b/${1}00m/gi;
2955 s/\b(\w{3,})er\b/${1}0r/gi;
2956 s/\bdo\b/d00/gi;
2957 s/\bthe\b/d4/gi;
2958 s/\byou\b/j00/gi;
2959
2960 tr/lLzZeEaAsSgGtTbBqQoOiIcC/11223344556677889900||((/;
2961 s/(\w)/rand(100) < 50 ? "\u$1" : "\l$1"/ge;
2962
2963 return $_;
2964 }
2965
2966 sub switch_me {
2967 my $data = shift;
2968
2969 $command_out = 'ACTION';
2970
2971 return $data;
2972 }
2973
2974 # &switch_mix by Martin Kihlgren <zond@troja.ath.cx>
2975 # slightly modified by myself
2976
2977 sub switch_mix {
2978 my $data = shift;
2979 my $output;
2980
2981 while ($data =~ s/(\s*)([^\w]*)([\w]+)([^\w]*)(\s+[^\w]*\w+[^\w]*\s*)*/$5/) {
2982 my $prespace = $1;
2983 my $prechars = $2;
2984 my $w = $3;
2985 my $postchars = $4;
2986 $output = $output . $prespace . $prechars . substr($w,0,1);
2987 my $middle = substr($w,1,length($w) - 2);
2988 while ($middle =~ s/(.)(.*)/$2/) {
2989 if (rand() > 0.1) {
2990 $middle = $middle . $1;
2991 } else {
2992 $output = $output . $1;
2993 }
2994 }
2995 if (length($w) > 1) {
2996 $output = $output . substr($w, length($w) - 1, 1);
2997 }
2998 $output = $output . $postchars;
2999 }
3000
3001 return $output;
3002 }
3003
3004 sub switch_mixedcase {
3005 my $data = shift;
3006
3007 $data =~ s/([[:alpha:]])/rand(100) < 50 ? uc($1) : lc($1)/ge;
3008
3009 return $data;
3010 }
3011
3012 sub switch_moron {
3013 my ($data, $channel_rec) = @_;
3014 my $output;
3015 my $option_eol_style = return_option('moron', 'eol_style', $option{dau_moron_eol_style});
3016 my $option_language = $option{dau_language};
3017
3018 ################################################################################
3019 # -omega on
3020 ################################################################################
3021
3022 my $omega;
3023
3024 if (return_option('moron', 'omega') eq 'on') {
3025 my @words = qw(omfg lol wtf);
3026
3027 foreach (split / (?=\w+\b)/, $data) {
3028 if (rand(100) < 20) {
3029 $omega .= ' ' . $words[rand(@words)] . " $_";
3030 } else {
3031 $omega .= ' ' . $_;
3032 }
3033 }
3034
3035 $omega =~ s/\s*,\s+\@/ @/g;
3036 $omega =~ s/^\s+//;
3037 }
3038
3039 $_ = $omega || $data;
3040
3041 ################################################################################
3042 # 'nick: text' -> 'text @ nick'
3043 ################################################################################
3044
3045 my $old_list_delimiter = $option{dau_parse_special_list_delimiter};
3046 $option{dau_parse_special_list_delimiter} = ' ';
3047 my @nicks = split(/ /, switch_parse_special('@nicks', $channel_rec));
3048 $option{dau_parse_special_list_delimiter} = $old_list_delimiter;
3049 @nicks = map { quotemeta($_) } @nicks;
3050
3051 {
3052 local $" = '|';
3053 eval { # Catch strange error
3054 s/^(@nicks): (.+)/$2 @ $1/;
3055 };
3056 }
3057
3058 ################################################################################
3059 # Preparations for "EOL modifications" later
3060 ################################################################################
3061
3062 # Remove puntuation marks at EOL and ensure there is a single space at EOL.
3063 # This is necessary because the EOL-styles 'new' and 'classic' put them at
3064 # EOL. If EOL-style is set to 'nothing' don't do this.
3065
3066 s/\s*([,;.:?!])*\s*$// unless ($option_eol_style eq 'nothing');
3067 my $lastchar = $1;
3068
3069 # Only whitespace? Remove it.
3070
3071 s/^\s+$//;
3072
3073 ################################################################################
3074 # Substitutions for every language
3075 ################################################################################
3076
3077 tr/'/`/;
3078
3079 # Dauify smileys
3080
3081 {
3082 # Use of uninitialized value in concatenation (.) or string at...
3083 # (the optional dash ($1) in the regular expressions).
3084 # Thus turn off warnings
3085
3086 no warnings;
3087
3088 if ($option{dau_language} eq 'de') {
3089 if (int(rand(2))) {
3090 s/:(-)?\)/^^/go;
3091 } else {
3092 s/:(-)?\)/':' . $1 . ')))' . (')' x rand(10)) . ('9' x rand(4))/ego;
3093 }
3094
3095 s/;(-)?\)/';' . $1 . ')))' . (')' x rand(10)) . ('9' x rand(4))/ego;
3096 s/:(-)?\(/':' . $1 . '(((' . ('(' x rand(10)) . ('8' x rand(4))/ego;
3097 s#(^|\s):(-)?/(\s|$)#$1 . ':' . $2 . '///' . ('/' x rand(10)) . ('7' x rand(4)) . $3#ego;
3098 } else {
3099 if (int(rand(2))) {
3100 s/:(-)?\)/^^/go;
3101 } else {
3102 s/:(-)?\)/':' . $1 . ')))' . (')' x rand(10)) . ('0' x rand(4))/ego;
3103 }
3104
3105 s/;(-)?\)/';' . $1 . ')))' . (')' x rand(10)) . ('0' x rand(4))/ego;
3106 s/:(-)?\(/':' . $1 . '(((' . ('(' x rand(10)) . ('9' x rand(4))/ego;
3107 }
3108 }
3109
3110 ################################################################################
3111 # English text
3112 ################################################################################
3113
3114 if ($option_language eq 'en') {
3115 s/\bthe\b/teh/go;
3116 }
3117
3118 ################################################################################
3119 # German text
3120 ################################################################################
3121
3122 if ($option_language eq 'de') {
3123
3124 # '*GG*' -> 'ÃGGÃ'
3125 {
3126 my @a = ('*', 'Ã');
3127 my $a = $a[int(rand(@a))];
3128 s/\*g\*/$a . 'ggg' . ('g' x rand(10)) . $a/egio;
3129 }
3130
3131 # verbs
3132
3133 s/\b(f)reuen\b/$1roien/gio;
3134 s/\b(f)reue\b/$1roie/gio;
3135 s/\b(f)reust\b/$1roist/gio;
3136 s/\b(f)reut\b/$1roit/gio;
3137
3138 s/\b(f)unktionieren\b/$1unzen/gio;
3139 s/\b(f)unktioniere\b/$1unze/gio;
3140 s/\b(f)unktionierst\b/$1unzt/gio;
3141 s/\b(f)unktioniert\b/$1unzt/gio;
3142
3143 s/\b(h)olen\b/$1ohlen/gio;
3144 s/\b(h)ole\b/$1ohle/gio;
3145 s/\b(h)olst\b/$1ohlst/gio;
3146 s/\b(h)olt\b/$1ohlt/gio;
3147
3148 s/\b(k)onfigurieren\b/$1 eq 'k' ? 'confen' : 'Confen'/egio;
3149 s/\b(k)onfiguriere\b/$1 eq 'k' ? 'confe' : 'Confe'/egio;
3150 s/\b(k)onfigurierst\b/$1 eq 'k' ? 'confst' : 'Confst'/egio;
3151 s/\b(k)onfiguriert\b/$1 eq 'k' ? 'conft' : 'Conft'/egio;
3152
3153 s/\b(l)achen\b/$1ölen/gio;
3154 s/\b(l)ache\b/$1öle/gio;
3155 s/\b(l)achst\b/$1ölst/gio;
3156 s/\b(l)acht\b/$1ölt/gio;
3157
3158 s/\b(m)achen\b/$1 eq 'm' ? 'tun' : 'Tun'/egio;
3159 s/\b(m)ache\b/$1 eq 'm' ? 'tu' : 'Tu'/egio;
3160 s/\b(m)achst\b/$1 eq 'm' ? 'tust' : 'Tust'/egio;
3161
3162 s/\b(n)erven\b/$1erfen/gio;
3163 s/\b(n)erve\b/$1erfe/gio;
3164 s/\b(n)ervst\b/$1erfst/gio;
3165 s/\b(n)ervt\b/$1erft/gio;
3166
3167 s/\b(p)rojizieren\b/$1rojezieren/gio;
3168 s/\b(p)rojiziere\b/$1rojeziere/gio;
3169 s/\b(p)rojizierst\b/$1rojezierst/gio;
3170 s/\b(p)rojiziert\b/$1rojeziert/gio;
3171
3172 s/\b(r)egistrieren\b/$1egestrieren/gio;
3173 s/\b(r)egistriere\b/$1egestriere/gio;
3174 s/\b(r)egistrierst\b/$1egestrierst/gio;
3175 s/\b(r)egistriert\b/$1egestriert/gio;
3176
3177 s/\b(s)pazieren\b/$1patzieren/gio;
3178 s/\b(s)paziere\b/$1patziere/gio;
3179 s/\b(s)pazierst\b/$1patzierst/gio;
3180 s/\b(s)paziert\b/$1patziert/gio;
3181
3182 # other
3183
3184 s/\bdanke\b/
3185 if (int(rand(2)) == 0) {
3186 'thx'
3187 } else {
3188 'danks'
3189 }
3190 /ego;
3191 s/\bDanke\b/
3192 if (int(rand(2)) == 0) {
3193 'Thx'
3194 } else {
3195 'Danks'
3196 }
3197 /ego;
3198
3199 s/\blol\b/
3200 if (int(rand(2)) == 0) {
3201 'löl'
3202 } else {
3203 'löllens'
3204 }
3205 /ego;
3206 s/\bLOL\b/
3207 if (int(rand(2)) == 0) {
3208 'LÃL'
3209 } else {
3210 'LÃLLENS'
3211 }
3212 /ego;
3213
3214 s/\br(?:ü|ue)ckgrat\b/
3215 if (int(rand(3)) == 0) {
3216 'rückgrad'
3217 } elsif (int(rand(3)) == 1) {
3218 'rückrad'
3219 } else {
3220 'rückrat'
3221 }
3222 /ego;
3223 s/\bR(?:ü|ue)ckgrat\b/
3224 if (int(rand(3)) == 0) {
3225 'Rückgrad'
3226 } elsif (int(rand(3)) == 1) {
3227 'Rückrad'
3228 } else {
3229 'Rückrat'
3230 }
3231 /ego;
3232
3233 s/\b(i)st er\b/$1ssa/gio;
3234 s/\bist\b/int(rand(2)) ? 'is' : 'iss'/ego;
3235 s/\bIst\b/int(rand(2)) ? 'Is' : 'Iss'/ego;
3236
3237 s/\b(d)a(?:ss|Ã) du\b/$1asu/gio;
3238 s/\b(d)a(?:ss|Ã)\b/$1as/gio;
3239
3240 s/\b(s)ag mal\b/$1amma/gio;
3241 s/\b(n)ochmal\b/$1omma/gio;
3242 s/(m)al\b/$1a/gio;
3243
3244 s/\b(u)nd nun\b/$1nnu/gio;
3245 s/\b(n)un\b/$1u/gio;
3246
3247 s/\b(s)oll denn\b/$1olln/gio;
3248 s/\b(d)enn\b/$1en/gio;
3249
3250 s/\b(s)o eine\b/$1onne/gio;
3251 s/\b(e)ine\b/$1 eq 'e' ? 'ne' : 'Ne'/egio;
3252
3253 s/\bkein problem\b/NP/gio;
3254 s/\b(p)roblem\b/$1rob/gio;
3255 s/\b(p)robleme\b/$1robs/gio;
3256
3257 s/\b(a)ber\b/$1bba/gio;
3258 s/\b(a)chso\b/$1xo/gio;
3259 s/\b(a)dresse\b/$1ddresse/gio;
3260 s/\b(a)ggressiv\b/$1gressiv/gio;
3261 s/\b([[:alpha:]]{2,})st du\b/${1}su/gio;
3262 s/\b(a)nf(?:ä|ae)nger\b/$1 eq 'a' ? 'n00b' : 'N00b'/egio;
3263 s/\b(a)sozial\b/$1ssozial/gio;
3264 s/\b(a)u(?:ss|Ã)er\b/$1user/gio;
3265 s/\b(a)utor/$1uthor/gio;
3266 s/\b(b)asta\b/$1 eq 'b' ? 'pasta' : 'Pasta'/egio;
3267 s/\b(b)illard\b/$1illiard/gio;
3268 s/\b(b)i(?:ss|Ã)chen\b/$1ischen/gio;
3269 s/\b(b)ist\b/$1is/gio;
3270 s/\b(b)itte\b/$1 eq 'b' ? 'plz' : 'Plz'/egio;
3271 s/\b(b)lo(?:ss|Ã)\b/$1los/gio;
3272 s/\b(b)(?:ox|(?:ü|ue)chse)\b/$1yxe/gio;
3273 s/\b(b)rillant\b/$1rilliant/gio;
3274 s/\b(c)hannel\b/$1 eq 'c' ? 'kanal' : 'Kanal'/egio;
3275 s/\b(c)hat\b/$1hatt/gio;
3276 s/\b(c)ool\b/$1 eq 'c' ? 'kewl' : 'Kewl'/egio;
3277 s/\b(d)(?:ä|ae)mlich\b/$1ähmlich/gio;
3278 s/\b(d)etailliert\b/$1etailiert/gio;
3279 s/\b(d)ilettantisch\b/$1illetantisch/gio;
3280 s/\b(d)irekt\b/$1ireckt/gio;
3281 s/\b(d)iskussion\b/$1isskusion/gio;
3282 s/\b(d)istribution/$1ystrubution/gio;
3283 s/\b(e)igentlich\b/$1igendlich/gio;
3284 s/\b(e)inzige\b/$1inzigste/gio;
3285 s/\b(e)nd/$1nt/gio;
3286 s/\b(e)ntschuldigung\b/$1 eq 'e' ? 'sry' : 'Sry'/egio;
3287 s/\b(f)ilm\b/$1 eq 'f' ? 'movie' : 'Movie'/egio;
3288 s/\b(f)lachbettscanner\b/$1lachbrettscanner/gio;
3289 s/\b(f)reu\b/$1roi/gio;
3290 s/\b(g)alerie\b/$1allerie/gio;
3291 s/\b(g)ay\b/$1hey/gio;
3292 s/\b(g)ebaren\b/$1ebahren/gio;
3293 s/\b(g)elatine\b/$1elantine/gio;
3294 s/\b(g)eratewohl\b/$1eradewohl/gio;
3295 s/\b(g)ibt es\b/$1ibbet/gio;
3296 s/\bgra([dt])/$1 eq 'd' ? 'grat' : 'grad'/ego;
3297 s/\bGra([dt])/$1 eq 'd' ? 'Grat' : 'Grad'/ego;
3298 s/\b(h)(?:ä|ae)ltst\b/$1älst/gio;
3299 s/\b(h)(?:ä|ae)sslich/$1äslich/gio;
3300 s/\b(h)aneb(?:ü|ue)chen\b/$1ahneb$2chen/gio;
3301 s/\b(i)mmobilie/$1mobilie/gio;
3302 s/\b(i)nteressant\b/$1nterressant/gio;
3303 s/\b(i)ntolerant\b/$1ntollerant/gio;
3304 s/\b(i)rgend/$1rgent/gio;
3305 s/\b(j)a\b/$1oh/gio;
3306 s/\b(j)etzt\b/$1ez/gio;
3307 s/\b(k)affee\b/$1affe/gio;
3308 s/\b(k)aputt\b/$1aput/gio;
3309 s/\b(k)arussell\b/$1arussel/gio;
3310 s/\b(k)iste\b/$1 eq 'k' ? 'byxe' : 'Byxe'/egio;
3311 s/\b(k)lempner\b/$1lemptner/gio;
3312 s/\b(k)r(?:ä|ae)nker\b/$1ranker/gio;
3313 s/\b(k)rise\b/$1riese/gio;
3314 s/\b(l)etal\b/$1ethal/gio;
3315 s/\b(l)eute\b/$1 eq 'l' ? 'ppl' : 'Ppl'/egio;
3316 s/\b(l)ibyen\b/$1ybien/gio;
3317 s/\b(l)izenz\b/$1izens/gio;
3318 s/\b(l)oser\b/$1ooser/gio;
3319 s/\b(l)ustig/$1ölig/gio;
3320 s/\b(m)aschine\b/$1aschiene/gio;
3321 s/\b(m)illennium\b/$1illenium/gio;
3322 s/\b(m)iserabel\b/$1ieserabel/gio;
3323 s/\b(m)it dem\b/$1im/gio;
3324 s/\b(m)orgendlich\b/$1orgentlich/gio;
3325 s/\b(n)(?:ä|ae)mlich\b/$1ähmlich/gio;
3326 s/\b(n)ein\b/$1eh/gio;
3327 s/\bnett\b/n1/gio;
3328 s/\b(n)ewbie\b/$100b/gio;
3329 s/\bnicht\b/int(rand(2)) ? 'net' : 'ned'/ego;
3330 s/\bNicht\b/int(rand(2)) ? 'Net' : 'Ned'/ego;
3331 s/\b(n)iveau/$1iwo/gio;
3332 s/\bok(?:ay)?\b/K/gio;
3333 s/\b(o)riginal\b/$1rginal/gio;
3334 s/\b(p)aket\b/$1acket/gio;
3335 s/\b(p)l(?:ö|oe)tzlich\b/$1lözlich/gio;
3336 s/\b(p)ogrom\b/$1rogrom/gio;
3337 s/\b(p)rogramm\b/$1roggie/gio;
3338 s/\b(p)rogramme\b/$1roggies/gio;
3339 s/\b(p)sychiater\b/$1sychater/gio;
3340 s/\b(p)ubert(?:ä|ae)t\b/$1upertät/gio;
3341 s/\b(q)uarz\b/$1uartz/gio;
3342 s/\b(q)uery\b/$1uerry/gio;
3343 s/\b(r)eferenz\b/$1efferenz/gio;
3344 s/\b(r)eparatur\b/$1eperatur/gio;
3345 s/\b(r)eply\b/$1eplay/gio;
3346 s/\b(r)essource\b/$1esource/gio;
3347 s/\b(r)(o)(t?fl)\b/$1 . ($2 eq 'o' ? 'ö' : 'Ã') . $3/egio;
3348 s/\b(r)(o)(t?fl)(o)(l)\b/$1 . ($2 eq 'o' ? 'ö' : 'Ã') . $3 . ($4 eq 'o' ? 'ö' : 'Ã') . $5/egio;
3349 s/\b(s)atellit\b/$1attelit/gio;
3350 s/\b(s)cherz\b/$1chertz/gio;
3351 s/\bsei([dt])\b/$1 eq 'd' ? 'seit' : 'seid'/ego;
3352 s/\bSei([dt])\b/$1 eq 'd' ? 'Seit' : 'Seid'/ego;
3353 s/\b(s)elig\b/$1eelig/gio;
3354 s/\b(s)eparat\b/$1eperat/gio;
3355 s/\b(s)eriosit(?:ä|ae)t\b/$1erösität/gio;
3356 s/\b(s)onst\b/$1onnst/gio;
3357 s/\b(s)orry\b/$1ry/gio;
3358 s/\b(s)pelunke\b/$1ilunke/gio;
3359 s/\b(s)piel\b/$1 eq 's' ? 'game' : 'Game'/egio;
3360 s/\b(s)tabil\b/$1tabiel/gio;
3361 s/\b(s)tandard\b/$1tandart/gio;
3362 s/\b(s)tegreif\b/$1tehgreif/gio;
3363 s/\b(s)ympathisch\b/$1ymphatisch/gio;
3364 s/\b(s)yntax\b/$1ynthax/gio;
3365 s/\b(t)era/$1erra/gio;
3366 s/\b(t)oler/$1oller/gio;
3367 s/\bto([td])/$1 eq 't' ? 'tod' : 'tot'/ego;
3368 s/\bTo([td])/$1 eq 't' ? 'Tod' : 'Tot'/ego;
3369 s/\b(u)ngef(?:ä|ae)hr\b/$1ngefär/gio;
3370 s/\bviel gl(?:ü|ue)ck\b/GL/gio;
3371 s/\b(v)ielleicht\b/$1ileicht/gio;
3372 s/\b(v)oraus/$1orraus/gio;
3373 s/\b(w)(?:ä|ae)re\b/$1ähre/gio;
3374 s/\bwa(h)?r/$1 eq 'h' ? 'war' : 'wahr'/ego;
3375 s/\bWa(h)?r/$1 eq 'h' ? 'War' : 'Wahr'/ego;
3376 s/\b(w)as du\b/$1asu/gio;
3377 s/\b(w)eil du\b/$1eilu/gio;
3378 s/\bweis(s)?/$1 eq 's' ? 'weis' : 'weiss'/ego;
3379 s/\bWeis(s)?/$1 eq 's' ? 'Weis' : 'Weiss'/ego;
3380 s/\b(w)enn du\b/$1ennu/gio;
3381 s/\b(w)ider/$1ieder/gio;
3382 s/\b(w)ieso\b/$1iso/gio;
3383 s/\b(z)iemlich\b/$1iehmlich/gio;
3384 s/\b(z)umindest\b/$1umindestens/gio;
3385
3386 tr/üÃ/yY/;
3387 s/ei(?:ss?|Ã)e?/ice/go;
3388 s/eife?/ive/go;
3389
3390 if(return_option('moron', 'level') >= 1) {
3391 s/\b(u)nd\b/$1nt/gio;
3392 s/\b(h)at\b/$1att/gio;
3393 s/\b(n)ur\b/$1uhr/gio;
3394 s/\b(v)er(\w+)/$1 eq 'V' ? "Fa$2" : "fa$2"/egio;
3395 s/\b([[:alpha:]]+[b-np-tv-z])er\b/${1}a/go;
3396 s/\b([[:alpha:]]+)ck/${1}q/go;
3397
3398 s/\b([fv])(?=[[:alpha:]]{2,})/
3399 if (rand(10) <= 4) {
3400 if ($1 eq 'f') {
3401 'v'
3402 }
3403 else {
3404 'f'
3405 }
3406 } else {
3407 $1
3408 }
3409 /egox;
3410 s/\b([FV])(?=[[:alpha:]]{2,})/
3411 if (rand(10) <= 4) {
3412 if ($1 eq 'F') {
3413 'V'
3414 }
3415 else {
3416 'F'
3417 }
3418 } else {
3419 $1
3420 }
3421 /egox;
3422 s#\b([[:alpha:]]{2,})([td])\b#
3423 my $begin = $1;
3424 my $end = $2;
3425 if (rand(10) <= 4) {
3426 if ($end eq 't' && $begin !~ /t$/) {
3427 "${begin}d"
3428 } elsif ($end eq 'd' && $begin !~ /d$/) {
3429 "${begin}t"
3430 } else {
3431 "${begin}${end}"
3432 }
3433 } else {
3434 "${begin}${end}"
3435 }
3436 #egox;
3437 s/\b([[:alpha:]]{2,})ie/
3438 if (rand(10) <= 4) {
3439 "$1i"
3440 } else {
3441 "$1ie"
3442 }
3443 /egox;
3444 }
3445 }
3446
3447 $data = $_;
3448
3449 ################################################################################
3450 # Swap characters with characters near at the keyboard
3451 ################################################################################
3452
3453 my %mark;
3454 my %chars;
3455 if ($option{dau_language} eq 'de') {
3456 %chars = (
3457 'a' => [ 's' ],
3458 'b' => [ 'v', 'n' ],
3459 'c' => [ 'x', 'v' ],
3460 'd' => [ 's', 'f' ],
3461 'e' => [ 'w', 'r' ],
3462 'f' => [ 'd', 'g' ],
3463 'g' => [ 'f', 'h' ],
3464 'h' => [ 'g', 'j' ],
3465 'i' => [ 'u', 'o' ],
3466 'j' => [ 'h', 'k' ],
3467 'k' => [ 'j', 'l' ],
3468 'l' => [ 'k', 'ö' ],
3469 'm' => [ 'n' ],
3470 'n' => [ 'b', 'm' ],
3471 'o' => [ 'i', 'p' ],
3472 'p' => [ 'o', 'ü' ],
3473 'q' => [ 'w' ],
3474 'r' => [ 'e', 't' ],
3475 's' => [ 'a', 'd' ],
3476 't' => [ 'r', 'z' ],
3477 'u' => [ 'z', 'i' ],
3478 'v' => [ 'c', 'b' ],
3479 'w' => [ 'q', 'e' ],
3480 'x' => [ 'y', 'c' ],
3481 'y' => [ 'x' ],
3482 'z' => [ 't', 'u' ],
3483 );
3484 } else {
3485 %chars = (
3486 'a' => [ 's' ],
3487 'b' => [ 'v', 'n' ],
3488 'c' => [ 'x', 'v' ],
3489 'd' => [ 's', 'f' ],
3490 'e' => [ 'w', 'r' ],
3491 'f' => [ 'd', 'g' ],
3492 'g' => [ 'f', 'h' ],
3493 'h' => [ 'g', 'j' ],
3494 'i' => [ 'u', 'o' ],
3495 'j' => [ 'h', 'k' ],
3496 'k' => [ 'j', 'l' ],
3497 'l' => [ 'k', 'ö' ],
3498 'm' => [ 'n' ],
3499 'n' => [ 'b', 'm' ],
3500 'o' => [ 'i', 'p' ],
3501 'p' => [ 'o', 'ü' ],
3502 'q' => [ 'w' ],
3503 'r' => [ 'e', 't' ],
3504 's' => [ 'a', 'd' ],
3505 't' => [ 'r', 'z' ],
3506 'u' => [ 'z', 'i' ],
3507 'v' => [ 'c', 'b' ],
3508 'w' => [ 'q', 'e' ],
3509 'x' => [ 'y', 'c' ],
3510 'y' => [ 't', 'u' ],
3511 'z' => [ 'x' ],
3512 );
3513 }
3514
3515 # Do not replace one character twice
3516 # Therefore every replace-position will be marked
3517
3518 unless (lc(return_option('moron', 'typo')) eq 'off') {
3519 for (0 .. length($data)) {
3520 $mark{$_} = 0;
3521 }
3522
3523 for (0 .. rand(length($data))/20) {
3524 my $pos = int(rand(length($data)));
3525 pos $data = $pos;
3526 unless ($mark{$pos} == 1) {
3527 no locale;
3528 if ($data =~ /\G([A-Za-z])/g) {
3529 my $matched = $1;
3530 my $replacement;
3531 if ($matched eq lc($matched)) {
3532 $replacement = $chars{$matched}[int(rand(@{ $chars{$matched} }))];
3533 } else {
3534 $replacement = uc($chars{$matched}[int(rand(@{ $chars{$matched} }))]);
3535 }
3536 if ($replacement !~ /^\s*$/) {
3537 substr($data, $pos, 1, $replacement);
3538 $mark{$pos} = 1;
3539 }
3540 }
3541 }
3542 }
3543 }
3544
3545 ################################################################################
3546 # Mix in some typos (swapping characters)
3547 ################################################################################
3548
3549 unless (lc(return_option('moron', 'typo')) eq 'off') {
3550 foreach my $word (split /([\s\n])/, $data) {
3551 if ((rand(100) <= 20) && length($word) > 1) {
3552 my $position_swap = int(rand(length($word)));
3553 if ($position_swap == 0) {
3554 $position_swap = 1;
3555 } elsif ($position_swap == length($word)) {
3556 $position_swap = length($word) - 1;
3557 }
3558 if (substr($word, $position_swap - 1, 1) eq uc(substr($word, $position_swap - 1, 1)) &&
3559 substr($word, $position_swap, 1) eq lc(substr($word, $position_swap, 1)))
3560 {
3561 (substr($word, $position_swap, 1), substr($word, $position_swap - 1, 1)) =
3562 (lc(substr($word, $position_swap - 1, 1)), uc(substr($word, $position_swap, 1)));
3563 } else {
3564 (substr($word, $position_swap, 1), substr($word, $position_swap - 1, 1)) =
3565 (substr($word, $position_swap - 1, 1), substr($word, $position_swap, 1));
3566 }
3567 }
3568 $output .= $word;
3569 }
3570 } else {
3571 $output = $_;
3572 }
3573
3574 ################################################################################
3575 # plenk
3576 ################################################################################
3577
3578 $output =~ s/(\w+)([,;.:?!]+)(\s+|$)/
3579 if (rand(10) <= 8 || $3 eq '') {
3580 "$1 $2$3"
3581 } else {
3582 "$1$2"
3583 }
3584 /egox;
3585
3586 ################################################################################
3587 # default behaviour: uppercase text
3588 ################################################################################
3589
3590 $output = uc($output) unless (return_option('moron', 'uppercase') eq 'off');
3591
3592 ################################################################################
3593 # do something at EOL
3594 ################################################################################
3595
3596 if ($option_eol_style ne 'nothing') {
3597 my $random = int(rand(100));
3598
3599 $output .= ' ' unless ($output =~ /^\s*$/);
3600
3601 # !!!!!!??????????!!!!!!!!!!11111
3602
3603 if ($random <= 70 || $lastchar eq '!') {
3604 my @punct = qw(? !);
3605 $output .= $punct[rand(@punct)] x int(rand(5))
3606 for (1..15);
3607
3608 if ($lastchar eq '?') {
3609 $output .= '?' x (int(rand(4))+1);
3610 } elsif ($lastchar eq '!') {
3611 $output .= '!' x (int(rand(4))+1);
3612 }
3613
3614 if ($output =~ /\?$/) {
3615 if ($option{dau_language} eq 'de') {
3616 $output .= "Ã" x int(rand(10));
3617 } else {
3618 $output .= "/" x int(rand(10));
3619 }
3620 } elsif ($output =~ /!$/) {
3621 $output .= "1" x int(rand(10));
3622 }
3623 }
3624
3625 # ?¿?
3626
3627 elsif ($random <= 85) {
3628 $output .= '?¿?';
3629 }
3630
3631 # "=\n?"
3632
3633 else {
3634 $output .= "=\n?";
3635 }
3636 }
3637
3638 return $output;
3639 }
3640
3641 sub switch_nothing {
3642 my $data = shift;
3643
3644 return $data;
3645 }
3646
3647 sub switch_parse_special {
3648 my ($text, $channel) = @_;
3649
3650 local $" = return_option('parse_special', 'list_delimiter', $option{dau_parse_special_list_delimiter});
3651
3652 # Build nick array with every nick in channel and
3653 # opnick array with every op in the channel
3654
3655 my @nicks = ();
3656 my @opnicks = ();
3657 if (defined($channel) && $channel && $channel->{type} eq 'CHANNEL') {
3658 foreach my $nick ($channel->nicks()) {
3659 next if ($channel->{server}->{nick} eq $nick->{nick});
3660 push(@nicks, $nick->{nick});
3661 push(@opnicks, $nick->{nick}) if ($nick->{op});
3662 }
3663 }
3664 @nicks = sort { lc($a) cmp lc($b) } @nicks;
3665 @opnicks = sort { lc($a) cmp lc($b) } @opnicks;
3666
3667 # Substitution: \n to a real newline
3668
3669 $text =~ s/(?<![\\])\\n/\n/g;
3670
3671 # Substitution: @nicks to all nicks of channel
3672
3673 $text =~ s/(?<![\\])\@nicks/@nicks/gc;
3674
3675 # Substitution: @opnicks to all nicks of channel
3676
3677 $text =~ s/(?<![\\])\@opnicks/@opnicks/gc;
3678
3679 # Substitution: $nick1..$nickn
3680
3681 while ($text =~ /(?<![\\])\$nick(\d+)/g) {
3682 my $substitution = $nicks[rand(@nicks)];
3683 $text =~ s/(?<![\\])\$nick$1([^\d]|$)/${substitution}$1/g;
3684 @nicks = grep { $_ ne $substitution } @nicks;
3685 last if (@nicks == 0);
3686 }
3687
3688 # Substitution: $opnick1..$opnickn
3689
3690 while ($text =~ /(?<![\\])\$opnick(\d+)/g) {
3691 my $substitution = $opnicks[rand(@opnicks)];
3692 $text =~ s/(?<![\\])\$opnick$1([^\d]|$)/${substitution}$1/g;
3693 @opnicks = grep { $_ ne $substitution } @opnicks;
3694 last if (@opnicks == 0);
3695 }
3696
3697 # Substitution: $?{ code }
3698
3699 my $np; # (nested pattern)
3700 $np = qr{
3701 {
3702 (?:
3703 (?> [^{}]+ ) # Non-capture group w/o backtracking
3704 |
3705 (??{ $np }) # Group with matching parens
3706 )*
3707 }
3708 }x;
3709
3710 while ($text =~ /(?<![\\])\$\?($np)/g) {
3711 {
3712 no strict;
3713 my $replacement = eval $1;
3714 if ($@) {
3715 print_err('Invalid code used in construct $?{ code }. Details:');
3716 print_err($@);
3717 return;
3718 } else {
3719 chomp($replacement);
3720 $text =~ s/(?<![\\])\$\?($np)/$replacement/;
3721 }
3722 }
3723 }
3724
3725 # Substitution: irssi's special variables
3726
3727 if ((defined($channel) && $channel &&
3728 ($channel->{type} eq 'CHANNEL' || $channel->{type} eq 'QUERY')) &&
3729 !(lc(return_option('parse_special', 'irssi_variables')) eq 'off'))
3730 {
3731 $text = $channel->parse_special($text);
3732 }
3733
3734 return $text;
3735 }
3736
3737 sub switch_reverse {
3738 my $data = shift;
3739
3740 $data = reverse($data);
3741
3742 return $data;
3743 }
3744
3745 sub switch_stutter {
3746 my $data = shift;
3747 my $output;
3748 my @words = qw(eeeh oeeeh aeeeh);
3749
3750 foreach (split / (?=\w+\b)/, $data) {
3751 if (rand(100) < 20) {
3752 $output .= ' ' . $words[rand(@words)] . ", $_";
3753 } else {
3754 $output .= ' ' . $_;
3755 }
3756 }
3757
3758 $output =~ s/\s*,\s+\@/ @/g;
3759
3760 for (1 .. rand(length($output)/5)) {
3761 pos $output = rand(length($output));
3762 $output =~ s/\G ([[:alpha:]]+)\b/ $1, $1/;
3763 }
3764 for (1 .. rand(length($output)/10)) {
3765 pos $output = rand(length($output));
3766 $output =~ s/\G([[:alpha:]])/$1 . ($1 x rand(3))/e;
3767 }
3768
3769 $output =~ s/^\s+//;
3770
3771 return $output;
3772 }
3773
3774 sub switch_substitute {
3775 $_ = shift;
3776
3777 my $file = "$option{dau_files_root_directory}/$option{dau_files_substitute}";
3778
3779 if (-e $file && -r $file) {
3780 my $return = do $file;
3781
3782 if ($@) {
3783 print_err("parsing $file failed: $@");
3784 }
3785 unless (defined($return)) {
3786 print_err("'do $file' failed");
3787 }
3788 }
3789
3790 return $_;
3791 }
3792
3793 sub switch_underline {
3794 my $data = shift;
3795
3796 $data = "\037$data\037";
3797
3798 return $data;
3799 }
3800
3801 sub switch_uppercase {
3802 my $data = shift;
3803
3804 $data = uc($data);
3805
3806 return $data;
3807 }
3808
3809 sub switch_words {
3810 my $data = shift;
3811 my $output;
3812 my @numbers;
3813
3814 if ($option{dau_words_range} =~ /^([1-9])-([1-9])$/) {
3815 my $x = $1;
3816 my $y = $2;
3817 unless ($x <= $y) {
3818 print_err('Invalid value for setting dau_words_range.');
3819 return;
3820 }
3821 if ($x == $y) {
3822 push(@numbers, $x);
3823 } elsif ($x < $y) {
3824 for (my $i = $x; $i <= $y; $i++) {
3825 push(@numbers, $i);
3826 }
3827 }
3828 } else {
3829 print_err('Invalid value for dau_words_range.');
3830 return;
3831 }
3832 my $random = $numbers[rand(@numbers)];
3833 while ($data =~ /((?:.*?(?:\s+|$)){1,$random})/g) {
3834 $output .= "$1\n"
3835 unless (length($1) == 0);
3836 $random = $numbers[rand(@numbers)];
3837 }
3838
3839 $output =~ s/\s*$//;
3840
3841 return $output;
3842 }
3843
3844 ################################################################################
3845 # Subroutines (signals)
3846 ################################################################################
3847
3848 sub signal_channel_destroyed {
3849 my ($channel) = @_;
3850
3851 my $channel_name = $channel->{name};
3852 my $network_name = $channel->{server}->{tag};
3853
3854 $daumode{channels_in}{$network_name}{$channel_name} = 0;
3855 $daumode{channels_out}{$network_name}{$channel_name} = 0;
3856 $daumode{channels_in_modes}{$network_name}{$channel_name} = '';
3857 $daumode{channels_out_modes}{$network_name}{$channel_name} = '';
3858 }
3859
3860 sub signal_channel_joined {
3861 my ($channel) = @_;
3862
3863 # Resume babbles
3864
3865 if (defined($babble{timer_writing})) {
3866 if ($babble{channel}->{name} eq $channel->{name} &&
3867 $babble{channel}->{server}->{tag} eq $channel->{server}->{tag})
3868 {
3869 $channel->print('%9dau.pl:%9 Continuing babble...');
3870 timer_babble_writing();
3871 }
3872 }
3873
3874 # Automatically set daumode
3875
3876 daumode_channels();
3877 }
3878
3879 sub signal_command_msg {
3880 my ($args, $server, $witem) = @_;
3881
3882 $args =~ /^(?:-\S+\s)?(?:\S*)\s(.*)/;
3883 my $data = $1;
3884
3885 $command_in .= "$data\n";
3886
3887 Irssi::signal_stop();
3888 }
3889
3890 sub signal_complete_word {
3891 my ($list, $window, $word, $linestart, $want_space) = @_;
3892
3893 # Parsing the commandline for dau.pl is relatively complicated.
3894 # TAB completion depends on commandline parsing in dau.pl.
3895 # Script autors looking for a simple example for irssi's
3896 # TAB completion are wrong here.
3897
3898 my $server = Irssi::active_server();
3899 my $channel = $window->{active};
3900 my @switches_combo = map { $_ = "--$_" } keys %{ $switches{combo} };
3901 my @switches_nocombo = map { $_ = "--$_" } keys %{ $switches{nocombo} };
3902 my @nicks = ();
3903
3904 # Only complete when the commandline starts with '${k}dau'.
3905 # If not, let irssi do the work
3906
3907 return unless ($linestart =~ /^\Q${k}\Edau/i);
3908
3909 # Remove everything syntactically correct thing of $linestart.
3910 # If there is anything else but whitespace at the end of
3911 # commandline parsing, we have an syntax error.
3912 # If we have a syntax error, complete only nicks.
3913
3914 $linestart =~ s/^\Q${k}\Edau ?//i;
3915
3916 # Generate list of nicks in current channel for later use
3917
3918 if (defined($channel->{type}) && $channel->{type} eq 'CHANNEL') {
3919 foreach my $nick ($channel->nicks()) {
3920 if ($nick->{nick} =~ /^\Q$word\E/i &&
3921 $window->{active_server}->{nick} ne $nick->{nick})
3922 {
3923 push(@nicks, $nick->{nick});
3924 }
3925 }
3926 }
3927
3928 # Variables
3929
3930 my $combo = 0; # Boolean: True if last switch was one of keys %{ $switches{combo} }
3931 my $syntax_error = 0; # Boolean: True if syntax error found
3932 my $counter = 0; # Integer: Counts first level options
3933 my $first_level_option = ''; # String: Last first level option
3934 my $second_level_option = ''; # String: Last second level option
3935 my $third_level_option = 0; # Boolean: True if found a third level option
3936
3937 # Parsing commandline now. Set variables accordingly.
3938
3939 OUTER: while ($linestart =~ /^--(\w+) ?/g) {
3940
3941 $second_level_option = '';
3942 $third_level_option = 0;
3943
3944 # Found a first level option (combo)
3945
3946 if (ref($switches{combo}{$1}{'sub'})) {
3947 $first_level_option = $1;
3948 $combo = 1;
3949 }
3950
3951 # Found a first level option (nocombo)
3952
3953 elsif (ref($switches{nocombo}{$1}{'sub'}) && $counter == 0) {
3954 $first_level_option = $1;
3955 $combo = 0;
3956 }
3957
3958 # Not a first level option => Syntax error
3959
3960 else {
3961 $syntax_error = 1;
3962 last OUTER;
3963 }
3964
3965 # Syntactically correct => remove it
3966
3967 $linestart =~ s/^--\w+ ?//;
3968
3969 # Checkout if there are Second- or third level options
3970
3971 INNER: while ($linestart =~ /^-(\w+)(?: ('.*?(?<![\\])'|\S+))? ?/g) {
3972
3973 my $second_level = $1;
3974 my $third_level = $2 || '';
3975
3976 $third_level =~ s/^'//;
3977 $third_level =~ s/'$//;
3978 $third_level =~ s/\\'/'/g;
3979
3980 # Do the same for combo and nocombo-options. They have to be
3981 # handled separately anyway.
3982
3983 # combo...
3984
3985 if ($combo) {
3986
3987 # Found a second level option
3988
3989 if ($switches{combo}{$first_level_option}{$second_level}) {
3990 $second_level_option = $second_level;
3991 }
3992
3993 # Not a second level option => Syntax error
3994
3995 else {
3996 $syntax_error = 1;
3997 last OUTER;
3998 }
3999
4000 # Syntactically correct => remove it
4001
4002 $linestart =~ s/^-\w+//;
4003
4004 # Found something in the regexp of the INNER-while-loop-condition,
4005 # which is perhaps a third level option
4006
4007 if ($third_level) {
4008
4009 # Found a third level option
4010
4011 if ($switches{combo}{$first_level_option}{$second_level_option}{$third_level} ||
4012 $switches{combo}{$first_level_option}{$second_level_option}{'*'})
4013 {
4014 $third_level_option = 1;
4015
4016 # Syntactically correct => remove it
4017
4018 $linestart =~ s/^(?: ('.*?(?<![\\])'|\S+))? ?//;
4019 }
4020
4021 # Not a third level option => Syntax error
4022
4023 else {
4024 $syntax_error = 1;
4025 last OUTER;
4026 }
4027
4028 # Nothing found which comes into question for a third level option.
4029 # The commandline has to be empty now (remember: everything
4030 # syntactically correct has been removed) or we have a syntax error.
4031
4032 } else {
4033
4034 # Empty! Later we will complete to third level options
4035
4036 if ($linestart =~ /^\s*$/) {
4037 $third_level_option = 0;
4038 }
4039
4040 # Not empty => Syntax error
4041
4042 else {
4043 $syntax_error = 1;
4044 last OUTER;
4045 }
4046 }
4047
4048 # nocombo...
4049
4050 } else {
4051
4052 # Found a second level option
4053
4054 if ($switches{nocombo}{$first_level_option}{$second_level}) {
4055 $second_level_option = $second_level;
4056 }
4057
4058 # Not a second level option => Syntax error
4059
4060 else {
4061 $syntax_error = 1;
4062 last OUTER;
4063 }
4064
4065 # Syntactically correct => remove it
4066
4067 $linestart =~ s/^-\w+//;
4068
4069 # Found something in the regexp of the INNER while loop condition,
4070 # which is perhaps a third level option
4071
4072 if ($third_level) {
4073
4074 # Found a third level option
4075
4076 if ($switches{nocombo}{$first_level_option}{$second_level_option}{$third_level} ||
4077 $switches{nocombo}{$first_level_option}{$second_level_option}{'*'})
4078 {
4079 $third_level_option = 1;
4080
4081 # Syntactically correct => remove it
4082
4083 $linestart =~ s/^(?: ('.*?(?<![\\])'|\S+))? ?//;
4084 }
4085
4086 # Not a third level option => Syntax error
4087
4088 else {
4089 $syntax_error = 1;
4090 last OUTER;
4091 }
4092
4093 # Nothing found which comes into question for a third level option.
4094 # The commandline has to be empty now (remember: everything
4095 # syntactically correct has been removed) or we have a syntax error.
4096
4097 } else {
4098
4099 # Empty! Later we will complete to third level options
4100
4101 if ($linestart =~ /^\s*$/) {
4102 $third_level_option = 0;
4103 }
4104
4105 # Not empty => Syntax error
4106
4107 else {
4108 $syntax_error = 1;
4109 last OUTER;
4110 }
4111 }
4112 }
4113 }
4114 } continue {
4115 $counter++;
4116 }
4117
4118 # End of commandline-parsing.
4119 # Everything syntactically correct removed.
4120 # If commandline is not empty now, we have a syntax error.
4121
4122 if ($linestart !~ /^\s*$/) {
4123 $syntax_error = 1;
4124 }
4125
4126 # Do the TAB completion
4127
4128 @$list = ();
4129
4130 if ($syntax_error) {
4131 foreach my $x (sort @nicks) {
4132 if($x =~ /^$word/i) {
4133 push(@$list, $x);
4134 }
4135 }
4136 }
4137 elsif ($counter == 0) {
4138 foreach my $x ((sort(@switches_combo, @switches_nocombo), sort(@nicks))) {
4139 if($x =~ /^$word/i) {
4140 push(@$list, $x);
4141 }
4142 }
4143 }
4144 elsif (($combo && $first_level_option && $second_level_option && $third_level_option) ||
4145 ($combo && $first_level_option && !$second_level_option && !$third_level_option))
4146 {
4147 my @switches_second_level = grep !/^-sub$/, map { $_ = "-$_" }
4148 keys %{ $switches{combo}{$first_level_option} };
4149
4150 foreach my $x ((sort(@switches_second_level), sort(@switches_combo), sort(@nicks))) {
4151 if($x =~ /^$word/i) {
4152 push(@$list, $x);
4153 }
4154 }
4155 }
4156 elsif ((!$combo && $counter == 1 && $first_level_option && $second_level_option && $third_level_option) ||
4157 (!$combo && $counter == 1 && $first_level_option && !$second_level_option && !$third_level_option))
4158 {
4159 my @switches_second_level = grep !/^-sub$/, map { $_ = "-$_" }
4160 keys %{ $switches{nocombo}{$first_level_option} };
4161
4162 foreach my $x (sort(@switches_second_level)) {
4163 if($x =~ /^$word/i) {
4164 push(@$list, $x);
4165 }
4166 }
4167 }
4168 elsif ($combo && $first_level_option && $second_level_option && !$third_level_option) {
4169 my @switches_third_level = grep !/^\*$/,
4170 keys %{ $switches{combo}{$first_level_option}{$second_level_option} };
4171
4172 foreach my $x (sort(@switches_third_level)) {
4173 if($x =~ /^$word/i) {
4174 push(@$list, $x);
4175 }
4176 }
4177 }
4178 elsif (!$combo && $counter == 1 && $first_level_option && $second_level_option && !$third_level_option) {
4179 my @switches_third_level = grep !/^\*$/,
4180 keys %{ $switches{nocombo}{$first_level_option}{$second_level_option} };
4181
4182 foreach my $x ((sort(@switches_third_level), sort(@nicks))) {
4183 if($x =~ /^$word/i) {
4184 push(@$list, $x);
4185 }
4186 }
4187 }
4188
4189 Irssi::signal_stop();
4190 }
4191
4192 sub signal_event_404 {
4193 my ($server, $message, $network_name) = @_;
4194
4195 if ($message =~ /^(?:\S+) (\S+) :Cannot send to channel$/) {
4196 my $channel_name = $1;
4197
4198 if ($server->{tag} eq $babble{channel}->{server}->{tag} &&
4199 $babble{channel}->{name} eq $channel_name &&
4200 defined($babble{timer_writing}))
4201 {
4202 Irssi::timeout_remove($babble{timer_writing});
4203 undef($babble{timer_writing});
4204 print_out("%9dau.pl:%9 Could not send message to $babble{channel}->{name}/$babble{channel}->{server}->{tag}. Cancelling babble.");
4205 return;
4206 }
4207 }
4208
4209 if ($message =~ /^(?:\S+) (\S+) :(.*)/) {
4210 Irssi::print("$1 $2");
4211 } else {
4212 Irssi::print($message);
4213 }
4214 }
4215
4216 sub signal_event_privmsg {
4217 my ($server, $data, $nick, $hostmask) = @_;
4218 my ($channel_name, $text) = split / :/, $data, 2;
4219 my $channel_rec = $server->channel_find($channel_name);
4220 $channel_name = lc($channel_name);
4221 my $server_name = lc($server->{tag});
4222 my %lookup;
4223
4224 while ($option{dau_remote_channellist} =~ /\s*([^\/]+)\/([^,]+)\s*,?/g) {
4225 my $channel = $1;
4226 $channel = lc($channel);
4227 my $ircnet = $2;
4228 $ircnet = lc($ircnet);
4229 $lookup{$ircnet}{$channel} = 1;
4230 }
4231 if (lc($option{dau_remote_channelpolicy}) eq 'allow') {
4232 return if ($lookup{$server_name}{$channel_name});
4233 } elsif (lc($option{dau_remote_channelpolicy}) eq 'deny') {
4234 return unless ($lookup{$server_name}{$channel_name});
4235 } else {
4236 return;
4237 }
4238
4239 # Remove formatting so dau.pl can reply to a colored, underlined, ...
4240 # question
4241
4242 $text =~ s/\003\d?\d?(?:,\d?\d?)?|\002|\006|\007|\016|\01f|\037//g;
4243
4244 my $regexp = switch_parse_special($option{dau_remote_question_regexp}, $channel_rec);
4245 if ($text =~ /$regexp/) {
4246 my $reply = return_random_list_item($option{dau_remote_question_reply});
4247 $reply =~ s/(?<![\\])\$nick/$nick/g;
4248 $reply = parse_text($reply, $channel_rec);
4249
4250 output_text($server, $channel_name, $reply);
4251 }
4252 }
4253
4254 sub signal_nick_mode_changed {
4255 my ($channel, $nick, $setby, $mode, $type) = @_;
4256 my ($reply, %lookup);
4257 my $channel_name = lc($channel->{name});
4258 my $network_name = lc($channel->{server}->{tag});
4259 my $op = $nick_mode{$network_name}{$channel_name}{op}; # mode before nick change
4260 my $voice = $nick_mode{$network_name}{$channel_name}{voice}; # mode before nick change
4261
4262 return if ($channel->{server}->{nick} ne $nick->{nick});
4263 if ($nick->{nick} eq $setby || $setby eq 'irc.psychoid.net') {
4264 build_nick_mode_struct();
4265 return;
4266 }
4267
4268 # Only act in channels where the user wants dau.pl to act
4269
4270 while ($option{dau_remote_channellist} =~ /\s*([^\/]+)\/([^,]+)\s*,?/g) {
4271 my $channel = $1;
4272 $channel = lc($channel);
4273 my $ircnet = $2;
4274 $ircnet = lc($ircnet);
4275 $lookup{$ircnet}{$channel} = 1;
4276 }
4277 if (lc($option{dau_remote_channelpolicy}) eq 'allow') {
4278 if ($lookup{$network_name}{$channel_name}) {
4279 build_nick_mode_struct();
4280 return;
4281 }
4282 } elsif (lc($option{dau_remote_channelpolicy}) eq 'deny') {
4283 unless ($lookup{$network_name}{$channel_name}) {
4284 build_nick_mode_struct();
4285 return;
4286 }
4287 } else {
4288 build_nick_mode_struct();
4289 return;
4290 }
4291
4292 # Now we are in the right channel
4293
4294 if ($option{dau_remote_permissions} =~ /^[01]1[01][01][01][01]$/) {
4295 if ($mode eq '+' && $type eq '+' && (!$voice && !$op)) {
4296 $reply = return_random_list_item($option{dau_remote_voice_reply});
4297 $reply =~ s/(?<![\\])\$nick/$setby/g;
4298 $reply = parse_text($reply, $channel);
4299 }
4300 }
4301 if ($option{dau_remote_permissions} =~ /^[01][01]1[01][01][01]$/) {
4302 if ($mode eq '@' && $type eq '+' && !$op) {
4303 $reply = return_random_list_item($option{dau_remote_op_reply});
4304 $reply =~ s/(?<![\\])\$nick/$setby/g;
4305 $reply = parse_text($reply, $channel);
4306 }
4307 }
4308 if ($option{dau_remote_permissions} =~ /^[01][01][01]1[01][01]$/) {
4309 if ($mode eq '+' && $type eq '-' && ($voice && !$op)) {
4310 $reply = return_random_list_item($option{dau_remote_devoice_reply});
4311 $reply =~ s/(?<![\\])\$nick/$setby/g;
4312 $reply = parse_text($reply, $channel);
4313 }
4314 }
4315 if ($option{dau_remote_permissions} =~ /^[01][01][01][01]1[01]$/) {
4316 if ($mode eq '@' && $type eq '-' && $op) {
4317 $reply = return_random_list_item($option{dau_remote_deop_reply});
4318 $reply =~ s/(?<![\\])\$nick/$setby/g;
4319 $reply = parse_text($reply, $channel);
4320 }
4321 }
4322
4323 # rebuild nick mode struct and print out the reply
4324
4325 build_nick_mode_struct();
4326 output_text($channel, $channel->{name}, $reply);
4327 }
4328
4329 sub signal_send_text {
4330 my ($data, $server, $witem) = @_;
4331 my $output;
4332
4333 return unless (defined($server) && $server && $server->{connected});
4334 return unless (defined($witem) && $witem &&
4335 ($witem->{type} eq 'CHANNEL' || $witem->{type} eq 'QUERY'));
4336
4337 if ($daumode{channels_out}{$server->{tag}}{$witem->{name}} == 1) {
4338 if ($daumode{channels_out_modes}{$server->{tag}}{$witem->{name}} eq '') {
4339 $output = parse_text($daumode{channels_out_modes}{$server->{tag}}{$witem->{name}} . $data, $witem);
4340 } else {
4341 $output = parse_text($daumode{channels_out_modes}{$server->{tag}}{$witem->{name}} . ' ' . $data, $witem);
4342 }
4343
4344 output_text($witem, $witem->{name}, $output);
4345
4346 Irssi::signal_stop();
4347 }
4348 }
4349
4350 sub signal_setup_changed {
4351 set_settings();
4352
4353 # setting changed/added => change/add it here
4354
4355 # setting cmdchars
4356
4357 $k = Irssi::parse_special('$k');
4358
4359 # babble history
4360
4361 if (defined($babble{history}) && ref($babble{history}) eq 'ARRAY') {
4362 my @history;
4363 my $i = 1;
4364 foreach (@{ $babble{history} } ) {
4365 if ($i++ <= $option{dau_babble_history_size}) {
4366 push(@history, $_);
4367 }
4368 }
4369 @{ $babble{history} } = @history;
4370 }
4371
4372 # setting dau_cowsay_cowpath
4373
4374 cowsay_cowlist($option{dau_cowsay_cowpath});
4375
4376 # setting dau_figlet_fontpath
4377
4378 figlet_fontlist($option{dau_figlet_fontpath});
4379
4380 # setting dau_daumode_channels
4381
4382 daumode_channels();
4383
4384 # setting dau_statusbar_daumode_hide_when_off
4385
4386 Irssi::statusbar_items_redraw('daumode');
4387
4388 # timer for the babble feature
4389
4390 timer_remote_babble_reset();
4391
4392 # signal handling
4393
4394 signal_handling();
4395 }
4396
4397 sub signals_daumode_in {
4398 my ($server, $data, $nick, $hostmask, $target) = @_;
4399 my $channel_rec = $server->channel_find($target);
4400 my $i_channel = $daumode{channels_in}{$server->{tag}}{$target};
4401 my $i_modes = $daumode{channels_in_modes}{$server->{tag}}{$target};
4402 my $modified_msg;
4403
4404 return unless (defined($server) && $server && $server->{connected});
4405
4406 # Not one of the channels where daumode for incoming messages is turned on.
4407 # In those channels print out the message as it is and leave the subroutine
4408
4409 if (!$i_channel) {
4410 return;
4411 }
4412
4413 # Evil Hack?
4414 # I had to dauify every incoming messages. Using &signal_continue was
4415 # not possible because --words f.e. generates output over multiple lines. So I
4416 # had to create multiple messages using &signal_emit. Those just created
4417 # messages shouldn't be dauified again when entering this subroutine. I
4418 # couldn't prevent irssi from entering this subroutine again after
4419 # dauifying the text so the messages had to be 'marked'. Marked
4420 # messages will not be dauified again. I think \x02 at the beginning of the
4421 # message is ok for that.
4422
4423 if ($data =~ s/^\x02//) {
4424 Irssi::signal_continue($server, $data, $nick, $hostmask, $target);
4425 } else {
4426 if ($i_modes ne '') {
4427 $modified_msg = parse_text($i_modes . ' ' . $data, $channel_rec);
4428 } else {
4429 $modified_msg = parse_text($data, $channel_rec);
4430 }
4431
4432 if ($modified_msg =~ /\n/) {
4433 for my $line (split /\n/, $modified_msg) {
4434 Irssi::signal_emit(Irssi::signal_get_emitted(), $server, "\x02$line", $nick, $hostmask, $target);
4435 Irssi::signal_stop();
4436 }
4437 } else {
4438 Irssi::signal_emit(Irssi::signal_get_emitted(), $server, "\x02$modified_msg", $nick, $hostmask, $target);
4439 Irssi::signal_stop();
4440 }
4441 }
4442 }
4443
4444 ################################################################################
4445 # Subroutines (statusbar)
4446 ################################################################################
4447
4448 sub statusbar_daumode {
4449 my ($item, $get_size_only) = @_;
4450 my ($status_in, $status_out, $modes_in, $modes_out);
4451 my $server = Irssi::active_server();
4452 my $witem = Irssi::active_win()->{active};
4453 my $theme = Irssi::current_theme();
4454 my $format = $theme->format_expand('{sb_daumode}');
4455
4456 if ($witem && ref($witem) &&
4457 $server && ref($server) &&
4458 ($witem->{type} eq 'CHANNEL' || $witem->{type} eq 'QUERY'))
4459 {
4460 if (defined($daumode{channels_in}{$server->{tag}}{$witem->{name}}) &&
4461 $daumode{channels_in}{$server->{tag}}{$witem->{name}} == 1)
4462 {
4463 $status_in = 'ON';
4464 } else {
4465 $status_in = 'OFF';
4466 }
4467
4468 if (defined($daumode{channels_out}{$server->{tag}}{$witem->{name}}) &&
4469 $daumode{channels_out}{$server->{tag}}{$witem->{name}} == 1)
4470 {
4471 $status_out = 'ON';
4472 } else {
4473 $status_out = 'OFF';
4474 }
4475
4476 # Hide statusbaritem if setting dau_statusbar_daumode_hide_when_off
4477 # is turned on and daumode is turned off
4478
4479 if ($status_in eq 'OFF' && $status_out eq 'OFF' && $option{dau_statusbar_daumode_hide_when_off}) {
4480 $item->{min_size} = $item->{max_size} = 0;
4481 return;
4482 }
4483
4484 if ($status_in eq 'ON') {
4485 $modes_in = $daumode{channels_in_modes}{$server->{tag}}{$witem->{name}} || $option{dau_standard_options};
4486 } else {
4487 $modes_in = '';
4488 }
4489 if ($status_out eq 'ON') {
4490 $modes_out = $daumode{channels_out_modes}{$server->{tag}}{$witem->{name}} || $option{dau_standard_options};
4491 } else {
4492 $modes_out = '';
4493 }
4494
4495 if ($format) {
4496 $format = $theme->format_expand("{sb_daumode $status_out $modes_out $status_in $modes_in}");
4497 } else {
4498 if ($status_in eq 'OFF' && $status_out eq 'OFF') {
4499 $format = $theme->format_expand("{sb daumode: <- $status_in | -> $status_out}");
4500 }
4501 elsif ($status_in eq 'OFF' && $status_out eq 'ON') {
4502 $format = $theme->format_expand("{sb daumode: <- $status_in | -> $status_out ($modes_out)}");
4503 }
4504 elsif ($status_in eq 'ON' && $status_out eq 'OFF') {
4505 $format = $theme->format_expand("{sb daumode: <- $status_in ($modes_in) | -> $status_out}");
4506 }
4507 elsif ($status_in eq 'ON' && $status_out eq 'ON') {
4508 $format = $theme->format_expand("{sb daumode: <- $status_in ($modes_in) | -> $status_out ($modes_out)}");
4509 }
4510 }
4511 } else {
4512 $item->{min_size} = $item->{max_size} = 0;
4513 return;
4514 }
4515
4516 $item->default_handler($get_size_only, $format, '', 1);
4517 }
4518
4519 ################################################################################
4520 # Subroutines (timer)
4521 ################################################################################
4522
4523 # for the babble remote feature
4524
4525 sub timer_away_reminder {
4526 my $id = shift;
4527 $id =~ m{^([^/]+)/(.+)};
4528 my $channel = $1;
4529 my $network = $2;
4530
4531 my $server_rec = Irssi::server_find_tag($network);
4532
4533 unless (defined($server_rec) && $server_rec) {
4534 return;
4535 }
4536
4537 my $channel_rec = $server_rec->channel_find($channel);
4538
4539 unless (defined($channel_rec) && $channel_rec &&
4540 ($channel_rec->{type} eq 'CHANNEL' || $channel_rec->{type} eq 'QUERY'))
4541 {
4542 return;
4543 }
4544
4545 ################################################################################
4546 # Open file
4547 ################################################################################
4548
4549 my $file = "$option{dau_files_root_directory}/$option{dau_files_away}";
4550 my @file;
4551 unless (tie(@file, 'Tie::File', $file)) {
4552 print_err("Cannot tie $file!");
4553 return;
4554 }
4555
4556 ################################################################################
4557 # Go through file
4558 ################################################################################
4559
4560 # Format:
4561 # channel | network | time | options | reminder | interval | reason
4562
4563 my ($time, $options, $reminder, $interval, $reason);
4564 foreach my $line (@file) {
4565 if ($line =~ m{^$channel\x02$network\x02(\d+)\x02([^\x02]*)\x02(\d)\x02(\d+)\x02(.*)}) {
4566 $time = $1;
4567 $options = $2;
4568 $reminder = $3;
4569 $interval = $4;
4570 $reason = $5;
4571 last;
4572 }
4573 }
4574
4575 ################################################################################
4576 # Special variables
4577 ################################################################################
4578
4579 my $output = $option{dau_away_reminder_text};
4580
4581 # $time
4582
4583 my $difference = time_diff_verbose(time, $time);
4584 $output =~ s/\$time/$difference/g;
4585
4586 # $reason
4587
4588 if ($option{dau_away_quote_reason}) {
4589 $reason =~ s/\\/\\\\/g;
4590 $reason =~ s/\$/\\\$/g;
4591 }
4592 $output =~ s/\$reason/$reason/g;
4593
4594 ################################################################################
4595 # Write text to channels. Write changes back to file
4596 ################################################################################
4597
4598 untie(@file);
4599
4600 $output = parse_text("$options $output", $channel_rec);
4601
4602 output_text($channel_rec, $channel_rec->{name}, $output);
4603 }
4604
4605 # all babbles: the writing to the channel
4606
4607 sub timer_babble_writing {
4608
4609 # check if we are still on the channel
4610
4611 my $onChannel = 0;
4612 foreach my $server (Irssi::servers()) {
4613 if ($server->{tag} eq $babble{channel}->{server}->{tag}) {
4614 foreach my $channel ($server->channels()) {
4615 if ($babble{channel}->{name} eq $channel->{name}) {
4616 if ($babble{channel} != $channel) {
4617 $babble{channel} = $channel;
4618 }
4619 $onChannel = 1;
4620 }
4621 }
4622 }
4623 }
4624 if (!$onChannel) {
4625 Irssi::timeout_remove($babble{timer_writing});
4626 print_out("%9dau.pl:%9 You are not on $babble{channel}->{name}/$babble{channel}->{server}->{tag}. Stalling babble.");
4627 return;
4628 }
4629
4630 # restore the variables
4631
4632 $command_out = $babble{command_out_history}{$babble{counter}};
4633 $command_out_activated = $babble{command_out_history_switch}{$babble{counter}};
4634
4635 # then output text
4636
4637 output_text($babble{channel}, $babble{channel}->{name}, $babble{line});
4638
4639 # And go to the "managing" subroutine...
4640
4641 timer_babble_writing_reset();
4642 }
4643
4644 # all babbles: the timer for the next writing
4645
4646 sub timer_babble_writing_reset {
4647 my $interval = 0;
4648
4649 # Remove used writing timer, if existent (at the first run we don't have any timer)
4650
4651 Irssi::timeout_remove($babble{timer_writing}) if (defined($babble{timer_writing}));
4652
4653 # At each run of this managing subroutine remove one line of text
4654
4655 $babble{text} =~ s/^(.*?)\n//;
4656 $babble{line} = $1;
4657
4658 if ($babble{line} =~ s/^BABBLE_INTERVAL=(\d+)\x02//) {
4659 $interval = $1;
4660 $babble{line} = parse_text("$option{dau_babble_options_line_by_line} $babble{line}");
4661 my $counter = $babble{counter} + 1;
4662 $babble{command_out_history}{$counter} = $command_out;
4663 $babble{command_out_history_switch}{$counter} = $command_out_activated;
4664 }
4665
4666 # If there is still some text left, add a new timer for the next line
4667
4668 if (length($babble{text}) != 0 || length($babble{line}) != 0) {
4669
4670 if ($babble{counter}++ == 0) {
4671 if ($option{dau_babble_verbose} && $babble{numberoflines} >= $option{dau_babble_verbose_minimum_lines}) {
4672 $babble{channel}->print("%9dau.pl:%9 Babbling $babble{numberoflines} line" . ($babble{numberoflines} > 1 ? 's' : '') . ' now:');
4673 }
4674 $interval = 50;
4675 }
4676
4677 if ($interval < 10) {
4678 # Calculate the writing breaks
4679 # The longer the next line is the longer the break will be
4680
4681 $interval = 1000 + rand(2000) +
4682 50 * length($babble{line}) +
4683 rand(25 * length($babble{line}));
4684
4685 # Some characters need more time to write
4686
4687 while ($babble{line} =~ /[^a-z ]/gio) {
4688 $interval += (75 + rand(25));
4689 }
4690
4691 $interval = int($interval);
4692 }
4693
4694 # Set timer
4695
4696 $babble{timer_writing} = Irssi::timeout_add($interval, \&timer_babble_writing, '');
4697 }
4698
4699 # No text left?
4700
4701 else {
4702 if ($option{dau_babble_verbose} && $babble{numberoflines} >= $option{dau_babble_verbose_minimum_lines}) {
4703 $babble{channel}->print('%9dau.pl:%9 Finished babbling.');
4704 }
4705
4706 # remove the timer
4707
4708 undef($babble{timer_writing});
4709
4710 if ($babble{remote}) {
4711 timer_remote_babble_reset();
4712 }
4713 }
4714 }
4715
4716 # remote babble: initialize
4717
4718 sub timer_remote_babble {
4719 my $text;
4720
4721 # Push all channels where it's ok to babble text in @channels
4722
4723 my %lookup;
4724 while ($option{dau_remote_babble_channellist} =~ /\s*([^\/]+)\/([^,]+)\s*,?/g) {
4725 my $channel = $1;
4726 $channel = lc($channel);
4727 my $ircnet = $2;
4728 $ircnet = lc($ircnet);
4729 $lookup{$ircnet}{$channel} = 1;
4730 }
4731
4732 my @channels;
4733 foreach my $server (Irssi::servers()) {
4734 my $server_name = lc($server->{tag});
4735
4736 foreach my $channel ($server->channels()) {
4737 my $channel_name = lc($channel->{name});
4738
4739 if (lc($option{dau_remote_babble_channelpolicy}) eq 'allow' &&
4740 !$lookup{$server_name}{$channel_name})
4741 {
4742 push(@channels, $channel);
4743 }
4744 elsif (lc($option{dau_remote_babble_channelpolicy}) eq 'deny' &&
4745 $lookup{$server_name}{$channel_name})
4746 {
4747 push(@channels, $channel);
4748 }
4749 }
4750 }
4751
4752 # No channels found => return
4753
4754 return if (@channels == 0);
4755
4756 # Choose one of the @channels
4757
4758 my $channel = $channels[rand(@channels)];
4759
4760 # If something is babbling right now, stop
4761
4762 if (defined($babble{timer_writing})) {
4763 return;
4764 }
4765
4766 # else get text from file
4767
4768 else {
4769 my @filter = ();
4770 $text = &babble_get_text($channel, \@filter, undef, $option{dau_babble_history_size});
4771 }
4772
4773 # Stop the timer for the big breaks.
4774
4775 Irssi::timeout_remove($babble{timer_remote}) if (defined($babble{timer_remote}));
4776
4777 # Start the writing.
4778
4779 babble_start($channel, $text, 1);
4780 }
4781
4782 # remote babble: reset
4783
4784 sub timer_remote_babble_reset {
4785 Irssi::timeout_remove($babble{timer_remote}) if (defined($babble{timer_remote}));
4786
4787 # Do not set the timer, if the permission-bit is not set
4788
4789 return unless ($option{dau_remote_permissions} =~ /^[01][01][01][01][01]1$/);
4790
4791 # Calculate interval
4792
4793 my $interval = babble_set_interval($option{dau_remote_babble_interval}, $option{dau_remote_babble_interval_accuracy});
4794
4795 # Set timer
4796
4797 if ($interval != 0) {
4798 $babble{timer_remote} = Irssi::timeout_add($interval, \&timer_remote_babble, '');
4799 }
4800 }
4801
4802 ################################################################################
4803 # Helper subroutines
4804 ################################################################################
4805
4806 sub babble_get_text {
4807 my ($channel, $filter, $nicks, $history_size) = @_;
4808 my $output;
4809
4810 # Return a random line from the dau_files_babble_messages file
4811
4812 my ($text, @file, @filterindex);
4813 my $file = "$option{dau_files_root_directory}/$option{dau_files_babble_messages}";
4814
4815 if (-e $file && -r $file) {
4816 unless (tie(@file, 'Tie::File', $file)) {
4817 print_err("Cannot tie $file!");
4818 return;
4819 }
4820 } else {
4821 print_err("Couldn't access babble file '$file'!");
4822 return;
4823 }
4824
4825 my @nicks_channel = ();
4826 my @opnicks_channel = ();
4827 if (defined($channel) && $channel && $channel->{type} eq 'CHANNEL') {
4828 foreach my $nick ($channel->nicks()) {
4829 next if ($channel->{server}->{nick} eq $nick->{nick});
4830 push(@nicks_channel, $nick->{nick});
4831 push(@opnicks_channel, $nick->{nick}) if ($nick->{op});
4832 }
4833 }
4834
4835 my @compiled_patterns_filter;
4836 eval { # possible user input here
4837 @compiled_patterns_filter = map { qr/$_/i } @$filter;
4838 };
4839 if ($@) {
4840 print_err("The %9-filter%9 you gave wasn't a valid regular expression.");
4841 print_err($@);
4842 return;
4843 }
4844 my $compiled_pattern_nicks = qr/(?<![\\])\$nick(\d+)/;
4845 my $compiled_pattern_ops = qr/(?<![\\])\$opnick(\d+)/;
4846
4847 my $i = 0;
4848 foreach my $line (@file) {
4849 my $add = 1;
4850
4851 # Every filter has to match
4852
4853 FILTER: foreach my $filter (@compiled_patterns_filter) {
4854 if ($line !~ /$filter/) {
4855 $add = 0;
4856 last FILTER;
4857 }
4858 }
4859
4860 # Check against history
4861
4862 if ($add) {
4863 my $i = 1;
4864 foreach (@{ $babble{history} }) {
4865 if ($i++ <= $history_size) {
4866 if ($line eq $_) {
4867 $add = 0;
4868 }
4869 }
4870 }
4871 }
4872
4873 # Don't babble at non-existent nicks
4874
4875 if ($add) {
4876 my $minimum_number_nicks = 0;
4877 while ($line =~ /$compiled_pattern_nicks/g) {
4878 if ($1 > $minimum_number_nicks) {
4879 $minimum_number_nicks = $1;
4880 }
4881 }
4882 if (defined($nicks) && @$nicks > 0) {
4883 if (scalar(@$nicks) < $minimum_number_nicks) {
4884 $add = 0;
4885 }
4886 } else {
4887 if (scalar(@nicks_channel) < $minimum_number_nicks) {
4888 $add = 0;
4889 }
4890 }
4891 }
4892
4893 # Don't babble at non-existent channel operators
4894
4895 if ($add) {
4896 if ($line =~ /$compiled_pattern_ops/) {
4897 my $minimum_number_ops = 0;
4898 while ($line =~ /$compiled_pattern_ops/g) {
4899 if ($1 > $minimum_number_ops) {
4900 $minimum_number_ops = $1;
4901 }
4902 }
4903 if (defined($nicks) && @$nicks > 0) {
4904 if (scalar(@$nicks) < $minimum_number_ops) {
4905 $add = 0;
4906 }
4907 } else {
4908 if (scalar(@opnicks_channel) < $minimum_number_ops) {
4909 $add = 0;
4910 }
4911 }
4912 }
4913 }
4914
4915 # Add the line as it passed all the tests
4916
4917 if ($add) {
4918 push(@filterindex, $i);
4919 }
4920 $i++;
4921 }
4922 $text = $file[$filterindex[int(rand(@filterindex))]];
4923
4924 if (@filterindex == 0) {
4925 print_err("Babble failed. Possible reasons: a) Too restrictive %9-filter%9 in place b) No matching lines in the babble file c) babble history holding that babble d) Not enough people in the channel");
4926 return;
4927 }
4928
4929 if (!$text) {
4930 print_err("No text to babble.");
4931 return;
4932 }
4933
4934 # Put babble in global history and shorten it, if necessary
4935
4936 @{ $babble{history} } = ($text, @{ $babble{history} });
4937 if (scalar(@{ $babble{history} }) > $option{dau_babble_history_size}) {
4938 pop(@{ $babble{history} });
4939 }
4940
4941 # dauify $text and return the dauified $output
4942
4943 my $options = $option{dau_babble_options_line_by_line};
4944
4945 # We have to keep track of the command history. --me and the --command
4946 # switch change the variables $command_out and $command_out_activated.
4947 # Because they are reset after every run of parse_text() they have to be kept
4948 # in a struct so that the writing timers later can do their job correctly.
4949
4950 my $counter = 1;
4951 $babble{command_out_history} = ();
4952 $babble{command_out_history_switch} = ();
4953
4954 # parse for special characters and substitute them
4955
4956 if (defined($nicks)) {
4957 if (@$nicks > 0) {
4958 for (my $i = 1; $i <= @$nicks; $i++) {
4959 $text =~ s/(?<![\\])\$nick$i/@$nicks[$i - 1]/g;
4960 }
4961 }
4962 $text = switch_parse_special($text, $channel);
4963 } else {
4964 $text = switch_parse_special($text, $channel);
4965 }
4966
4967 # Preprocessing options
4968
4969 if ($option{dau_babble_options_preprocessing} !~ /^\s*$/) {
4970 $text = parse_text("$option{dau_babble_options_preprocessing} \x02$text");
4971 $text =~ s/^\x02//;
4972 }
4973
4974 # Process $text line by line
4975
4976 $text =~ s/\\n/\n/g;
4977 $text =~ s/\n$//;
4978 while ($text =~ /(.*?)(\n|$)/g) {
4979 my $line = $1;
4980
4981 # Exit while loop when finished
4982
4983 last if ($2 ne "\n" && $1 eq "");
4984
4985 # Dauify text
4986
4987 my $newtext = parse_text("$options $line") . "\n";
4988
4989 $output .= $newtext;
4990
4991 # The parsed text ($newtext) can contain more than one line.
4992 # All $newtext lines have the same command.
4993 # The command (MSG, ACTION, ...) has to be remembered.
4994
4995 while ($newtext =~ /\n/g) {
4996 $babble{command_out_history}{$counter} = $command_out;
4997 $babble{command_out_history_switch}{$counter} = $command_out_activated;
4998 $counter++;
4999 }
5000 }
5001
5002 # Lines are separated by newline characters. Maybe there are to many of
5003 # them at the end of the string (probably produced by --figlet, --cowsay, ...).
5004 # That's disturbing the number of lines calculation later.
5005
5006 $output =~ s/\n{2,}$/\n/;
5007
5008 # $output contains now the text to be babbled. It will be split by
5009 # newlines by the babble subroutines and each line will be babbled with
5010 # the correct commands restored.
5011
5012 return $output;
5013 }
5014
5015 sub babble_interval {
5016 return "BABBLE_INTERVAL=" . babble_set_interval(@_) . "\x02";
5017 }
5018
5019 sub babble_set_interval {
5020 my ($time, $accuracy) = @_;
5021
5022 my $interval = time_parse($time);
5023
5024 my $addend;
5025 if ($accuracy == 100) {
5026 $addend = 0;
5027 } elsif ($accuracy > 0 && $accuracy < 100) {
5028 $addend = rand($interval - ($interval * ($accuracy / 100)));
5029 } else {
5030 print_err('Invalid accuracy value');
5031 return;
5032 }
5033
5034 if (int(rand(2))) {
5035 $interval = $interval + $addend;
5036 } else {
5037 $interval = $interval - $addend;
5038 }
5039
5040 $interval = int($interval);
5041
5042 if ($interval < 10 || $interval > 1000000000) {
5043 print_err('Invalid interval value');
5044 return 0;
5045 }
5046
5047 return $interval;
5048 }
5049
5050 sub babble_start {
5051 my ($channel_rec, $text, $remote) = @_;
5052
5053 # These are some global variables for the writing timer
5054
5055 $babble{channel} = $channel_rec;
5056 $babble{counter} = 0;
5057 $babble{text} = "$text\n";
5058 $babble{numberoflines} = 0;
5059 $babble{numberoflines}++ while ($babble{text} =~ /\n/g);
5060 $babble{numberoflines} -= 1;
5061 $babble{remote} = $remote;
5062
5063 Irssi::timeout_remove($babble{timer_writing}) if (defined($babble{timer_writing}));
5064
5065 timer_babble_writing_reset();
5066 }
5067
5068 sub build_nick_mode_struct {
5069 undef(%nick_mode);
5070
5071 foreach my $server (Irssi::servers()) {
5072 my $network_name = lc($server->{tag});
5073
5074 foreach my $channel ($server->channels()) {
5075 my $channel_name = lc($channel->{name});
5076 my $op = $channel->{ownnick}{op};
5077 my $voice = $channel->{ownnick}{voice};
5078
5079 $nick_mode{$network_name}{$channel_name}{op} = $op;
5080 $nick_mode{$network_name}{$channel_name}{voice} = $voice;
5081 }
5082 }
5083 }
5084
5085 sub daumode_channels {
5086 my @items;
5087 my $item;
5088 while ($option{dau_daumode_channels} =~ /([^,]+)/g) {
5089 my $match = $1;
5090 if ($match =~ s/\\$//) {
5091 $item .= "$match,";
5092 } else {
5093 $item .=