line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package AnyEvent::XMPP::Client; |
2
|
19
|
|
|
19
|
|
1601
|
use strict; |
|
19
|
|
|
|
|
42
|
|
|
19
|
|
|
|
|
762
|
|
3
|
19
|
|
|
19
|
|
100
|
use AnyEvent; |
|
19
|
|
|
|
|
41
|
|
|
19
|
|
|
|
|
352
|
|
4
|
19
|
|
|
19
|
|
22928
|
use AnyEvent::XMPP::IM::Connection; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
use AnyEvent::XMPP::Util qw/stringprep_jid prep_bare_jid dump_twig_xml bare_jid cmp_bare_jid/; |
6
|
|
|
|
|
|
|
use AnyEvent::XMPP::Namespaces qw/xmpp_ns/; |
7
|
|
|
|
|
|
|
use AnyEvent::XMPP::Extendable; |
8
|
|
|
|
|
|
|
use AnyEvent::XMPP::IM::Account; |
9
|
|
|
|
|
|
|
use Object::Event; |
10
|
|
|
|
|
|
|
use Scalar::Util; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
#use XML::Twig; |
13
|
|
|
|
|
|
|
# |
14
|
|
|
|
|
|
|
#sub _dumpxml { |
15
|
|
|
|
|
|
|
# my $data = shift; |
16
|
|
|
|
|
|
|
# my $t = XML::Twig->new; |
17
|
|
|
|
|
|
|
# if ($t->safe_parse ("$data")) { |
18
|
|
|
|
|
|
|
# $t->set_pretty_print ('indented'); |
19
|
|
|
|
|
|
|
# $t->print; |
20
|
|
|
|
|
|
|
# print "\n"; |
21
|
|
|
|
|
|
|
# } else { |
22
|
|
|
|
|
|
|
# print "[$data]\n"; |
23
|
|
|
|
|
|
|
# } |
24
|
|
|
|
|
|
|
#} |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
our @ISA = qw/Object::Event AnyEvent::XMPP::Extendable/; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=head1 NAME |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
AnyEvent::XMPP::Client - XMPP Client abstraction |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head1 SYNOPSIS |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
use AnyEvent::XMPP::Client; |
35
|
|
|
|
|
|
|
use AnyEvent; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
my $j = AnyEvent->condvar; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
my $cl = AnyEvent::XMPP::Client->new; |
40
|
|
|
|
|
|
|
$cl->start; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
$j->wait; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 DESCRIPTION |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
This module tries to implement a straight forward and easy to |
47
|
|
|
|
|
|
|
use API to communicate with XMPP entities. L |
48
|
|
|
|
|
|
|
handles connections and timeouts and all such stuff for you. |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
For more flexibility please have a look at L |
51
|
|
|
|
|
|
|
and L, they allow you to control what |
52
|
|
|
|
|
|
|
and how something is being sent more precisely. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head1 METHODS |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=head2 new (%args) |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
Following arguments can be passed in C<%args>: |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=over 4 |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=item debug => 1 |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
This will install callbacks which produce debugging output. This will |
65
|
|
|
|
|
|
|
require L to be installed (as it is used for pretty printing |
66
|
|
|
|
|
|
|
the "XML" output). |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=back |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=cut |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub new { |
73
|
|
|
|
|
|
|
my $this = shift; |
74
|
|
|
|
|
|
|
my $class = ref($this) || $this; |
75
|
|
|
|
|
|
|
my $self = { @_ }; |
76
|
|
|
|
|
|
|
bless $self, $class; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
if ($self->{debug}) { |
79
|
|
|
|
|
|
|
$self->reg_cb ( |
80
|
|
|
|
|
|
|
debug_recv => sub { |
81
|
|
|
|
|
|
|
my ($self, $acc, $data) = @_; |
82
|
|
|
|
|
|
|
printf "recv>> %s\n%s", $acc->jid, dump_twig_xml ($data) |
83
|
|
|
|
|
|
|
}, |
84
|
|
|
|
|
|
|
debug_send => sub { |
85
|
|
|
|
|
|
|
my ($self, $acc, $data) = @_; |
86
|
|
|
|
|
|
|
printf "send<< %s\n%s", $acc->jid, dump_twig_xml ($data) |
87
|
|
|
|
|
|
|
}, |
88
|
|
|
|
|
|
|
) |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
return $self; |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub add_extension { |
94
|
|
|
|
|
|
|
my ($self, $ext) = @_; |
95
|
|
|
|
|
|
|
$self->add_forward ($ext, sub { |
96
|
|
|
|
|
|
|
my ($self, $ext, $ev, $acc, @args) = @_; |
97
|
|
|
|
|
|
|
return if $ext->{inhibit_forward}->{$ev}; |
98
|
|
|
|
|
|
|
$ext->_event ($ev, $acc->connection (), @args); |
99
|
|
|
|
|
|
|
}); |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=head2 add_account ($jid, $password, $host, $port, $connection_args) |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
This method adds a jabber account for connection with the JID C<$jid> |
105
|
|
|
|
|
|
|
and the password C<$password>. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
C<$host> and C<$port> can be undef and their default will be the domain of the |
108
|
|
|
|
|
|
|
C<$jid> and the default for the C parameter to the constructor of |
109
|
|
|
|
|
|
|
L (look there for details about DNS-SRV lookups). |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
C<$connection_args> must either be undef or a hash reference to |
112
|
|
|
|
|
|
|
additional arguments for the constructor of the L |
113
|
|
|
|
|
|
|
that will be used to connect the account. |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
Returns 1 on success and undef when the account already exists. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=cut |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
sub add_account { |
120
|
|
|
|
|
|
|
my ($self, $jid, $password, $host, $port, $connection_args) = @_; |
121
|
|
|
|
|
|
|
my $bj = prep_bare_jid $jid; |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
my $acc = $self->{accounts}->{$bj}; |
124
|
|
|
|
|
|
|
if ($acc) { |
125
|
|
|
|
|
|
|
$acc->{password} = $password; |
126
|
|
|
|
|
|
|
$acc->{host} = $host; |
127
|
|
|
|
|
|
|
$acc->{port} = $port; |
128
|
|
|
|
|
|
|
$acc->{args} = $connection_args; |
129
|
|
|
|
|
|
|
return; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
$acc = |
133
|
|
|
|
|
|
|
$self->{accounts}->{$bj} = |
134
|
|
|
|
|
|
|
AnyEvent::XMPP::IM::Account->new ( |
135
|
|
|
|
|
|
|
jid => $jid, |
136
|
|
|
|
|
|
|
password => $password, |
137
|
|
|
|
|
|
|
host => $host, |
138
|
|
|
|
|
|
|
port => $port, |
139
|
|
|
|
|
|
|
args => $connection_args, |
140
|
|
|
|
|
|
|
); |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
$self->event (added_account => $acc); |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
$self->update_connections |
145
|
|
|
|
|
|
|
if $self->{started}; |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
$acc |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=head2 start () |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
This method initiates the connections to the XMPP servers. |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=cut |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub start { |
157
|
|
|
|
|
|
|
my ($self) = @_; |
158
|
|
|
|
|
|
|
$self->{started} = 1; |
159
|
|
|
|
|
|
|
$self->update_connections; |
160
|
|
|
|
|
|
|
} |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=head2 update_connections () |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
This method tries to connect all unconnected accounts. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=cut |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub update_connections { |
169
|
|
|
|
|
|
|
my ($self) = @_; |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
Scalar::Util::weaken $self; |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
for (values %{$self->{accounts}}) { |
174
|
|
|
|
|
|
|
my $acc = $_; |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
if (!$acc->is_connected && !$self->{prep_connections}->{$acc->bare_jid}) { |
177
|
|
|
|
|
|
|
my %args = (initial_presence => 10); |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
if (defined $self->{presence}) { |
180
|
|
|
|
|
|
|
if (defined $self->{presence}->{priority}) { |
181
|
|
|
|
|
|
|
$args{initial_presence} = $self->{presence}->{priority}; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
my $con = $acc->spawn_connection (%args); |
186
|
|
|
|
|
|
|
$self->{prep_connections}->{$acc->bare_jid} = $con; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
$con->add_forward ($self, sub { |
189
|
|
|
|
|
|
|
my ($con, $self, $ev, @arg) = @_; |
190
|
|
|
|
|
|
|
$self->_event ($ev, $acc, @arg); |
191
|
|
|
|
|
|
|
}); |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
$con->reg_cb ( |
194
|
|
|
|
|
|
|
session_ready => sub { |
195
|
|
|
|
|
|
|
my ($con) = @_; |
196
|
|
|
|
|
|
|
delete $self->{prep_connections}->{$acc->bare_jid}; |
197
|
|
|
|
|
|
|
$self->event (connected => $acc); |
198
|
|
|
|
|
|
|
if (defined $self->{presence}) { |
199
|
|
|
|
|
|
|
$con->send_presence (undef, undef, %{$self->{presence} || {}}); |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
$con->unreg_me |
202
|
|
|
|
|
|
|
}, |
203
|
|
|
|
|
|
|
disconnect => sub { |
204
|
|
|
|
|
|
|
my ($con, $h, $p, $err) = @_; |
205
|
|
|
|
|
|
|
$self->event (connect_error => $acc, $err); |
206
|
|
|
|
|
|
|
delete $self->{prep_connections}->{$acc->bare_jid}; |
207
|
|
|
|
|
|
|
$con->unreg_me; |
208
|
|
|
|
|
|
|
}, |
209
|
|
|
|
|
|
|
after_disconnect => sub { |
210
|
|
|
|
|
|
|
my ($con, $h, $p, $err) = @_; |
211
|
|
|
|
|
|
|
$con->remove_forward ($self); |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
); |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
$con->connect; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=head2 disconnect ($msg) |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
Disconnect all accounts. |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=cut |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub disconnect { |
227
|
|
|
|
|
|
|
my ($self, $msg) = @_; |
228
|
|
|
|
|
|
|
for my $acc (values %{$self->{accounts}}) { |
229
|
|
|
|
|
|
|
if ($acc->is_connected) { $acc->connection ()->disconnect ($msg) } |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=head2 remove_accounts ($reason) |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
Removes all accounts and disconnects. C<$reason> should be some descriptive |
236
|
|
|
|
|
|
|
reason why this account was removed (just for logging purposes). |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=cut |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
sub remove_accounts { |
241
|
|
|
|
|
|
|
my ($self, $reason) = @_; |
242
|
|
|
|
|
|
|
for my $acc (keys %{$self->{accounts}}) { |
243
|
|
|
|
|
|
|
$self->remove_account ($acc, $reason); |
244
|
|
|
|
|
|
|
} |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=head2 remove_account ($acc, $reason) |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
Removes and disconnects account C<$acc> (which is a L object). |
250
|
|
|
|
|
|
|
The reason for the removal can be given via C<$reason>. |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=cut |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub remove_account { |
255
|
|
|
|
|
|
|
my ($self, $acc, $reason) = @_; |
256
|
|
|
|
|
|
|
my $acca = $self->{accounts}->{$acc}; |
257
|
|
|
|
|
|
|
$self->event (removed_account => $acca); |
258
|
|
|
|
|
|
|
if ($acca->is_connected) { $acca->connection ()->disconnect ($reason) } |
259
|
|
|
|
|
|
|
delete $self->{accounts}->{$acc}; |
260
|
|
|
|
|
|
|
} |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=head2 set_accounts (%$accounts) |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
Sets the set of (to be connected) accounts. C<$accounts> must be a hash |
265
|
|
|
|
|
|
|
reference which contains the JIDs of the accounts as keys and the values for |
266
|
|
|
|
|
|
|
C<$password>, C<$domain>, C<$port> and C<$connection_args> as described in |
267
|
|
|
|
|
|
|
C above. |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
If the account is not yet connected it will be connected on the next call to |
270
|
|
|
|
|
|
|
C and if an account is connected that is not in |
271
|
|
|
|
|
|
|
C<$accounts> it will be disconnected. |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=cut |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
sub set_accounts { |
276
|
|
|
|
|
|
|
my ($self, $accounts) = @_; |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
for my $accid (keys %{$self->{accounts}}) { |
280
|
|
|
|
|
|
|
my $acca = $self->{accounts}->{$accid}; |
281
|
|
|
|
|
|
|
if (!grep { cmp_bare_jid ($acca->jid, $_) } keys %$accounts) { |
282
|
|
|
|
|
|
|
$self->remove_account ($accid, "removed from set"); |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
for my $acc_jid (keys %$accounts) { |
287
|
|
|
|
|
|
|
$self->add_account ($acc_jid, @{$accounts->{$acc_jid}}); |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=head2 send_message ($msg, $dest_jid, $src, $type) |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
Sends a message to the destination C<$dest_jid>. |
294
|
|
|
|
|
|
|
C<$msg> can either be a string or a L object. |
295
|
|
|
|
|
|
|
If C<$msg> is such an object C<$dest_jid> is optional, but will, when |
296
|
|
|
|
|
|
|
passed, override the destination of the message. |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
NOTE: C<$dest_jid> is transformed into a bare JID and the routing |
299
|
|
|
|
|
|
|
is done by the conversation tracking mechanism which keeps track of |
300
|
|
|
|
|
|
|
which resource should get the message. |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
C<$src> is optional. It specifies which account to use |
303
|
|
|
|
|
|
|
to send the message. If it is not passed L will try |
304
|
|
|
|
|
|
|
to find an account itself. First it will look through all rosters |
305
|
|
|
|
|
|
|
to find C<$dest_jid> and if none found it will pick any of the accounts that |
306
|
|
|
|
|
|
|
are connected. |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
C<$src> can either be a JID or a L object as returned |
309
|
|
|
|
|
|
|
by C and C. |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
C<$type> is optional but overrides the type of the message object in C<$msg> |
312
|
|
|
|
|
|
|
if C<$msg> is such an object. |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
C<$type> should be 'chat' for normal chatter. If no C<$type> is specified |
315
|
|
|
|
|
|
|
the type of the message defaults to the value documented in L |
316
|
|
|
|
|
|
|
(should be 'normal'). |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=cut |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
sub send_message { |
321
|
|
|
|
|
|
|
my ($self, $msg, $dest_jid, $src, $type) = @_; |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
unless (ref $msg) { |
324
|
|
|
|
|
|
|
$msg = AnyEvent::XMPP::IM::Message->new (body => $msg); |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
if (defined $dest_jid) { |
328
|
|
|
|
|
|
|
my $jid = stringprep_jid $dest_jid |
329
|
|
|
|
|
|
|
or die "send_message: \$dest_jid is not a proper JID"; |
330
|
|
|
|
|
|
|
$msg->to ($jid); |
331
|
|
|
|
|
|
|
} |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
$msg->type ($type) if defined $type; |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
my $srcacc; |
336
|
|
|
|
|
|
|
if (ref $src) { |
337
|
|
|
|
|
|
|
$srcacc = $src; |
338
|
|
|
|
|
|
|
} elsif (defined $src) { |
339
|
|
|
|
|
|
|
$srcacc = $self->get_account ($src) |
340
|
|
|
|
|
|
|
} else { |
341
|
|
|
|
|
|
|
$srcacc = $self->find_account_for_dest_jid ($dest_jid); |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
unless ($srcacc && $srcacc->is_connected) { |
345
|
|
|
|
|
|
|
die "send_message: Couldn't get connected account for sending" |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
$srcacc->send_tracked_message ($msg); |
349
|
|
|
|
|
|
|
} |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
=head2 get_account ($jid) |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
Returns the L account object for the JID C<$jid> |
354
|
|
|
|
|
|
|
if there is any such account added. (returns undef otherwise). |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=cut |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
sub get_account { |
359
|
|
|
|
|
|
|
my ($self, $jid) = @_; |
360
|
|
|
|
|
|
|
$self->{accounts}->{prep_bare_jid $jid} |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
=head2 get_accounts () |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
Returns a list of Ls. |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=cut |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
sub get_accounts { |
370
|
|
|
|
|
|
|
my ($self) = @_; |
371
|
|
|
|
|
|
|
values %{$self->{accounts}} |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
=head2 get_connected_accounts () |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
Returns a list of connected Ls. |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
Same as: |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
grep { $_->is_connected } $client->get_accounts (); |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=cut |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
sub get_connected_accounts { |
385
|
|
|
|
|
|
|
my ($self, $jid) = @_; |
386
|
|
|
|
|
|
|
my (@a) = grep $_->is_connected, values %{$self->{accounts}}; |
387
|
|
|
|
|
|
|
@a |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=head2 find_account_for_dest_jid ($jid) |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
This method tries to find any account that has the contact C<$jid> |
393
|
|
|
|
|
|
|
on his roster. If no account with C<$jid> on his roster was found |
394
|
|
|
|
|
|
|
it takes the first one that is connected. (Return value is a L |
395
|
|
|
|
|
|
|
object). |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
If no account is connected it returns undef. |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=cut |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
sub find_account_for_dest_jid { |
402
|
|
|
|
|
|
|
my ($self, $jid) = @_; |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
my $any_acc; |
405
|
|
|
|
|
|
|
for my $acc (values %{$self->{accounts}}) { |
406
|
|
|
|
|
|
|
next unless $acc->is_connected; |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
# take "first" active account |
409
|
|
|
|
|
|
|
$any_acc = $acc unless defined $any_acc; |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
my $roster = $acc->connection ()->get_roster; |
412
|
|
|
|
|
|
|
if (my $c = $roster->get_contact ($jid)) { |
413
|
|
|
|
|
|
|
return $acc; |
414
|
|
|
|
|
|
|
} |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
$any_acc |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=head2 get_contacts_for_jid ($jid) |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
This method returns all contacts that we are connected to. |
423
|
|
|
|
|
|
|
That means: It joins the contact lists of all account's rosters |
424
|
|
|
|
|
|
|
that we are connected to. |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
=cut |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
sub get_contacts_for_jid { |
429
|
|
|
|
|
|
|
my ($self, $jid) = @_; |
430
|
|
|
|
|
|
|
my @cons; |
431
|
|
|
|
|
|
|
for ($self->get_connected_accounts) { |
432
|
|
|
|
|
|
|
my $roster = $_->connection ()->get_roster (); |
433
|
|
|
|
|
|
|
my $con = $roster->get_contact ($jid); |
434
|
|
|
|
|
|
|
push @cons, $con if $con; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
return @cons; |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=head2 get_priority_presence_for_jid ($jid) |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
This method returns the presence for the contact C<$jid> with the highest |
442
|
|
|
|
|
|
|
priority. |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
If the contact C<$jid> is on multiple account's rosters it's undefined which |
445
|
|
|
|
|
|
|
roster the presence belongs to. |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=cut |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
sub get_priority_presence_for_jid { |
450
|
|
|
|
|
|
|
my ($self, $jid) = @_; |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
my $lpres; |
453
|
|
|
|
|
|
|
for ($self->get_connected_accounts) { |
454
|
|
|
|
|
|
|
my $roster = $_->connection ()->get_roster (); |
455
|
|
|
|
|
|
|
my $con = $roster->get_contact ($jid); |
456
|
|
|
|
|
|
|
next unless defined $con; |
457
|
|
|
|
|
|
|
my $pres = $con->get_priority_presence ($jid); |
458
|
|
|
|
|
|
|
next unless defined $pres; |
459
|
|
|
|
|
|
|
if ((not defined $lpres) || $lpres->priority < $pres->priority) { |
460
|
|
|
|
|
|
|
$lpres = $pres; |
461
|
|
|
|
|
|
|
} |
462
|
|
|
|
|
|
|
} |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
$lpres |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
=head2 set_presence ($show, $status, $priority) |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
This sets the presence of all accounts. For a meaning of C<$show>, C<$status> |
470
|
|
|
|
|
|
|
and C<$priority> see the description of the C<%attrs> hash in |
471
|
|
|
|
|
|
|
C method of L. |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
=cut |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
sub set_presence { |
476
|
|
|
|
|
|
|
my ($self, $show, $status, $priority) = @_; |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
$self->{presence} = { |
479
|
|
|
|
|
|
|
show => $show, |
480
|
|
|
|
|
|
|
status => $status, |
481
|
|
|
|
|
|
|
priority => $priority |
482
|
|
|
|
|
|
|
}; |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
for my $ac ($self->get_connected_accounts) { |
485
|
|
|
|
|
|
|
my $con = $ac->connection (); |
486
|
|
|
|
|
|
|
$con->send_presence (undef, undef, %{$self->{presence}}); |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
} |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
=head1 EVENTS |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
In the following event descriptions the argument C<$account> |
493
|
|
|
|
|
|
|
is always a L object. |
494
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
All events from L are forwarded to the client, |
496
|
|
|
|
|
|
|
only that the first argument for every event is a C<$account> object. |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
Aside fom those, these events can be registered on with C: |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
=over 4 |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
=item connected => $account |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
This event is sent when the C<$account> was successfully connected. |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=item connect_error => $account, $reason |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
This event is emitted when an error occured in the connection process for the |
509
|
|
|
|
|
|
|
account C<$account>. |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
=item error => $account, $error |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
This event is emitted when any error occured while communicating |
514
|
|
|
|
|
|
|
over the connection to the C<$account> - after a connection was established. |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
C<$error> is an error object which is derived from L. |
517
|
|
|
|
|
|
|
It will reveal human readable information about the error by calling the C |
518
|
|
|
|
|
|
|
method (which returns a descriptive error string about the nature of the error). |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=item added_account => $account |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
Called whenever an account is added. |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
=item removed_account => $account |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
Called whenever an account is removed. |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
=back |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
=head1 AUTHOR |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
Robin Redeker, C<< >>, JID: C<< >> |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
Copyright 2007, 2008 Robin Redeker, all rights reserved. |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
539
|
|
|
|
|
|
|
under the same terms as Perl itself. |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
=cut |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
1; # End of AnyEvent::XMPP::Client |