1 | #! perl |
1 | #! perl |
2 | |
2 | |
3 | use Time::HiRes; |
3 | use AnyEvent::IRC::Client; |
4 | use Net::IRC3::Client::Connection; |
4 | use AnyEvent::IRC::Util qw/filter_colors/; |
5 | |
5 | |
6 | # requires: commands.ext |
6 | # requires: commands.ext |
7 | |
7 | |
8 | return unless exists $cf::CFG{irc_server}; |
8 | return unless exists $cf::CFG{irc_server}; |
9 | |
9 | |
10 | my $BOTSERVER = $cf::CFG{irc_server}; |
10 | CONF BOTSERVER : irc_server = undef; |
11 | my $BOTPORT = $cf::CFG{irc_port}; |
11 | CONF BOTPORT : irc_port = undef; |
12 | my $BOTNAME = $cf::CFG{irc_nick}; |
12 | CONF BOTNAME : irc_nick = undef; |
13 | my $BOTCHAN = $cf::CFG{irc_chan}; |
13 | CONF BOTCHAN : irc_chan = undef; |
14 | |
14 | |
15 | my $CON; # the connection |
15 | our $CON; # the connection |
16 | |
16 | |
17 | sub unload { |
17 | sub unload { |
18 | $CON->disconnect if $CON; |
18 | $CON->disconnect if $CON; |
19 | undef $CON; |
19 | undef $CON; |
20 | } |
20 | } |
21 | |
21 | |
22 | sub do_notice { |
22 | sub do_notice { |
23 | my ($msg) = @_; |
23 | my ($msg) = @_; |
24 | |
24 | |
25 | utf8::encode $msg; |
25 | utf8::encode $msg; |
26 | $CON->send_chan ($BOTCHAN, NOTICE => $msg, $BOTCHAN) |
26 | $CON->send_chan ($BOTCHAN, NOTICE => $BOTCHAN, $msg) |
27 | if $CON; |
27 | if $CON; |
28 | } |
28 | } |
29 | |
29 | |
30 | sub users { |
30 | sub users { |
31 | $CON |
31 | $CON |
32 | ? grep $_ ne $CON->nick, keys %{ $CON->channel_list->{$BOTCHAN} || {} } |
32 | ? grep $_ ne $CON->nick, keys %{ $CON->channel_list->{$BOTCHAN} || {} } |
33 | : () |
33 | : () |
34 | } |
34 | } |
|
|
35 | |
|
|
36 | # for nicklist monitoring, #d# should be done event-based |
|
|
37 | our %NICKLIST; |
|
|
38 | our $NICKLIST = AE::timer 20, 59.17, sub { |
|
|
39 | return unless defined &ext::nickmon::NT_OTHER; |
|
|
40 | |
|
|
41 | my %NEXTLIST; |
|
|
42 | for (users) { |
|
|
43 | &ext::nickmon::upd ("irc/$_", &ext::nickmon::NT_OTHER, "irc") |
|
|
44 | unless exists $NICKLIST{$_}; |
|
|
45 | |
|
|
46 | delete $NICKLIST{$_}; |
|
|
47 | undef $NEXTLIST{$_}; |
|
|
48 | } |
|
|
49 | |
|
|
50 | &ext::nickmon::del ("irc/$_") |
|
|
51 | for keys %NICKLIST; |
|
|
52 | |
|
|
53 | %NICKLIST = %NEXTLIST; |
|
|
54 | }; |
35 | |
55 | |
36 | sub handle_fcmd { |
56 | sub handle_fcmd { |
37 | my ($name, $me, $msg) = @_; |
57 | my ($name, $me, $msg) = @_; |
38 | |
58 | |
39 | if ($msg eq "!who") { |
59 | if ($msg eq "!who") { |
… | |
… | |
47 | |
67 | |
48 | if (my $other = cf::player::find_active $target) { |
68 | if (my $other = cf::player::find_active $target) { |
49 | |
69 | |
50 | if ($tmsg) { |
70 | if ($tmsg) { |
51 | if ($me eq $target) { |
71 | if ($me eq $target) { |
52 | $CON->send_chan ($BOTCHAN, NOTICE => "$me: You are talking to yourself, you freak!", $BOTCHAN); |
72 | $CON->send_chan ($BOTCHAN, NOTICE => $BOTCHAN, "$me: You are talking to yourself, you freak!"); |
53 | } elsif ($other->ob->{ext_ignore_tell}{$me} >= time) { |
73 | } elsif ($other->ob->{ext_ignore_tell}{$me} >= time) { |
54 | $CON->send_chan ($BOTCHAN, NOTICE => "$me: $target ignores what you say. Give up on it.", $BOTCHAN); |
74 | $CON->send_chan ($BOTCHAN, NOTICE => $BOTCHAN, "$me: $target ignores what you say. Give up on it."); |
55 | } else { |
75 | } else { |
56 | cf::LOG cf::llevDebug, sprintf "TELL [%s/%s>%s] %s\n", $name, $me, $target, $tmsg; |
76 | cf::LOG cf::llevDebug, sprintf "TELL [%s/%s>%s] %s\n", $name, $me, $target, $tmsg; |
57 | |
77 | |
58 | $other->ns->send_msg (ext::chat::tell_channel ("$name/$me"), "$name/$me tells you: $tmsg", cf::NDI_DK_ORANGE | cf::NDI_DEF); |
78 | $other->ns->send_msg (ext::chat::tell_channel ("$name/$me"), "$name/$me tells you: $tmsg", cf::NDI_DK_ORANGE | cf::NDI_DEF); |
59 | } |
79 | } |
… | |
… | |
66 | } |
86 | } |
67 | |
87 | |
68 | sub check_connection { |
88 | sub check_connection { |
69 | return if $CON; |
89 | return if $CON; |
70 | |
90 | |
71 | $CON = Net::IRC3::Client::Connection->new; |
91 | $CON = AnyEvent::IRC::Client->new; |
|
|
92 | $CON->set_exception_cb (sub { |
|
|
93 | my ($exp, $ev) = @_; |
|
|
94 | cf::error "IRC: IRC EXCEPTION (event $ev): $exp\n"; |
|
|
95 | }); |
72 | $CON->connect ($BOTSERVER, $BOTPORT); |
96 | $CON->connect ($BOTSERVER, $BOTPORT, { |
|
|
97 | nick => $BOTNAME, |
|
|
98 | user => $BOTNAME, |
|
|
99 | real => 'deliantra server' |
|
|
100 | }); |
73 | $CON->send_srv (JOIN => undef, $BOTCHAN); |
101 | $CON->send_srv (JOIN => undef, $BOTCHAN); |
74 | $CON->register ($BOTNAME, $BOTNAME, 'crossfire connection'); |
|
|
75 | $CON->reg_cb ( |
102 | $CON->reg_cb ( |
76 | #d# 'irc_*' => sub { warn "IRC $_[1]->{trailing}\n"; 1 }, |
|
|
77 | irc_privmsg => sub { |
103 | irc_privmsg => sub { |
78 | my ($con, $msg) = @_; |
104 | my ($con, $msg) = @_; |
79 | my $name = 'irc'; |
105 | my $name = 'irc'; |
80 | my $nick = Net::IRC3::Util::prefix_nick ($msg); |
106 | my $nick = AnyEvent::IRC::Util::prefix_nick ($msg); |
81 | my $NOW = Time::HiRes::time; |
107 | my $NOW = EV::time; |
82 | |
108 | |
83 | my $tmsg = $msg->{trailing}; |
109 | my $tmsg = filter_colors ($msg->{params}->[-1]); |
84 | $tmsg =~ s/\x01[^\x01]*\x01//g; |
110 | $tmsg =~ s/\x01[^\x01]*\x01//g; |
85 | $tmsg =~ s/\015?\012/ /g; |
111 | $tmsg =~ s/\015?\012/ /g; |
86 | |
112 | |
87 | utf8::decode $tmsg; |
113 | utf8::decode $tmsg; |
88 | |
114 | |
89 | if ($tmsg =~ /^\!/) { |
115 | if ($tmsg =~ /^\!/) { |
90 | handle_fcmd ($name, $nick, $tmsg); |
116 | handle_fcmd ($name, $nick, $tmsg); |
91 | } elsif ($tmsg =~ m/\S/) { |
117 | } elsif ($tmsg =~ m/\S/) { |
92 | $_->ns->send_msg ($ext::chat::CHAT_CHANNEL, |
118 | $_->ns->send_msg ($cf::CHAT_CHANNEL, |
93 | "$name/".$nick." chats: $tmsg", cf::NDI_BLUE | cf::NDI_DEF |
119 | "$name/".$nick." chats: $tmsg", cf::NDI_BLUE | cf::NDI_DEF |
94 | ) for grep { $_->ob->{ext_ignore_shout}{$name} < $NOW && $_->listening >= 10 } cf::player::list; |
120 | ) for grep { $_->ob->{ext_ignore_shout}{$name} < $NOW } cf::player::list; |
|
|
121 | cf::LOG cf::llevDebug, sprintf "QBERT [%s] %s\n", "$name/$nick", $tmsg; |
95 | } |
122 | } |
96 | 1; |
|
|
97 | }, |
123 | }, |
|
|
124 | connect => sub { |
|
|
125 | my ($con, $error) = @_; |
|
|
126 | |
|
|
127 | if ($error) { |
|
|
128 | cf::error "IRC: CONNECT ERROR to IRC server: $BOTSERVER:$BOTPORT: $error\n"; |
|
|
129 | undef $CON; |
|
|
130 | |
|
|
131 | } else { |
|
|
132 | cf::info "IRC: connected to IRC server: $BOTSERVER:$BOTPORT\n"; |
|
|
133 | } |
|
|
134 | }, |
98 | # registered => sub { |
135 | registered => sub { |
99 | # 1; |
136 | cf::info "IRC: successfully logged into IRC server: $BOTSERVER:$BOTPORT\n"; |
100 | # }, |
137 | }, |
|
|
138 | error => sub { |
|
|
139 | my ($con, $code, $message) = @_; |
|
|
140 | cf::error "IRC: IRC ERROR ($code) $message\n"; |
|
|
141 | }, |
101 | disconnect => sub { |
142 | disconnect => sub { |
102 | my ($con, $reason) = @_; |
143 | my ($con, $reason) = @_; |
103 | warn "CFBOT: disconnect: $reason\n"; |
144 | cf::warn "IRC: disconnect: $reason\n"; |
104 | undef $CON; |
145 | undef $CON; |
105 | 0; |
|
|
106 | } |
146 | } |
107 | ); |
147 | ); |
108 | } |
148 | } |
109 | |
149 | |
110 | Event->timer ( |
150 | our $RECONNECT = length $BOTSERVER && cf::periodic 30, Coro::unblock_sub { |
111 | reentrant => 0, |
151 | check_connection; |
112 | after => 1, |
152 | }; |
113 | interval => 30, |
|
|
114 | data => cf::WF_AUTOCANCEL, |
|
|
115 | cb => Coro::unblock_sub { check_connection }, |
|
|
116 | ); |
|
|
117 | |
153 | |