3 # Copyright (c) 2009 Matej Cepl <mcepl () redhat ! com>
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
13 # The above copyright notice and this permission notice shall be
14 # included in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 my $pluginName = "open-chats-xmpp";
29 $botname = "USERSERV";
31 perl_api_version
=> 2,
32 name
=> "Perl: Open Chats from XMPP Bookmarks",
34 summary
=> "Opens all XMPP chats according to bookmarks" .
35 "stored on the server.",
36 description
=> "Opens all XMPP chats according to bookmarks" .
37 "stored on the server.",
38 author
=> "Matěj Cepl <mcepl () redhat ! com>",
39 url
=> "http://matej.ceplovi.cz",
40 load
=> "plugin_load",
41 unload
=> "plugin_unload",
44 # list of outstanding IDs for <iq>s we are waiting to get answer
45 my @requests_queue = ();
50 my @found = grep($_ eq "$element" , @requests_queue);
52 Purple
::Debug
::misc
("$pluginName",
53 "Element $element found in queue $count times.\n(@found)\n");
63 foreach my $item (@requests_queue) {
64 if ($item =~ /$element/) {
65 @requests_queue = grep (!/$item/,@requests_queue);
75 my $callback_function = shift ;
77 my $randid = "bkmks-" . int(rand(100));
78 while (is_queued
($randid)) {
79 $randid = "bkmks-" . int(rand(100));
82 my $nodestr = '<iq type="get" id="' . $randid . '">' . $payload . '</iq>';
83 Purple
::Debug
::misc
("$pluginName","sending packet:\n$nodestr\nto $conn\n");
84 my $ret = Purple
::Prpl
::send_raw
($conn,$nodestr);
85 push @requests_queue, $randid;
87 my $no_connected_signals = @connected_signals;
88 if ($no_connected_signals == 0) {
89 Purple
::Debug
::misc
("$pluginName",
90 "Connecting got_xml_cb to jabber-receiving-iq signal\n");
91 my $jabber = Purple
::Find
::prpl
("prpl-jabber");
93 die("No jabber protocol?, weird: $!\n");
95 $consignal = Purple
::Signal
::connect($jabber,
96 "jabber-receiving-iq",$plugin,\
&got_xml_cb
, 0);
97 push @connected_signals,$consignal;
102 my $im_connection = shift; # current Connection
104 send_iq_request
($im_connection,
105 '<pubsub xmlns="http://jabber.org/protocol/pubsub">' .
106 '<items node="storage:bookmarks"/></pubsub>',
110 sub process_conference_node
{
112 my $curnode = shift ;
114 my $autojoin = lc($curnode->get_attrib('autojoin'));
116 my $count = grep (/$autojoin/ , (1,"true") );
118 my ($room,$server) = split(/@/,$curnode->get_attrib('jid'));
119 my $handlenode = $curnode->get_child("nick");
120 my $handle = $handlenode->get_data();
121 my $blist_chat = Purple
::BuddyList
::find_chat
($conn,$room);
122 Purple
::Debug
::info
("$pluginName","\$blist_chat = $blist_chat\n");
129 Purple
::Debug
::info
("$pluginName",
130 "join_chat: " . Dumper
(%components) . "\n");
131 Purple
::Serv
::join_chat
($conn,\
%components);
137 my $queue_length = @requests_queue;
138 if ($queue_length == 0) {
139 foreach my $signal (@connected_signals) {
140 Purple
::Prefs
::disconnect_by_handle
($signal);
144 my $conn = shift; # connection
145 my $iq_type = shift; # what type of IQ is this?
146 my $iq_id = shift; # what's the ID of the incoming IQ?
147 my $iq_from = shift; # who is the IQ from?
148 my $packet = shift; # xmlnode
149 my $soughtid = shift; # random ID
150 Purple
::Debug
::misc
("$pluginName",
151 "IQ received: \$iq_type = $iq_type, \$iq_id = $iq_id, ' .
152 '\$iq_from = $iq_from\n\$packet = $packet\n");
154 if (($iq_type eq 'result') && is_queued
($iq_id)) {
155 pick_from_queue
($iq_id,@requests_queue);
157 my $packetstr = $packet->to_str();
158 Purple
::Debug
::info
("$pluginName", "packet: $packetstr\n");
159 # TODO check that items/@node == "storage:bookmarks" and/or
160 # xmlns of storage is that.
161 my $curnode = $packet->get_child("pubsub/items/item/storage/conference");
163 Purple
::Debug
::info
("$pluginName", "conference: " .
164 $curnode->to_str() . "\n");
165 process_conference_node
($conn,$curnode);
166 $curnode = $curnode->get_next_twin();
172 # http://xmpp.org/extensions/xep-0048.html
173 # http://xmpp.org/extensions/xep-0223.html
174 # http://xmpp.org/extensions/xep-0060.html
177 my $conv = shift; # PurpleConversation
178 Purple
::Debug
::info
("$pluginName", "joined chat " .
179 $conv->get_name() . " for account " .
180 $conv->get_account()->get_username() . "\n");
181 # if not("chat already registered") then add_to_server
185 my $conv = shift; # PurpleConversation
186 Purple
::Debug
::info
("$pluginName", "left chat " .
187 $conv->get_name() . " for account " .
188 $conv->get_account()->get_username() . "\n");
189 # if "chat already registered" then remove_from_server
192 my @connected_signals = ();
197 my $account = $conn->get_account();
198 my $username = $account->get_username();
199 my $protocol_id = $account->get_protocol_id();
201 Purple
::Debug
::misc
("$pluginName",
202 "signed-on $username @ $account ($protocol_id)\n");
203 if ($protocol_id eq "prpl-jabber") {
204 get_bookmarks
($conn);
205 @buddies = Purple
::Find
::buddies
($account,"");
211 my $connected_signal;
213 # it doesn't make any sense when we don't have jabber
214 my $jabber = Purple
::Find
::prpl
("prpl-jabber");
219 # connect signed-on signal
220 $conn = Purple
::Connections
::get_handle
();
221 $consignal = Purple
::Signal
::connect($conn, "signed-on", $plugin,
223 push @connected_signals,$consignal;
225 # connect IQ management signals
226 $consignal = Purple
::Signal
::connect($jabber,
227 "jabber-receiving-iq",$plugin,\
&got_xml_cb
, 0);
228 push @connected_signals,$consignal;
230 # connect chat management signals
231 $conn = Purple
::Conversations
::get_handle
();
232 $consignal = Purple
::Signal
::connect($conn,
233 "chat-joined",$plugin,\
&joined_chat
, 0);
234 push @connected_signals,$consignal;
235 $consignal = Purple
::Signal
::connect($conn,
236 "chat-left",$plugin,\
&left_chat
, 0);
237 push @connected_signals,$consignal;
239 # Initialize a buddy list
240 # FIXME Do we need it? What it is good for?
241 $blist = Purple
::get_blist
();
242 Purple
::Debug
::misc
("$pluginName",
243 "Getting the current Buddy List\n" . Dumper
($blist) . "\n");
244 my $node = Purple
::BuddyList
::get_root
();
248 foreach my $signal (@connected_signals) {
249 Purple
::Prefs
::disconnect_by_handle
($signal);
251 Purple
::Debug
::info
("$pluginName", "Login to $botname plugin unloaded\n");