html/mangle.pl
1 #!/usr/bin/perl
2 #
3 # by Szymon Sokol <szymon@hell.pl>
4 # ideas taken from BabelIRC by Stefan Tomanek
5 #
6
7 use strict;
8 use locale;
9 use Irssi 20020324;
10 use POSIX;
11 use Data::Dumper;
12
13 use vars qw($VERSION %IRSSI %HELP %channels %translations);
14 $VERSION = '2004031701';
15 %IRSSI = (
16 authors => 'Szymon Sokol',
17 contact => 'szymon@hell.pl',
18 name => 'mangle',
19 description => 'translates your messages into Morse code, rot13 and other sillinesses.',
20 license => 'GPLv2',
21 url => 'http://irssi.org/scripts/', changed => $VERSION,
22 modules => 'Data::Dumper'
23 );
24
25 # To work, this help requires scripthelp.pl by Maciek 'fahren' Freudenheim
26 $HELP{"mangle add"} = "/mangle add <translation> [<channel>]
27 Add a new translation entry for <channel> (default is current channel)";
28 $HELP{"mangle del"} = "/mangle del [<channel>]
29 Removes the translation for <channel> (default is current channel)";
30 $HELP{"mangle say"} = "/mangle say <translation> <message>
31 Says something to the current channel using given translation";
32 $HELP{"mangle load"} = "/mangle load
33 Loads translations from file";
34 $HELP{"mangle save"} = "/mangle save
35 Saves active translations to file";
36 $HELP{"mangle show"} = "/mangle show
37 Shows active translations";
38 $HELP{"mangle list"} = "/mangle list
39 Lists available translations";
40
41 # the endless possibilities for extensions here
42 %translations = (
43 # CChheecckk yyoouurr dduupplleexx sswwiittcchh
44 "duplex" => sub {
45 my ($text) = @_;
46 $text =~ s/./$&$&/g;
47 return $text;
48 },
49 # TaLk LiKe ThIs - EvErY OtHeR LeTtEr Is UpPeRcAse
50 "funky" => sub {
51 my ($text) = @_;
52 $text =~ s/(\w.)/\u$1/g;
53 return $text;
54 },
55 # TalkLikeThis-NoSpaces,WordBeginsWithUppercase
56 "gnome" => sub {
57 my ($text) = @_;
58 $text =~ s/\b(\w)/\u$1/g;
59 $text =~ s/\s+//g;
60 return $text;
61 },
62 # -- --- .-. ... . -.-. --- -.. .
63 "morse" => sub {
64 my %morse = (
65 " " => "",
66 "a" => ".-",
67 "b" => "-...",
68 "c" => "-.-.",
69 "d" => "-..",
70 "e" => ".",
71 "f" => "..-.",
72 "g" => "--.",
73 "h" => "....",
74 "i" => "..",
75 "j" => ".---",
76 "k" => "-.-",
77 "l" => ".-..",
78 "m" => "--",
79 "n" => "-.",
80 "o" => "---",
81 "p" => ".--.",
82 "q" => "--.-",
83 "r" => ".-.",
84 "s" => "...",
85 "t" => "-",
86 "u" => "..-",
87 "v" => "...-",
88 "w" => ".--",
89 "x" => "-..-",
90 "y" => "-.--",
91 "z" => "--..",
92 # notice: Polish and German diacritical characters have their own
93 # Morse codes; the same probably stands true for other languages
94 # using ISO-8859-2 - if you happen to know them, please send me e-mail
95 "±" => ".-.-",
96 "æ" => "-.-..",
97 "ê" => "..-..",
98 "³" => ".-..-",
99 "ñ" => "--.-",
100 "ó" => "---.".
101 "¶" => "...-...",
102 "¼" => "--..",
103 "¿" => "--..-",
104 'ä'=>'.-.-',
105 'ö'=>'---.',
106 'ü'=>'..--',
107 "0" => "-----",
108 "1" => ".----",
109 "2" => "..---",
110 "3" => "...--",
111 "4" => "....-",
112 "5" => ".....",
113 "6" => "-....",
114 "7" => "--...",
115 "8" => "---..",
116 "9" => "----.",
117 "'" => ".----.",
118 '"' => ".-..-.",
119 '.' => ".-.-.-",
120 ',' => "--..--",
121 '?' => "..--..",
122 ':' => "---...",
123 ';' => "-.-.-.",
124 '-' => "-....-",
125 '_' => "..--.-",
126 '/' => "-..-.",
127 '(' => "-.--.",
128 ')' => "-.--.-",
129 '@' => ".--.-.", # byFlorian Ernst <florian@uni-hd.de>
130 '=' => "-...-"
131 );
132 my ($text) = @_;
133 $text = lc($text);
134 $text =~ s/./defined $morse{$&} ? $morse{$&}." " : ""/eg;
135 return $text.'[morse]';
136 },
137 # convert text in Polish from ISO-8859-2 to 7-bit approximation
138 # if you know how to do it for other languages using 8859-2,
139 # please let me know
140 "polskawe" => sub {
141 my ($text) = @_;
142 $text =~ y/¡ÆÊ£ÑÓ¦¯¬±æê³ñó¶¿¼/ACELNOSZZacelnoszz/;
143 return $text;
144 },
145 # Ouch, my eyes!
146 "rainbow" => sub {
147 my ($text) = @_;
148 # colors list
149 # 0 == white
150 # 4 == light red
151 # 8 == yellow
152 # 9 == light green
153 # 11 == light cyan
154 # 12 == light blue
155 # 13 == light magenta
156 my @colors = ('00','04','08','09','11','12','13');
157 my $color;
158 $text = join '', map { push @colors, $color = shift @colors;
159 "\003" . $color . ($_ eq "," ? ",," : $_) } split(//,$text);
160 return $text;
161 },
162 # .drawkcab klaT
163 "reverse" => sub {
164 my ($text) = @_;
165 $text = scalar reverse $text;
166 return $text;
167 },
168 # Gnyx va ebg13 rapbqvat.
169 "rot13" => sub {
170 my ($text) = @_;
171 $text =~ y/N-ZA-Mn-za-m/A-Za-z/;
172 return $text.' [rot13]';
173 },
174 # T-T-Talk l-l-like y-y-you h-h-have a s-s-stutter.
175 "stutter" => sub {
176 my ($text) = @_;
177 $text =~ s/(\w)(\w+)/$1-$1-$1$2/g;
178 return $text;
179 },
180 # rmv vwls
181 "vowels" => sub {
182 my ($text) = @_;
183 $text =~ y/aeiouy±ê//d;
184 return $text;
185 }
186 );
187
188 sub add_channel ($$) {
189 my ($channel,$code) = @_;
190 $channels{$channel} = $code;
191 }
192
193 sub save_channels {
194 my $filename = Irssi::settings_get_str('mangle_filename');
195 local *F;
196 open F, '>'.$filename;
197 my $data = Dumper(\%channels);
198 print F $data;
199 close F;
200 print CLIENTCRAP "%R>>%n Mangle channels saved";
201 }
202
203 sub load_channels {
204 my $filename = Irssi::settings_get_str('mangle_filename');
205 return unless (-e $filename);
206 local *F;
207 open F, '<'.$filename;
208 my $text;
209 $text .= $_ foreach <F>;
210 no strict "vars";
211 %channels = %{ eval "$text" };
212 }
213
214 sub mangle_show ($$) {
215 my ($item, $get_size_only) = @_;
216 my $win = !Irssi::active_win() ? undef : Irssi::active_win()->{active};
217 if (ref $win && ($win->{type} eq "CHANNEL" || $win->{type} eq "QUERY") && $channels{$win->{name}}) {
218 my $code = $channels{$win->{name}};
219 $item->{min_size} = $item->{max_size} = length($code);
220 $code = '%U%g'.$code.'%U%n';
221 my $format = "{sb ".$code."}";
222 $item->default_handler($get_size_only, $format, 0, 1);
223 } else {
224 $item->{min_size} = $item->{max_size} = 0;
225 }
226 }
227 sub cmd_mangle ($$$) {
228 my ($args, $server, $witem) = @_;
229 my @arg = split(/ +/, $args);
230 if ($arg[0] eq 'add' && defined $arg[1]) {
231 my $code = $arg[1];
232 if(exists $translations{$code}) {
233 if (defined $arg[2]) {
234 add_channel($arg[2], $code);
235 }
236 elsif($witem) {
237 add_channel($witem->{name}, $code);
238 }
239 } else {
240 Irssi::print("There is no such translation as $code !");
241 }
242 } elsif ($arg[0] eq 'del') {
243 if(defined $arg[1]) {
244 delete $channels{$arg[1]} if defined $channels{$arg[1]};
245 } elsif($witem) {
246 delete $channels{$witem->{name}} if defined $channels{$witem->{name}};
247 }
248 } elsif ($arg[0] eq 'say' && defined $arg[1]) {
249 my $code = $arg[1];
250 if(exists $translations{$code}) {
251 if($witem) {
252 say($code, join(' ',@arg[2..$#arg]), $server, $witem);
253 }
254 } else {
255 Irssi::print("There is no such translation as $code !");
256 }
257 } elsif ($arg[0] eq 'save') {
258 save_channels();
259 } elsif ($arg[0] eq 'load') {
260 load_channels();
261 } elsif ($arg[0] eq 'list') {
262 Irssi::print("mangle: available translations are: ".
263 join(" ", sort keys %translations));
264 } elsif ($arg[0] eq 'show') {
265 for (sort keys %channels) {
266 Irssi::print("mangle: ".$_." set to ".$channels{$_});
267 }
268 } else {
269 Irssi::print("mangle v. $VERSION; use /help mangle for help (ensure you have scripthelp.pl loaded!)");
270 }
271 Irssi::statusbar_items_redraw('mangle_sb');
272 }
273
274 sub say ($$$$) {
275 my ($code, $line, $server, $witem) = @_;
276 my $target = "";
277 if ($line =~ s/^(\w+?: )//) {
278 $target = $1;
279 }
280 $line = $translations{$code}->($line);
281 $server->command('MSG '.$witem->{name}.' '.$target.$line);
282 }
283
284 sub event_send_text ($$$) {
285 my ($line, $server, $witem) = @_;
286 return unless ($witem &&
287 ($witem->{type} eq "CHANNEL" || $witem->{type} eq "QUERY") &&
288 $channels{$witem->{name}});
289 say($channels{$witem->{name}}, $line, $server, $witem);
290 Irssi::signal_stop();
291 Irssi::statusbar_items_redraw('mangle_sb');
292 }
293
294 # main
295
296 Irssi::command_bind('mangle', \&cmd_mangle);
297 foreach my $cmd ('add', 'del', 'save', 'load', 'say', 'list', 'show') {
298 Irssi::command_bind('mangle '.$cmd => sub {
299 cmd_mangle($cmd." ".$_[0], $_[1], $_[2]); });
300 }
301
302 Irssi::statusbar_item_register('mangle_sb', 0, "mangle_show");
303 Irssi::signal_add('setup saved', 'save_channels');
304 Irssi::signal_add('send text', \&event_send_text);
305 Irssi::signal_add('window changed', sub {Irssi::statusbar_items_redraw('mangle_sb');});
306
307 Irssi::settings_add_str($IRSSI{name}, 'mangle_filename', Irssi::get_irssi_dir()."/mangle_channels");
308 load_channels();
309 print CLIENTCRAP '%B>>%n '.$IRSSI{name}.' '.$VERSION.' loaded: /help mangle for help';
310
311 # ;-)