ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-Knuddels/eg/knuddels2irc2
Revision: 1.1
Committed: Mon Jan 24 01:42:06 2005 UTC (21 years, 7 months ago) by elmex
Branch: MAIN
Log Message:
new knuddels irc client

File Contents

# User Rev Content
1 elmex 1.1 #!/usr/bin/perl
2     package Knuddler;
3    
4     sub new {
5     my $class = shift;
6     my $self = bless { @_ }, $class;
7     $self;
8     }
9    
10     sub set_ircclient {
11     my ($self, $icl) = @_;
12     $self->{icl} = $icl;
13     }
14    
15     sub room_to_irc {
16     my ($self, $room) = @_;
17     my $o = $room;
18    
19     $room =~ s/[ ]/_/g;
20     $room =~ s/[^a-zA-Z0-9_-]*//g;
21     print "r2i '$o' -> '#$room'\n";
22     $self->{c2r}->{lc "#$room"} = $o;
23     lc "#$room"
24     }
25    
26     sub irc_to_room {
27     my ($self, $ircchan) = @_;
28     if (not defined $self->{c2r}->{lc $ircchan}) {
29     $ircchan =~ s/^#//;
30     $ircchan =~ s/_/ /g;
31     return $ircchan;
32     }
33     return $self->{c2r}->{lc $ircchan};
34     }
35    
36     sub knuddler_to_nick {
37     my ($self, $knuddler) = @_;
38    
39     return $self->{k2n}->{lc $orig_knick}
40     if defined $self->{k2n}->{lc $orig_knick};
41    
42     my $orig_knick = $knuddler;
43     $knuddler =~ s/[ ]/_/g;
44     $knuddler =~ s/[<]/{/g;
45     $knuddler =~ s/[>]/}/g;
46     $knuddler =~ s/[=]/^/g;
47     $knuddler =~ s/[&]/\\/g;
48     $knuddler =~ s/[+]/_/g;
49     $knuddler =~ s/[\344]/ae/g;
50     $knuddler =~ s/[\324]/Ae/g;
51     $knuddler =~ s/[\366]/oe/g;
52     $knuddler =~ s/[\346]/Oe/g;
53     $knuddler =~ s/[\374]/ue/g;
54     $knuddler =~ s/[\334]/Ue/g;
55     $knuddler =~ s/[\337]/ss/g;
56     $knuddler =~ s/[^a-zA-Z0-9_-]*//g;
57    
58    
59     if (defined $self->{n2k}->{lc $knuddler}) {
60     my $d = 2;
61    
62     while (defined $self->{n2k}->{lc ($knuddler.$d)}) {
63     $d++;
64     }
65     $knuddler = $knuddler.$d;
66     }
67    
68     $self->{n2k}->{lc $knuddler} = $orig_knick;
69     $self->{k2n}->{lc $orig_knick} = $knuddler;
70    
71     return $knuddler;
72     }
73    
74     sub nick_to_knuddler {
75     my ($self, $nick) = @_;
76    
77     return $self->{n2k}->{lc $nick}
78     if defined $self->{n2k}->{lc $nick};
79    
80     $nick =~ s/_/ /g;
81    
82     return $nick;
83     }
84    
85     sub activate_client {
86     my ($self, $knuddelnick, $kpass) = @_;
87     $self->{active} = 1;
88     $self->{knuddelnick} = $knuddelnick;
89     $self->{knuddelpass} = $kpass;
90     }
91    
92     sub ircprfx {
93     my ($self, $nick) = @_;
94     $self->{s}->mk_clpref ({ nickname => $nick, username => "knuddler", hostname => "knuddels.de", registered => 1 })
95     }
96    
97     sub replace_msg_nicks {
98     my ($self, $msg) = @_;
99    
100     for (keys %{$self->{n2k}}) {
101     my $n = $self->{n2k}->{$_};
102    
103     if ($msg =~ s/\b\Q$_\E\b/$n/gi) { last }
104     }
105     return $msg;
106     }
107    
108     sub handle_room_msg {
109     my ($self, $room, $user, $msg) = @_;
110    
111     $room = $self->room_to_irc ($room);
112    
113     my $kn = $self->knuddler_to_nick ($user);
114    
115     $self->{s}->send_msg ($self->{icl}, $self->ircpre ($kn), "PRIVMSG", $msg, $room);
116     }
117    
118     sub handle_priv_msg {
119     my ($self, $src, $dst, $msg) = @_;
120     return if $src =~ m/^James\d*$/ and $msg =~ m/Funktion.*knuschel.*gibt.*leider.*nich.*/i;
121    
122     my $src = $self->knuddler_to_nick ($src);
123     # not of much meaning ;) # my $dstcl = $knuddel_channels{room_to_irc $room}->{knd}->{lc $dst};
124    
125     $self->{s}->send_msg ($self->{icl}, $self->ircpre ($src), "PRIVMSG", $msg, $self->{icl});
126     }
127    
128     sub irc_srvpre {
129     my $self = shift;
130     $self->{s}->mk_clpref ({ nickname => "}", username => "server", hostname => "localhost" });
131     }
132    
133     sub handle_room_action {
134     my ($self, $room, $action) = @_;
135     $self->{s}->send_msg ($self->{icl}, $self->irc_srvpre (), "PRIVMSG", $action, room_to_irc ($room));
136     }
137    
138     sub send_exit_room {
139     my ($self, $ircchan) = @_;
140    
141     my $room = $self->irc_to_room ($ircchan);
142    
143     $self->{s}->send_msg ($self->{icl}, $self->{s}->mk_clpref ($self->{icl}), "PART", "parted", $ircchan);
144    
145     delete $self->{rooms}->{lc $room};
146     delete $self->{channels}->{lc $ircchan};
147     delete $self->{myrooms}->{lc $room};
148    
149     $self->{c}->send_exit_room ($self->irc_to_room ($ircchan));
150     }
151    
152    
153     sub send_enter_room {
154     my ($self, $ircchan) = @_;
155    
156     my $room = $self->irc_to_room ($ircchan);
157    
158     $self->{c}->enter_room ($room, $self->{knuddelsnick}, $self->{knuddelspass});
159     }
160    
161     sub handle_userlist {
162     my ($self, $room, $list) = @_;
163    
164     for (values %$list) {
165     $self->join_knuddler ($_->{name}, $_->{age}, $_->{gender}, $room);
166     }
167    
168     $self->send_nameslist ($self->room_to_irc ($room));
169     }
170    
171     sub handle_dialog {
172     my ($self, $d) = @_;
173     for my $l (@$d) {
174     $l =~ s/\260[^\260]*female[^\260]*\260/weiblich/i;
175     $l =~ s/\260[^\260]*male[^\260]*\260/maennlich/i;
176     $l =~ s/\260[^\260]*\260//g;
177    
178     $ircsrv->send_msg ($self->{icl}, $self->irc_srvpre (), "NOTICE", $l, $self->{icl}->{nickname});
179     }
180     }
181    
182     sub send_nameslist {
183     my ($self, $ic) = @_;
184    
185     my $i = 1;
186     my @part;
187    
188     for (keys %{$self->{channels}->{lc $ic}}) {
189     $i++;
190     push @part, $_;
191    
192     if ($i % 10 == 0) {
193     $self->{s}->send_srv_msg ($self->{icl}, "353", join (' ', @part), $self->{icl}->{nickname}, "=", $ic);
194     @part = ();
195     }
196     }
197     if (@part) {
198     $self->{s}->send_srv_msg ($self->{icl}, "353", join (' ', @part), $self->{icl}->{nickname}, "=", $ic);
199     }
200     $self->{s}->send_srv_msg ($self->{icl}, "366", "End of NAMES list", $self->{icl}->{nickname}, $ic);
201     }
202    
203     sub join_knuddler {
204     my ($self, $knuddler, $age, $gender, $room) = @_;
205     my $ic = $self->room_to_irc ($room);
206     my $in = $self->knuddler_to_nick ($knuddler);
207    
208     my $i = {
209     nickname => $in,
210     knuddelnick => $knuddler,
211     age => $age,
212     gender => $gender
213     };
214    
215     $self->{channels}->{lc $ic}->{lc $in}->{info} =
216     $self->{rooms}->{lc $room}->{lc $knuddler}->{info} = $i;
217    
218     $self->{s}->send_msg ($self->{icl}, $self->ircpre ($in), "JOIN", $ic);
219     }
220    
221     sub part_knuddler {
222     my ($knuddler, $room) = @_;
223     my $ic = $self->room_to_irc ($room);
224     my $in = $self->knuddler_to_nick ($knuddler);
225    
226     delete $self->{channels}->{lc $ic}->{lc $in};
227     delete $self->{rooms}->{lc $room}->{lc $knuddler};
228    
229     $self->{s}->send_msg ($self->{icl}, $self->ircpre ($in), "PART", "parted nick", $ic);
230     }
231    
232     sub handle_room_list {
233     my ($self, $rooms) = @_;
234     $self->room_to_irc ($_) for keys %$rooms;
235     }
236    
237     sub change_room {
238     my ($self, $oroom, $nroom) = @_;
239    
240     my $oic = $self->room_to_irc ($oroom);
241     my $nic = $self->room_to_irc ($nroom);
242    
243     delete $self->{rooms}->{lc $oroom};
244     delete $self->{channels}->{lc $oic};
245    
246     delete $self->{myrooms}->{lc $oroom};
247     $self->{myrooms}->{lc $nroom} = 1;
248    
249     $self->{s}->send_msg ($self->{icl}, $self->{s}->mk_clpref ($self->{icl}), "PART", "change room", $oic);
250     $self->{s}->send_msg ($self->{icl}, $self->{s}->mk_clpref ($self->{icl}), "JOIN", undef, $nic);
251     }
252    
253     sub handle_room_info {
254     my ($self, $room, $ri) = @_;
255    
256     $self->{myrooms}->{lc $room} = 1;
257     $self->{s}->send_msg ($self->{icl}, $self->{s}->mk_clpref ($self->{icl}), "JOIN", undef, $self->room_to_irc ($room));
258     }
259    
260    
261     sub find_any_room {
262     my ($self) = @_;
263    
264     return (keys %{$self->{myrooms}})[0];
265     }
266    
267     sub send_keepalive_client {
268     my ($self) = @_;
269     my $r = $self->find_any_room ();
270    
271     print "KNUDDELS PING\n";
272     return if not defined $r;
273     print "PING TO $f->{knuddelroom} $f->{knuddelnick}\n";
274    
275     $self->{c}->send_room_msg ($r, "/knuschel");
276     }
277    
278     package main;
279     use strict;
280     use lib '../Net-IRC-Server/';
281     use IO::Select;
282     use Socket;
283     use IO::Socket::INET;
284     use Event;
285     use Net::Knuddels;
286     use Net::IRC::Server;
287     use YAML;
288    
289     my %CFG = (
290     server_cl_nick => "_",
291     server_cl_user => "server",
292     server_cl_host => "localhost",
293     server_prefix => "test.de",
294    
295     knuddel_nick => "Net-Knuddels",
296     knuddel_pass => "lolfe",
297     knuddel_chan => "Flirt Private",
298     );
299    
300     scan_config ();
301    
302     my $KDL;
303     my $client;
304     my $ircsrv;
305     my $irc_client;
306    
307     sub scan_config {
308     my $config = $ENV{HOME}."/.knuddels2irc2.rc";
309    
310     if (! -e $config) { return; }
311    
312     my $h = YAML::LoadFile $config;
313    
314     if (defined $h and ref $h eq "HASH") {
315     %CFG = (%CFG, %$h);
316     } else {
317     die "$config is not a map!";
318     }
319     }
320    
321     sub ready_irc_server {
322     $ircsrv = Net::IRC::Server->new (srv_prefix => $CFG{server_prefix});
323    
324     $ircsrv->set_send_cb (sub {
325     my ($cl, $data, @msg) = @_;
326    
327     if (not defined $cl->{socket}) {
328     return 1;
329     }
330    
331     }, 'PRIVMSG');
332    
333     $ircsrv->set_cmd_cb ('*', sub {
334     my $c = uc $_[1]->{command};
335     return 1;
336     }); # default handler ;) Overwrite _anything_ the server does
337    
338     $ircsrv->set_cmd_cb ('PING', sub {
339     my ($cl, $msg) = @_;
340     $ircsrv->send_srv_msg ($cl, "PONG", $msg->{params}->[0]);
341     });
342     $ircsrv->set_cmd_cb ('NICK', sub {
343     my ($cl, $msg) = @_;
344     $cl->{nickname} = $msg->{params}[0];
345     });
346    
347     $ircsrv->set_cmd_cb ('USER', sub {
348     my ($cl, $msg) = @_;
349     $cl->{username} = $msg->{params}->[0];
350     $cl->{realname} = $msg->{params}->[3];
351    
352     $ircsrv->send_srv_msg ($irc_client,
353     "001",
354     "Welcome to NET::IRCServer! "
355     . $ircsrv->mk_clpref ($cl),
356     $cl->{nickname});
357     });
358    
359     $ircsrv->set_cmd_cb ('NAMES', sub {
360     my ($cl, $msg) = @_;
361     return if not defined $msg->{params}[0];
362     $KDL->send_nameslist ($msg->{params}[0]);
363     });
364    
365     $ircsrv->set_cmd_cb ('PART', sub {
366     my ($cl, $msg) = @_;
367     $KDL->send_exit_room ($msg->{params}[0]);
368     });
369    
370     $ircsrv->set_cmd_cb ('JOIN', sub {
371     my ($cl, $msg) = @_;
372     print "ENTER ROOM: $msg->{params}[0]\n";
373     $KDL->send_enter_room ($msg->{params}[0]);
374     });
375    
376     $ircsrv->set_cmd_cb ('LIST', sub {
377    
378     # for (sort { $a cmp $b } keys %knuddel_channels) {
379     # my $chan = $knuddel_channels{$_};
380     # my $c = room_to_irc ($chan->{name});
381    
382     # $ircsrv->send_srv_msg (
383     # $irc_client,
384     # "322",
385     # $chan->{name} . ($chan->{full_flag} ? " (full)" : ""),
386     # $irc_client->{nickname},
387     # "$c",
388     # $chan->{user_count});
389     # }
390     # $ircsrv->send_srv_msg ($irc_client, "323", "End of LIST", $irc_client->{nickname});
391     });
392    
393     # $ircsrv->set_cmd_cb ('WHOIS', sub {
394     # my ($cl, $msg) = @_;
395     # my $kcl = $irc_to_knuddel{lc $msg->{params}->[0]};
396     #
397     # $client->send_whois ($kcl->{knuddelroom}, $kcl->{knuddelnick});
398     #
399     # return 1;
400     # });
401    
402     $ircsrv->set_cmd_cb ('PRIVMSG', sub {
403     =pod
404     my ($cl, $msg) = @_;
405    
406     my $targ = $msg->{params}->[0];
407     my $imsg = scan_msg_nicks $msg->{params}->[1];
408    
409     $imsg =~ s/(?<!\\)#/\//;
410     $imsg =~ s/^\\#/#/;
411    
412     if (defined $knuddel_channels{lc $targ}) {
413    
414     $client->send_room_msg (irc_to_room ($targ), $imsg);
415    
416     return 1;
417     } elsif (defined $irc_to_knuddel{lc $targ}) {
418     my $cl = $irc_to_knuddel{lc $targ};
419    
420     $client->send_priv_msg ($cl->{knuddelnick}, $cl->{knuddelroom}, $imsg);
421     return 1;
422     }
423     return 0;
424     =cut
425     });
426    
427     $ircsrv->set_send_cb (sub {
428     my ($cl, $data) = @_;
429    
430     if (defined $cl->{socket}) { # a knuddels-client
431    
432     $cl->{socket}->syswrite ($data);
433     print "send $cl->{nickname}> $data"
434     }
435     });
436    
437     my $sock = IO::Socket::INET->new(
438     Listen => 5,
439     # LocalAddr => localhost,
440     LocalPort => 6667,
441     Proto => 'tcp',
442     ReuseAddr => 1);
443    
444     if (!$sock) { die "Couldn't get listening socket: $!\n" }
445    
446     Event->io (
447     fd => $sock,
448     poll => 'r',
449     cb => sub {
450     my $newfh = $sock->accept ();
451     my $addr = $newfh->sockaddr ();
452    
453     if (defined $irc_client) {
454     $newfh->close;
455     print "NEWCL\n";
456     return;
457     }
458    
459     $irc_client = { hostname => inet_ntoa ($addr), socket => $newfh };
460     $KDL->set_ircclient ($irc_client);
461    
462     Event->io (
463     fd => $newfh,
464     poll => 'r',
465     cb => sub {
466     my ($e) = @_;
467    
468     my $data;
469     my $c = $newfh->sysread ($data, 2048);
470     print "recv $irc_client->{nickname}> $data";
471    
472     if ($c == 0) {
473     $e->w->cancel ();
474     $newfh->close ();
475    
476     } else {
477     $ircsrv->feed_irc_data ($irc_client, $data);
478     }
479     });
480     });
481     }
482     sub connect_knuddels {
483     $client->login;
484     Event->io (
485     fd => $client->fh,
486     poll => 'r',
487     cb => sub {
488     my $e = shift;
489    
490     if (not $client->ready) {
491     $e->w->cancel;
492     }
493     });
494     }
495    
496     ####################################################################################
497     ########################## MAIN START ##############################################
498     ####################################################################################
499    
500     $client = new Net::Knuddels::Client PeerAddr => "213.61.5.150:2710";
501     $KDL = new Knuddler c => $client, s => $ircsrv;
502    
503    
504     $client->register (UNHANDLED => sub {
505     use Dumpvalue;
506     print "---\n";
507     Dumpvalue->new (compactDump => 1, veryCompact => 1, quoteHighBit => 1, tick => '"')->dumpValue ([@_]);
508     });
509    
510     $client->register (login => sub {
511     $KDL->activate_client;
512    
513     Event->timer (interval => 60, cb => sub {
514     $KDL->send_keepalive_client ();
515     });
516     });
517    
518     $client->register (msg_room => sub {
519     my ($room, $user, $msg) = @_;
520     print "($room) =========== $user: $msg\n";
521     $KDL->handle_room_msg ($room, $user, $msg);
522     });
523    
524     $client->register (msg_priv => sub {
525     my ($room, $src, $dst, $msg) = @_;
526     print "($room) ########### $src an $dst: $msg\n";
527     $KDL->handle_priv_msg ($room, $src, $dst, $msg);
528     });
529    
530     $client->register (join_room => sub {
531     print "$_[1]->{name} joined $_[0]: ".scalar(keys %{$client->{user_lists}->{lc $_[0]}}). " users\n";
532     $KDL->join_knuddler ($_[1]->{name}, $_[1]->{age}, $_[1]->{gender}, $_[0]);
533     });
534    
535     $client->register (action_room => sub {
536     $KDL->handle_room_action ($_[0], $_[1]);
537     });
538    
539     $client->register (part_room => sub {
540     print "$_[1]->{name} left $_[0]: ".scalar(keys %{$client->{user_lists}->{lc $_[0]}}). " users\n";
541     $KDL->part_knuddler ($_[1]->{name}, $_[0]);
542     });
543    
544     $client->register (user_list => sub {
545     my ($room, $list) = @_;
546     print "***** USER JOIN FUER $room *****\n";
547     print scalar (keys %$list)." users\n";
548     print "********************************\n";
549    
550     $KDL->handle_userlist ($room);
551     });
552    
553     $client->register (room_info => sub {
554     my ($room, $ri) = @_;
555     print "ROOM INFO: $room : $ri->{picture}\n";
556     $KDL->handle_room_info ($room, $ri);
557     });
558    
559     $client->register (change_room => sub {
560     my ($r, $nr) = @_;
561     $KDL->change_room ($r, $nr);
562     });
563    
564     $client->register (room_list => sub {
565     my ($room_hash) = @_;
566     $KDL->handle_room_list ($room_hash);
567     });
568    
569     $client->register (dialog => sub {
570     $KDL->handle_dialog ($_[0]);
571     });
572    
573     ready_irc_server;
574     connect_knuddels;
575     Event::loop;
576    
577    
578