ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/Net-IRC3/samples/jsonsrv
Revision: 1.5
Committed: Sun Jan 14 01:10:53 2007 UTC (19 years, 8 months ago) by elmex
Branch: MAIN
Changes since 1.4: +149 -44 lines
Log Message:
further improvements of the jsonchat framework. maybe in some weeks i
have a new irc client for me!

File Contents

# User Rev Content
1 elmex 1.1 #!/usr/bin/perl
2     use strict;
3 elmex 1.5 use URI;
4 elmex 1.1 use AnyEvent::Impl::Perl;
5     use JSON::Syck;
6     use JSONConnection;
7     use Net::IRC3::Client::Connection;
8     $Net::IRC3::Client::Connection::DEBUG = 1;
9    
10     our $CFG;
11 elmex 1.5 our %ALIASES;
12 elmex 1.1 our %CONNS;
13    
14 elmex 1.5 our $JS;
15    
16 elmex 1.1 sub load_cfg {
17     $CFG ||= {};
18     return unless -e "$ENV{HOME}/.jsonircrc";
19     open CFGH, "<", "$ENV{HOME}/.jsonircrc" or die "Couldn't open ~/.jsonircrc: $!";
20     $::CFG = JSON::Syck::Load (do { local $/; <CFGH> });
21     }
22    
23     sub save_cfg {
24     open CFGH, ">", "$ENV{HOME}/.jsonircrc" or die "Couldn't open for writing ~/.jsonircrc: $!";
25     print CFGH (JSON::Syck::Dump ($::CFG));
26     close CFGH;
27     }
28    
29 elmex 1.3 sub to_dest_id {
30 elmex 1.5 my ($irccon, $targ) = @_;
31     $irccon = $ALIASES{$irccon} || $irccon;
32     my $uri = new URI;
33     $uri->scheme ("jsirc"); $uri->authority ($irccon); $uri->path ($targ);
34     "$uri"
35 elmex 1.3 }
36 elmex 1.5
37     sub unalias {
38     my ($id) = @_;
39     for (keys %ALIASES) {
40     if ($id eq $ALIASES{$_}) {
41     return $_;
42     }
43 elmex 1.3 }
44     }
45    
46 elmex 1.5 sub lookup_connection {
47     my ($id) = @_;
48     my $alias = unalias ($id);
49     return $CONNS{$alias || $id}
50     }
51 elmex 1.3
52 elmex 1.5 sub from_dest_id {
53     my ($dest_id) = @_;
54     my $uri = URI->new ($dest_id);
55     my $path = ($uri->path_segments ())[1];
56     return (lookup_connection ($uri->authority), unalias ($uri->authority) || $uri->authority, $path);
57     }
58 elmex 1.1
59 elmex 1.5 sub connect_irc {
60     my ($host, $port, $alias) = @_;
61     my $irccon = "$host:$port";
62     my $pc = $CONNS{$irccon} = Net::IRC3::Client::Connection->new;
63     $ALIASES{$irccon} = $alias if defined $alias;
64 elmex 1.1
65     $pc->reg_cb (
66     publicmsg => sub {
67     my ($pc, $chan, $msg) = @_;
68 elmex 1.5 my ($nick) = Net::IRC3::Util::split_prefix ($msg->{prefix});
69     my $dest = to_dest_id ($irccon, $chan);
70     my $nickdest = to_dest_id ($irccon, $nick);
71    
72     $JS->broadcast ({
73 elmex 1.3 src => $dest,
74     type => "message",
75     msg_type => "public",
76 elmex 1.1 message => $msg->{trailing},
77 elmex 1.2 timestamp => time (),
78 elmex 1.5 to => { nick => $pc->nick, id => to_dest_id ($irccon, $pc->nick) },
79 elmex 1.4 from => { nick => $nick, id => $nickdest },
80 elmex 1.1 });
81     1;
82     },
83     privatemsg => sub {
84     my ($pc, $dsgnick, $msg) = @_;
85     my ($nick) = Net::IRC3::Util::split_prefix ($msg->{prefix});
86 elmex 1.5 my $dest = to_dest_id ($irccon, $nick);
87    
88     $JS->broadcast ({
89 elmex 1.3 src => $dest,
90     type => "message",
91     msg_type => "private",
92 elmex 1.1 message => $msg->{trailing},
93 elmex 1.2 timestamp => time (),
94 elmex 1.5 to => { nick => $pc->nick, id => to_dest_id ($irccon, $pc->nick) },
95 elmex 1.4 from => { nick => $nick, id => $dest },
96 elmex 1.1 });
97     1;
98     },
99 elmex 1.5 connect => sub {
100     info_reply ($JS, undef, undef,
101     "Connected to $host:$port "
102     . (defined $alias ? "(aka $alias)" : "")
103     );
104     },
105     disconnect => sub {
106     error_reply ($JS, undef, undef,
107     "Lost connection to $host:$port "
108     . (defined $alias ? "(aka $alias)" : "")
109     );
110     delete $CONNS{"$host:$port"};
111     delete $ALIASES{"$host:$port"};
112     }
113 elmex 1.1 );
114    
115 elmex 1.5 eval {
116     $pc->connect ($host, $port);
117     };
118     if ($@) {
119     error_reply ($JS, undef, undef,
120     "Couldn't connect to $host:$port "
121     . (defined $alias ? "(aka $alias)" : "")
122     . ": $@"
123     );
124     delete $CONNS{"$host:$port"};
125     delete $ALIASES{"$host:$port"};
126     return;
127     }
128 elmex 1.1 $pc->register (qw/elmex2 elmex2 elmex2/);
129    
130 elmex 1.5 for (@{$CFG->{channels}->{$alias || "$host:$port"}}) {
131     $pc->send_srv (JOIN => undef => $_);
132 elmex 1.1 }
133     }
134    
135 elmex 1.5 sub update_connections {
136     for (map { /^(\S+):(\d+)/ ? [$1, $2, $_] : [] } keys %CONNS) {
137     my ($h, $p) = @$_;
138     unless (
139     grep {
140     ($_->{host} eq $h) && (($_->{port} || 6667) == $p) && ($_->{connect})
141     } @{$CFG->{servers}})
142     {
143     $CONNS{$_->[2]}->disconnect;
144     }
145     }
146    
147     for my $con (@{$CFG->{servers}}) {
148     my ($host, $port) = ($con->{host}, $con->{port} || 6667);
149    
150     if ($con->{connect} and not $CONNS{"$host:$port"}) {
151     connect_irc ($host, $port, $con->{alias});
152     }
153     }
154     }
155    
156     sub info_reply {
157     my ($con, $lid, $infodata, $string) = @_;
158     if (defined $lid) {
159     $con->send_data ($lid,
160     { type => 'info', info_packet => $infodata, message => $string });
161     } else {
162     $JS->broadcast ({ type => 'info', info_packet => $infodata, message => $string });
163     }
164     }
165    
166     sub error_reply {
167     my ($con, $lid, $errdata, $string) = @_;
168     if (defined $lid) {
169     $con->send_data ($lid,
170     { type => 'error', error_packet => $errdata, message => $string });
171     } else {
172     $JS->broadcast ({ type => 'error', error_packet => $errdata, message => $string });
173     }
174     }
175    
176     load_cfg;
177    
178     my $c = AnyEvent->condvar;
179    
180     $JS =
181     JSONConnection->new (
182     packet_cb => sub {
183     my ($JS, $lid, $data) = @_;
184    
185     if ($data->{type} eq 'message') {
186     my ($con, $irccon, $dest) = from_dest_id ($data->{dest});
187     unless (defined $con) {
188     error_reply ($JS, $lid, $data, "No such ID found: '$data->{dest}'");
189     return
190     }
191     $con->send_srv (PRIVMSG => $data->{message} => $dest);
192    
193     } elsif ($data->{type} eq 'command') {
194     if ($data->{command} eq 'reload') {
195     load_cfg;
196     update_connections;
197     } elsif ($data->{command} eq 'list_connections') {
198     } elsif ($data->{command} eq 'list_ids') {
199     }
200     } else {
201     error_reply ($JS, $lid, $data, "Did not understand this packet");
202     }
203     1
204     },
205     connect_cb => sub {
206     my ($JS, $lid) = @_;
207     $JS->send_data ($lid, { type => "hello" });
208     });
209    
210     update_connections;
211    
212     $JS->start_listener;
213 elmex 1.1
214     $c->wait;