File Coverage

blib/lib/AnyEvent/XMPP/IM/Message.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package AnyEvent::XMPP::IM::Message;
2 1     1   2072 use strict;
  1         3  
  1         46  
3             use overload
4 1     1   5 '""' => "to_string";
  1         2  
  1         10  
5              
6 1     1   627 use AnyEvent::XMPP::IM::Delayed;
  0            
  0            
7              
8             our @ISA = qw/AnyEvent::XMPP::IM::Delayed/;
9              
10             =head1 NAME
11              
12             AnyEvent::XMPP::IM::Message - Instant message
13              
14             =head1 SYNOPSIS
15              
16             use AnyEvent::XMPP::IM::Message;
17              
18             my $con = AnyEvent::XMPP::IM::Connection->new (...);
19              
20             AnyEvent::XMPP::IM::Message->new (
21             body => "Hello there!",
22             to => "elmex@jabber.org"
23             )->send ($con);
24              
25             =head1 DESCRIPTION
26              
27             This module represents an instant message. It's mostly
28             a shortlived object and acts as wrapper object around the
29             XML stuff that is happening under the hood.
30              
31             A L object overloads the stringification
32             operation. The string represenation of this object is the return
33             value of the C method.
34              
35             L is derived from L,
36             use the interface described there to find out whether this message was delayed.
37              
38             =head1 METHODS
39              
40             =over 4
41              
42             =item B
43              
44             This method creates a new instance of a L.
45              
46             C<%args> is the argument hash. All arguments to C are optional.
47              
48             These are the possible keys:
49              
50             =over 4
51              
52             =item connection => $connection
53              
54             This is the L object that will
55             be used to send this message when the C method is called.
56              
57             =item to => $jid
58              
59             This is the destination JID of this message.
60             C<$jid> should be full if this message is send within a conversation
61             'context', for example when replying to a previous message.
62              
63             Replies can also be generated by the C method, see also
64             the C argument below.
65              
66             =item from => $jid
67              
68             This is the source JID of this message, it's mainly
69             used by the C method.
70              
71             =item lang => $lang
72              
73             This is the default language that will be used to tag the values
74             passed in the C and C argument to C.
75              
76             =item body => $body
77              
78             This is the text C<$body> of the message either with the language
79             tag from the C attached or without any language tag.
80              
81             If you want to attach multiple bodies with different languages use the C
82             method.
83              
84             =item subject => $subject
85              
86             This is the C<$subject> of the message either with the language
87             tag from the C attached or without any language tag.
88              
89             If you want to attach the subject with a different language use the C
90             method.
91              
92             =item type => $type
93              
94             This field sets the type of the message. See also the L method below.
95              
96             The default value for C<$type> is 'normal'.
97              
98             =back
99              
100             =cut
101              
102             sub new {
103             my $this = shift;
104             my $class = ref($this) || $this;
105             my $self = bless { @_ }, $class;
106              
107             if (my $sub = delete $self->{subject}) {
108             $self->add_subject ($sub);
109             }
110             if (my $body = delete $self->{body}) {
111             $self->add_body ($body);
112             }
113              
114             $self->{type} ||= 'normal'; # default it to 'normal'
115             $self->{lang} ||= '';
116              
117             $self
118             }
119              
120             sub from_node {
121             my ($self, $node) = @_;
122             $self->{node} = $node;
123              
124             $self->fetch_delay_from_node ($node);
125              
126             my $id = $node->attr ('id');
127             my $from = $node->attr ('from');
128             my $to = $node->attr ('to');
129             my $type = $node->attr ('type');
130             my ($thread) = $node->find_all ([qw/client thread/]);
131              
132             my %bodies;
133             my %subjects;
134              
135             $bodies{$_->attr ('lang') || ''} = $_->text
136             for $node->find_all ([qw/client body/]);
137             $subjects{$_->attr ('lang') || ''} = $_->text
138             for $node->find_all ([qw/client subject/]);
139              
140             $self->{id} = $id;
141             $self->{from} = $from;
142             $self->{to} = $to;
143             $self->{type} = $type;
144             $self->{thread} = $thread;
145             $self->{bodies} = \%bodies;
146             $self->{subjects} = \%subjects;
147             }
148              
149             sub to_string {
150             my ($self) = @_;
151             $self->any_body
152             }
153              
154             =item B
155              
156             This method returns the ID of this message.
157             If C<$msg_id> is not undef it will replace the current
158             message id.
159              
160             =cut
161              
162             sub id {
163             my ($self, $id) = @_;
164             $self->{id} = $id if defined $id;
165             $self->{id}
166             }
167              
168             =item B
169              
170             This method returns the source JID of this message.
171             If C<$jid> is not undef it will replace the current
172             source address.
173              
174             =cut
175              
176             sub from {
177             my ($self, $from) = @_;
178             $self->{from} = $from if defined $from;
179             $self->{from}
180             }
181              
182             =item B
183              
184             This method returns the destination JID of this message.
185             If C<$jid> is not undef it will replace the current
186             destination address.
187              
188             =cut
189              
190             sub to {
191             my ($self, $to) = @_;
192             $self->{to} = $to if defined $to;
193             $self->{to}
194             }
195              
196             =item B
197              
198             This method returns a new instance of L.
199             The destination address, connection and type of the returned message
200             object will be set.
201              
202             If C<$msg> is defined and an instance of L
203             the destination address, connection and type of C<$msg> will be changed
204             and this method will not return a new instance of L.
205              
206             =cut
207              
208             sub make_reply {
209             my ($self, $msg) = @_;
210              
211             unless ($msg) {
212             $msg = $self->new ();
213             }
214              
215             $msg->{connection} = $self->{connection};
216             $msg->to ($self->from);
217             $msg->type ($self->type);
218              
219             $msg
220             }
221              
222             =item B
223              
224             This method returns 1 when the message is "connected".
225             That means: It returns 1 when you can call the C method
226             without a connection argument. (It will also return only 1 when
227             the connection that is referenced by this message is still
228             connected).
229              
230             =cut
231              
232             sub is_connected {
233             my ($self) = @_;
234             $self->{connection}->is_connected
235             }
236              
237             =item B
238              
239             This method send this message. If C<$connection>
240             is defined it will set the connection of this
241             message object before it is send.
242              
243             =cut
244              
245             sub send {
246             my ($self, $connection) = @_;
247              
248             $self->{connection} = $connection if $connection;
249              
250             my @add;
251             push @add, (subject => $self->{subjects})
252             if %{$self->{subjects} || {}};
253             push @add, (thread => $self->thread)
254             if $self->thread;
255             push @add, (from => $self->from)
256             if $self->from;
257              
258             push @add, (id => $self->id)
259             if $self->id;
260              
261             $self->{connection}->send_message (
262             $self->to, $self->type, $self->{create_cbs},
263             body => $self->{bodies},
264             @add
265             );
266             }
267              
268             =item B
269              
270             This method returns the type of the message, which
271             is either undefined or one of the following values:
272              
273             'chat', 'error', 'groupchat', 'headline', 'normal'
274              
275             If the C<$type> argument is defined it will set the type
276             of this message.
277              
278             =cut
279              
280             sub type {
281             my ($self, $type) = @_;
282             $self->{type} = $type
283             if defined $type;
284             $self->{type}
285             }
286              
287             =item B
288              
289             This method returns the thread id of this message,
290             which might be undefined.
291              
292             If you want to set the threadid simply pass the C<$thread>
293             argument.
294              
295             =cut
296              
297             sub thread {
298             my ($self, $thread) = @_;
299             $self->{thread} = $thread
300             if defined $thread;
301             $self->{thread}
302             }
303              
304             =item B
305              
306             This returns the default language tag of this message,
307             which can be undefined.
308              
309             To set the language tag pass the C<$lang> argument, which
310             should be the new default language tag.
311              
312             If you do not want to specify any language pass the empty
313             string as language tag.
314              
315             =cut
316              
317             sub lang {
318             my ($self, $lang) = @_;
319             $self->{lang} = $lang
320             if defined $lang;
321             $self->{lang}
322             }
323              
324             =item B
325              
326             This method returns the subject of this message.
327             If the C<$lang> argument is defined a subject of that
328             language will be returned or undef.
329             If the C<$lang> argument is undefined this method will
330             return either the subject in the default language.
331              
332             =cut
333              
334             sub subject {
335             my ($self, $lang) = @_;
336              
337             if (defined $lang) {
338             return $self->{subjects}->{$lang}
339             }
340              
341             return $self->{subjects}->{$self->{lang}};
342              
343             undef
344             }
345              
346             =item B
347              
348             This method will try to find any subject on the message with the
349             following try order of languagetags:
350              
351             1. $lang argument if one passed
352             2. default language
353             3. subject without any language tag
354             4. subject with the 'en' language tag
355             5. any subject from any language
356              
357             =cut
358              
359             sub any_subject {
360             my ($self, $lang) = @_;
361             if (defined $lang) {
362             return $self->{subjects}->{$lang}
363             if defined $self->{subjects}->{$lang};
364             }
365             return $self->{subjects}->{$self->{lang}}
366             if defined $self->{subjects}->{$self->{lang}};
367             return $self->{subjects}->{''}
368             if defined $self->{subjects}->{''};
369             return $self->{subjects}->{en}
370             if defined $self->{subjects}->{en};
371             return $self->{subjects}->{$_} for (keys %{$self->{subjects}});
372             return undef;
373             }
374              
375             =item B
376              
377             This method adds the subject C<$subject> with the optional
378             language tag C<$lang> to this message. If no C<$lang>
379             argument is passed the default language for this message will be used.
380              
381             Further subject => lang pairs can passed to this function like this:
382              
383             $msg->add_subject ('foobar' => undef, "barfooo" => "de");
384              
385             =cut
386              
387             sub add_subject {
388             my $self = shift;
389             while (@_) {
390             my $subj = shift;
391             my $lang = shift;
392             $self->{subjects}->{$lang || $self->{lang} || ''} = $subj;
393             }
394             $self
395             }
396              
397             =item B
398              
399             This method returns a list of key value pairs
400             with the language tag as key and the subject as value.
401              
402             The subject which has the empty string as key has no
403             language attached.
404              
405             =cut
406              
407             sub subjects {
408             %{$_[0]->{subjects} || {}}
409             }
410              
411             =item B
412              
413             This method returns the body of this message.
414             If the C<$lang> argument is defined a body of that
415             language will be returned or undef.
416             If the C<$lang> argument is undefined this method will
417             return either the body in the default language.
418              
419             =cut
420              
421             sub body {
422             my ($self, $lang) = @_;
423              
424             if (defined $lang) {
425             return $self->{bodies}->{$lang}
426             } else {
427             return $self->{bodies}->{$self->{lang}}
428             if defined $self->{bodies}->{$self->{lang}};
429             }
430              
431             undef
432             }
433              
434             =item B
435              
436             This method will try to find any body on the message with the
437             following try order of languagetags:
438              
439             1. $lang argument if one passed
440             2. default language
441             3. body without any language tag
442             4. body with the 'en' language tag
443             5. any body from any language
444              
445             =cut
446              
447             sub any_body {
448             my ($self, $lang) = @_;
449             if (defined $lang) {
450             return $self->{bodies}->{$lang}
451             if defined $self->{bodies}->{$lang};
452             }
453             return $self->{bodies}->{$self->{lang}}
454             if defined $self->{bodies}->{$self->{lang}};
455             return $self->{bodies}->{''}
456             if defined $self->{bodies}->{''};
457             return $self->{bodies}->{en}
458             if defined $self->{bodies}->{en};
459             return $self->{bodies}->{$_} for (keys %{$self->{bodies}});
460             return undef;
461             }
462              
463             =item B
464              
465             This method adds the body C<$body> with the optional
466             language tag C<$lang> to this message. If no C<$lang>
467             argument is passed the default language for this message will be used.
468              
469             Further body => lang pairs can passed to this function like this:
470              
471             $msg->add_body ('foobar' => undef, "barfooo" => "de");
472              
473             =cut
474              
475             sub add_body {
476             my $self = shift;
477             while (@_) {
478             my $body = shift;
479             my $lang = shift;
480             $self->{bodies}->{$lang || $self->{lang} || ''} = $body;
481             }
482             $self
483             }
484              
485             =item B
486              
487             This method returns a list of key value pairs
488             with the language tag as key and the body as value.
489              
490             The body which has the empty string as key has no
491             language attached.
492              
493             =cut
494              
495             sub bodies {
496             %{$_[0]->{bodies} || {}}
497             }
498              
499             =item B
500              
501             This method allows the user to append custom XML stuff to the message
502             when it is sent. This is an example:
503              
504             my $msg =
505             AnyEvent::XMPP::IM::Message->new (
506             body => "Test!",
507             to => "test@test.tld",
508             );
509             $msg->append_creation (sub {
510             my ($w) = @_;
511             $w->startTag (['http://test.namespace','test']);
512             $w->characters ("TEST");
513             $w->endTag;
514             });
515              
516             $msg->send ($con);
517              
518             This should send a message stanza similar to this:
519              
520             =cut
521              
522             sub append_creation {
523             my ($self, $cb) = @_;
524             push @{$self->{create_cbs}}, $cb;
525             }
526              
527             =back
528              
529             =head1 AUTHOR
530              
531             Robin Redeker, C<< >>, JID: C<< >>
532              
533             =head1 COPYRIGHT & LICENSE
534              
535             Copyright 2007, 2008 Robin Redeker, all rights reserved.
536              
537             This program is free software; you can redistribute it and/or modify it
538             under the same terms as Perl itself.
539              
540             =cut
541              
542             1; # End of AnyEvent::XMPP