social_stream-presence 0.8.4 → 0.8.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. data/app/assets/javascripts/chat_interface_manager.js.erb +42 -132
  2. data/app/assets/javascripts/chat_persistence.js +84 -70
  3. data/app/assets/javascripts/chat_utilities.js +10 -33
  4. data/app/assets/javascripts/chat_window_manager.js +275 -217
  5. data/app/assets/javascripts/jquery.ui.chatbox.sstreampresence.js +9 -2
  6. data/app/assets/javascripts/notifications.js +191 -0
  7. data/app/assets/javascripts/social_stream-presence.js +1 -0
  8. data/app/assets/javascripts/videochat.js.erb +4 -24
  9. data/app/assets/javascripts/xmpp_client_management.js.erb +369 -47
  10. data/app/assets/stylesheets/chat.css.scss +1 -1
  11. data/app/views/chat/_contacts.html.erb +5 -5
  12. data/app/views/chat/_index.html.erb +10 -2
  13. data/config/locales/en.yml +9 -1
  14. data/config/locales/es.yml +9 -1
  15. data/ejabberd/ejabberd_files.zip +0 -0
  16. data/ejabberd/ejabberd_scripts/emanagement +132 -2
  17. data/ejabberd/installer.sh +1 -0
  18. data/ejabberd/mod_muc_admin/mod_muc_admin.beam +0 -0
  19. data/ejabberd/mod_muc_admin/mod_muc_admin.erl +871 -0
  20. data/ejabberd/mod_sspresence/mod_sspresence.beam +0 -0
  21. data/lib/social_stream-presence.rb +1 -1
  22. data/lib/social_stream/presence/engine.rb +6 -0
  23. data/lib/social_stream/presence/models/buddy_manager.rb +32 -26
  24. data/lib/social_stream/presence/models/group_manager.rb +51 -0
  25. data/lib/social_stream/presence/version.rb +1 -1
  26. data/lib/social_stream/presence/xmpp_server_order.rb +84 -10
  27. data/lib/tasks/presence/synchronize.rake +15 -0
  28. data/vendor/assets/javascripts/strophe.muc.js +934 -0
  29. metadata +9 -24
@@ -14,9 +14,9 @@ module SocialStream
14
14
 
15
15
  module Models
16
16
  autoload :BuddyManager, 'social_stream/presence/models/buddy_manager'
17
+ autoload :GroupManager, 'social_stream/presence/models/group_manager'
17
18
  end
18
19
 
19
-
20
20
  mattr_accessor :domain
21
21
  mattr_accessor :bosh_service
22
22
  mattr_accessor :auth_method
@@ -6,6 +6,12 @@ module SocialStream
6
6
  include SocialStream::Presence::Models::BuddyManager
7
7
  end
8
8
  end
9
+
10
+ initializer "social_stream-presence.group" do
11
+ ActiveSupport.on_load(:group) do
12
+ include SocialStream::Presence::Models::GroupManager
13
+ end
14
+ end
9
15
 
10
16
  initializer "social_stream-presence.views.settings" do
11
17
  SocialStream::Views::Settings.module_eval do
@@ -23,35 +23,41 @@ module SocialStream
23
23
  return
24
24
  end
25
25
 
26
- #WEB DOMAIN
27
- domain = SocialStream::Presence.domain
28
- user_sid = self.sender.slug + "@" + domain
29
- user_name = self.sender.name
30
- buddy_sid = self.receiver.slug + "@" + domain
31
- buddy_name = self.receiver.name
32
- site_name = I18n.t('site.name').delete(' ')
33
-
34
- #Check if is a positive and replied tie
35
- if self.bidirectional?
36
- #Execute setRosterForBidirectionalTie(userASid,userBSid,userANick,userBNick,groupForA,groupForB)
37
- SocialStream::Presence::XmppServerOrder::setRosterForBidirectionalTie(user_sid,buddy_sid,user_name,buddy_name,site_name,site_name)
38
- elsif self.positive?
39
- #Case: Possitive tie unidirectional
40
- #Execute addBuddyToRoster(userSID,buddySID,buddyNick,buddyGroup,subscription_type)
41
- subscription_type = "from"
42
- SocialStream::Presence::XmppServerOrder::addBuddyToRoster(user_sid,buddy_sid,buddy_name,site_name,subscription_type)
43
- else
44
- #Negative Tie
26
+ begin
27
+ #WEB DOMAIN
28
+ domain = SocialStream::Presence.domain
29
+ user_sid = self.sender.slug + "@" + domain
30
+ user_name = self.sender.name
31
+ buddy_sid = self.receiver.slug + "@" + domain
32
+ buddy_name = self.receiver.name
33
+ site_name = I18n.t('site.name').delete(' ')
45
34
 
46
- if self.contact.positive_replied?
47
- #Bidirectional contacts
48
- #Execute unsetRosterForBidirectionalTie(user_sid,oldfriend_sid,oldfriendNick,oldfriendGroup)
49
- SocialStream::Presence::XmppServerOrder::unsetRosterForBidirectionalTie(buddy_sid,user_sid,user_name,site_name)
35
+ #Check if is a positive and replied tie
36
+ if self.bidirectional?
37
+ #Execute setRosterForBidirectionalTie(userASid,userBSid,userANick,userBNick,groupForA,groupForB)
38
+ SocialStream::Presence::XmppServerOrder::setRosterForBidirectionalTie(user_sid,buddy_sid,user_name,buddy_name,site_name,site_name)
39
+ elsif self.positive?
40
+ #Case: Possitive tie unidirectional
41
+ #Execute addBuddyToRoster(userSID,buddySID,buddyNick,buddyGroup,subscription_type)
42
+ subscription_type = "from"
43
+ SocialStream::Presence::XmppServerOrder::addBuddyToRoster(user_sid,buddy_sid,buddy_name,site_name,subscription_type)
50
44
  else
51
- SocialStream::Presence::XmppServerOrder::removeBuddyFromRoster(user_sid,buddy_sid)
45
+ #Negative Tie
46
+
47
+ if self.contact.positive_replied?
48
+ #Bidirectional contacts
49
+ #Execute unsetRosterForBidirectionalTie(user_sid,oldfriend_sid,oldfriendNick,oldfriendGroup)
50
+ SocialStream::Presence::XmppServerOrder::unsetRosterForBidirectionalTie(buddy_sid,user_sid,user_name,site_name)
51
+ else
52
+ SocialStream::Presence::XmppServerOrder::removeBuddyFromRoster(user_sid,buddy_sid)
53
+ end
54
+
55
+ return
52
56
  end
53
-
54
- return
57
+
58
+ rescue Exception => e
59
+ logger.warn ("WARNING Exeception in Buddy Manager save_buddy: " + e.message)
60
+ puts ("WARNING Exeception in Buddy Manager save_buddy: " + e.message)
55
61
  end
56
62
 
57
63
  end
@@ -0,0 +1,51 @@
1
+ module SocialStream
2
+ module Presence
3
+ module Models
4
+ module GroupManager
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ after_create :create_group_room
9
+ after_destroy :remove_group_room
10
+ end
11
+
12
+ def create_group_room
13
+
14
+ unless SocialStream::Presence.enable
15
+ return
16
+ end
17
+
18
+ unless self.subject_type == "Group"
19
+ return
20
+ end
21
+
22
+ begin
23
+ SocialStream::Presence::XmppServerOrder::createPersistentRoom(self.slug,SocialStream::Presence.domain)
24
+ rescue Exception => e
25
+ logger.warn ("WARNING Exeception in Group Manager create_group_room: " + e.message)
26
+ puts ("WARNING Exeception in Group Manager create_group_room: " + e.message)
27
+ end
28
+ end
29
+
30
+
31
+ def remove_group_room
32
+
33
+ unless SocialStream::Presence.enable
34
+ return
35
+ end
36
+
37
+ unless self.subject_type == "Group"
38
+ return
39
+ end
40
+
41
+ begin
42
+ SocialStream::Presence::XmppServerOrder::destroyRoom(self.slug,SocialStream::Presence.domain)
43
+ rescue Exception => e
44
+ logger.warn ("WARNING Exeception in Group Manager remove_group_room: " + e.message)
45
+ puts ("WARNING Exeception in Group Manager remove_group_room: " + e.message)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,5 +1,5 @@
1
1
  module SocialStream
2
2
  module Presence
3
- VERSION = "0.8.4"
3
+ VERSION = "0.8.6"
4
4
  end
5
5
  end
@@ -7,7 +7,11 @@ module SocialStream
7
7
  class XmppServerOrder
8
8
 
9
9
  class << self
10
-
10
+
11
+ ##################
12
+ #Emanagement Calls
13
+ ##################
14
+
11
15
  def setRosterForBidirectionalTie(userASid,userBSid,userANick,userBNick,groupForA,groupForB)
12
16
  executeEmanagementCommand("setBidireccionalBuddys",[userASid,userBSid,userANick,userBNick,groupForA,groupForB])
13
17
  end
@@ -27,8 +31,23 @@ module SocialStream
27
31
  executeEmanagementCommand("removeBuddyFromRoster",[userSid,buddySid])
28
32
  end
29
33
 
34
+
35
+ def createPersistentRoom(roomName,domain)
36
+ executeEmanagementCommand("createPersistentRoom",[roomName,domain])
37
+ end
38
+
39
+
40
+ def destroyRoom(roomName,domain)
41
+ executeEmanagementCommand("destroyRoom",[roomName,domain])
42
+ end
43
+
30
44
 
45
+
46
+
47
+ ##################
31
48
  # Presence synchronization
49
+ ##################
50
+
32
51
  def synchronizePresence(webDomain)
33
52
  if isEjabberdNodeUp
34
53
  if (webDomain=="all")
@@ -106,8 +125,12 @@ module SocialStream
106
125
  end
107
126
 
108
127
 
109
-
110
- # Rosters synchronization
128
+
129
+
130
+ ##################
131
+ # Rosters synchronization
132
+ ##################
133
+
111
134
  def removeAllRosters(webDomain)
112
135
  executeEmanagementCommand("removeAllRostersByDomain",[webDomain])
113
136
  end
@@ -140,7 +163,39 @@ module SocialStream
140
163
  end
141
164
 
142
165
 
143
- #Installation methods
166
+
167
+
168
+ ##################
169
+ # Room (MUC) synchronization
170
+ ##################
171
+
172
+ def removeAllRooms(webDomain)
173
+ executeEmanagementCommand("destroyAllRoomsByDomain",[webDomain])
174
+ end
175
+
176
+
177
+ def synchronizeRooms(webDomain)
178
+ commands = []
179
+
180
+ #Remove all mucs
181
+ commands << buildCommand("emanagement","destroyAllRoomsByDomain",[webDomain])
182
+
183
+ #Populate mucs
184
+ groups = Group.all
185
+
186
+ groups.each do |group|
187
+ commands << buildCommand("emanagement","createRoom",[group.slug,webDomain])
188
+ end
189
+
190
+ executeCommands(commands)
191
+ end
192
+
193
+
194
+
195
+
196
+ ##################
197
+ # Installation methods
198
+ ##################
144
199
 
145
200
  def copyFolderToXmppServer(oPath,dPath)
146
201
  if SocialStream::Presence.remote_xmpp_server
@@ -311,7 +366,12 @@ module SocialStream
311
366
  puts "Finish"
312
367
  end
313
368
 
314
- #Execution commands manage
369
+
370
+
371
+
372
+ ##################
373
+ # Execution commands management
374
+ ##################
315
375
 
316
376
  def buildCommand(script,order,params)
317
377
  command = SocialStream::Presence.scripts_path + "/" + script + " " + order
@@ -411,7 +471,12 @@ module SocialStream
411
471
  end
412
472
 
413
473
 
414
- #Authorization methods
474
+
475
+
476
+ ##################
477
+ # Authorization methods
478
+ ##################
479
+
415
480
  def authorization(params)
416
481
  case SocialStream::Presence.secure_rest_api
417
482
  when true
@@ -509,11 +574,15 @@ module SocialStream
509
574
  #Non Secure Mode
510
575
  return params
511
576
  end
512
- end
577
+ end
513
578
 
514
579
 
515
- #Help methods
516
-
580
+
581
+
582
+ ##################
583
+ # Help methods
584
+ ##################
585
+
517
586
  def isEjabberdNodeUp
518
587
  output = executeEmanagementCommand("isEjabberdNodeStarted",[])
519
588
  nodeUp = output.split("\n")[0]
@@ -536,7 +605,12 @@ module SocialStream
536
605
  end
537
606
 
538
607
 
539
- #Multidomain tasks
608
+
609
+
610
+ ##################
611
+ # Multidomain tasks
612
+ ##################
613
+
540
614
  def addWebDomain(domain,url)
541
615
  commands = []
542
616
  if url
@@ -32,5 +32,20 @@ namespace :presence do
32
32
  SocialStream::Presence::XmppServerOrder::synchronizeRosters(domain)
33
33
  puts "Rosters Synchronization complete"
34
34
  end
35
+
36
+ desc "Synchronize Xmpp Server database with Social Stream Rails Application database."
37
+ desc "Remove all rooms and create one room (also knowledge as MUC) for each Social Stream group."
38
+ task :rooms, [:domain] => :environment do |t, args|
39
+ puts "Starting presence:synchronize:rooms"
40
+ unless args[:domain]
41
+ puts "No web domain specified"
42
+ domain = SocialStream::Presence.domain
43
+ puts "Executing rake presence:synchronize:rooms[" + domain + "]"
44
+ else
45
+ domain = args[:domain]
46
+ end
47
+ SocialStream::Presence::XmppServerOrder::synchronizeRooms(domain)
48
+ puts "Rooms Synchronization complete"
49
+ end
35
50
  end
36
51
  end
@@ -0,0 +1,934 @@
1
+ /*
2
+ *Plugin to implement the MUC extension.
3
+ http://xmpp.org/extensions/xep-0045.html
4
+ *Previous Author:
5
+ Nathan Zorn <nathan.zorn@gmail.com>
6
+ *Complete CoffeeScript rewrite:
7
+ Andreas Guth <guth@dbis.rwth-aachen.de>
8
+ */
9
+ var Occupant, RoomConfig, XmppRoom,
10
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
11
+
12
+ Strophe.addConnectionPlugin('muc', {
13
+ _connection: null,
14
+ rooms: [],
15
+ /*Function
16
+ Initialize the MUC plugin. Sets the correct connection object and
17
+ extends the namesace.
18
+ */
19
+ init: function(conn) {
20
+ this._connection = conn;
21
+ this._muc_handler = null;
22
+ Strophe.addNamespace('MUC_OWNER', Strophe.NS.MUC + "#owner");
23
+ Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC + "#admin");
24
+ Strophe.addNamespace('MUC_USER', Strophe.NS.MUC + "#user");
25
+ return Strophe.addNamespace('MUC_ROOMCONF', Strophe.NS.MUC + "#roomconfig");
26
+ },
27
+ /*Function
28
+ Join a multi-user chat room
29
+ Parameters:
30
+ (String) room - The multi-user chat room to join.
31
+ (String) nick - The nickname to use in the chat room. Optional
32
+ (Function) msg_handler_cb - The function call to handle messages from the
33
+ specified chat room.
34
+ (Function) pres_handler_cb - The function call back to handle presence
35
+ in the chat room.
36
+ (String) password - The optional password to use. (password protected
37
+ rooms only)
38
+ */
39
+ join: function(room, nick, msg_handler_cb, pres_handler_cb, roster_cb, password) {
40
+ var msg, room_nick, _base,
41
+ _this = this;
42
+ room_nick = this.test_append_nick(room, nick);
43
+ msg = $pres({
44
+ from: this._connection.jid,
45
+ to: room_nick
46
+ }).c("x", {
47
+ xmlns: Strophe.NS.MUC
48
+ });
49
+ if (password != null) msg.cnode(Strophe.xmlElement("password", [], password));
50
+ if (this._muc_handler == null) {
51
+ this._muc_handler = this._connection.addHandler(function(stanza) {
52
+ var from, handler, handlers, id, roomname, x, xmlns, xquery, _i, _len;
53
+ from = stanza.getAttribute('from');
54
+ roomname = from.split("/")[0];
55
+ if (!_this.rooms[roomname]) return true;
56
+ room = _this.rooms[roomname];
57
+ handlers = {};
58
+ if (stanza.nodeName === "message") {
59
+ handlers = room._message_handlers;
60
+ } else if (stanza.nodeName === "presence") {
61
+ xquery = stanza.getElementsByTagName("x");
62
+ if (xquery.length > 0) {
63
+ for (_i = 0, _len = xquery.length; _i < _len; _i++) {
64
+ x = xquery[_i];
65
+ xmlns = x.getAttribute("xmlns");
66
+ if (xmlns && xmlns.match(Strophe.NS.MUC)) {
67
+ handlers = room._presence_handlers;
68
+ break;
69
+ }
70
+ }
71
+ }
72
+ }
73
+ for (id in handlers) {
74
+ handler = handlers[id];
75
+ if (!handler(stanza, room)) delete handlers[id];
76
+ }
77
+ return true;
78
+ });
79
+ }
80
+ if ((_base = this.rooms)[room] == null) {
81
+ _base[room] = new XmppRoom(this, room, nick, password);
82
+ }
83
+ if (pres_handler_cb) this.rooms[room].addHandler('presence', pres_handler_cb);
84
+ if (msg_handler_cb) this.rooms[room].addHandler('message', msg_handler_cb);
85
+ if (roster_cb) this.rooms[room].addHandler('roster', roster_cb);
86
+ return this._connection.send(msg);
87
+ },
88
+ /*Function
89
+ Leave a multi-user chat room
90
+ Parameters:
91
+ (String) room - The multi-user chat room to leave.
92
+ (String) nick - The nick name used in the room.
93
+ (Function) handler_cb - Optional function to handle the successful leave.
94
+ (String) exit_msg - optional exit message.
95
+ Returns:
96
+ iqid - The unique id for the room leave.
97
+ */
98
+ leave: function(room, nick, handler_cb, exit_msg) {
99
+ var presence, presenceid, room_nick;
100
+ delete this.rooms[room];
101
+ if (this.rooms.length === 0) {
102
+ this._connection.deleteHandler(this._muc_handler);
103
+ this._muc_handler = null;
104
+ }
105
+ room_nick = this.test_append_nick(room, nick);
106
+ presenceid = this._connection.getUniqueId();
107
+ presence = $pres({
108
+ type: "unavailable",
109
+ id: presenceid,
110
+ from: this._connection.jid,
111
+ to: room_nick
112
+ });
113
+ if (exit_msg != null) presence.c("status", exit_msg);
114
+ if (handler_cb != null) {
115
+ this._connection.addHandler(handler_cb, null, "presence", null, presenceid);
116
+ }
117
+ this._connection.send(presence);
118
+ return presenceid;
119
+ },
120
+ /*Function
121
+ Parameters:
122
+ (String) room - The multi-user chat room name.
123
+ (String) nick - The nick name used in the chat room.
124
+ (String) message - The plaintext message to send to the room.
125
+ (String) html_message - The message to send to the room with html markup.
126
+ (String) type - "groupchat" for group chat messages o
127
+ "chat" for private chat messages
128
+ Returns:
129
+ msgiq - the unique id used to send the message
130
+ */
131
+ message: function(room, nick, message, html_message, type) {
132
+ var msg, msgid, parent, room_nick;
133
+ room_nick = this.test_append_nick(room, nick);
134
+ type = type || (nick != null ? "chat" : "groupchat");
135
+ msgid = this._connection.getUniqueId();
136
+ msg = $msg({
137
+ to: room_nick,
138
+ from: this._connection.jid,
139
+ type: type,
140
+ id: msgid
141
+ }).c("body", {
142
+ xmlns: Strophe.NS.CLIENT
143
+ }).t(message);
144
+ msg.up();
145
+ if (html_message != null) {
146
+ msg.c("html", {
147
+ xmlns: Strophe.NS.XHTML_IM
148
+ }).c("body", {
149
+ xmlns: Strophe.NS.XHTML
150
+ }).h(html_message);
151
+ if (msg.node.childNodes.length === 0) {
152
+ parent = msg.node.parentNode;
153
+ msg.up().up();
154
+ msg.node.removeChild(parent);
155
+ } else {
156
+ msg.up().up();
157
+ }
158
+ }
159
+ msg.c("x", {
160
+ xmlns: "jabber:x:event"
161
+ }).c("composing");
162
+ this._connection.send(msg);
163
+ return msgid;
164
+ },
165
+ /*Function
166
+ Convenience Function to send a Message to all Occupants
167
+ Parameters:
168
+ (String) room - The multi-user chat room name.
169
+ (String) message - The plaintext message to send to the room.
170
+ (String) html_message - The message to send to the room with html markup.
171
+ Returns:
172
+ msgiq - the unique id used to send the message
173
+ */
174
+ groupchat: function(room, message, html_message) {
175
+ return this.message(room, null, message, html_message);
176
+ },
177
+ /*Function
178
+ Send a mediated invitation.
179
+ Parameters:
180
+ (String) room - The multi-user chat room name.
181
+ (String) receiver - The invitation's receiver.
182
+ (String) reason - Optional reason for joining the room.
183
+ Returns:
184
+ msgiq - the unique id used to send the invitation
185
+ */
186
+ invite: function(room, receiver, reason) {
187
+ var invitation, msgid;
188
+ msgid = this._connection.getUniqueId();
189
+ invitation = $msg({
190
+ from: this._connection.jid,
191
+ to: room,
192
+ id: msgid
193
+ }).c('x', {
194
+ xmlns: Strophe.NS.MUC_USER
195
+ }).c('invite', {
196
+ to: receiver
197
+ });
198
+ if (reason != null) invitation.c('reason', reason);
199
+ this._connection.send(invitation);
200
+ return msgid;
201
+ },
202
+ /*Function
203
+ Send a direct invitation.
204
+ Parameters:
205
+ (String) room - The multi-user chat room name.
206
+ (String) receiver - The invitation's receiver.
207
+ (String) reason - Optional reason for joining the room.
208
+ (String) password - Optional password for the room.
209
+ Returns:
210
+ msgiq - the unique id used to send the invitation
211
+ */
212
+ directInvite: function(room, receiver, reason, password) {
213
+ var attrs, invitation, msgid;
214
+ msgid = this._connection.getUniqueId();
215
+ attrs = {
216
+ xmlns: 'jabber:x:conference',
217
+ jid: room
218
+ };
219
+ if (reason != null) attrs.reason = reason;
220
+ if (password != null) attrs.password = password;
221
+ invitation = $msg({
222
+ from: this._connection.jid,
223
+ to: receiver,
224
+ id: msgid
225
+ }).c('x', attrs);
226
+ this._connection.send(invitation);
227
+ return msgid;
228
+ },
229
+ /*Function
230
+ Queries a room for a list of occupants
231
+ (String) room - The multi-user chat room name.
232
+ (Function) success_cb - Optional function to handle the info.
233
+ (Function) error_cb - Optional function to handle an error.
234
+ Returns:
235
+ id - the unique id used to send the info request
236
+ */
237
+ queryOccupants: function(room, success_cb, error_cb) {
238
+ var attrs, info;
239
+ attrs = {
240
+ xmlns: Strophe.NS.DISCO_ITEMS
241
+ };
242
+ info = $iq({
243
+ from: this._connection.jid,
244
+ to: room,
245
+ type: 'get'
246
+ }).c('query', attrs);
247
+ return this._connection.sendIQ(info, success_cb, error_cb);
248
+ },
249
+ /*Function
250
+ Start a room configuration.
251
+ Parameters:
252
+ (String) room - The multi-user chat room name.
253
+ (Function) handler_cb - Optional function to handle the config form.
254
+ Returns:
255
+ id - the unique id used to send the configuration request
256
+ */
257
+ configure: function(room, handler_cb) {
258
+ var config, id, stanza;
259
+ config = $iq({
260
+ to: room,
261
+ type: "get"
262
+ }).c("query", {
263
+ xmlns: Strophe.NS.MUC_OWNER
264
+ });
265
+ stanza = config.tree();
266
+ id = this._connection.sendIQ(stanza);
267
+ if (handler_cb != null) {
268
+ this._connection.addHandler(function(stanza) {
269
+ handler_cb(stanza);
270
+ return false;
271
+ }, Strophe.NS.MUC_OWNER, "iq", null, id);
272
+ }
273
+ return id;
274
+ },
275
+ /*Function
276
+ Cancel the room configuration
277
+ Parameters:
278
+ (String) room - The multi-user chat room name.
279
+ Returns:
280
+ id - the unique id used to cancel the configuration.
281
+ */
282
+ cancelConfigure: function(room) {
283
+ var config, stanza;
284
+ config = $iq({
285
+ to: room,
286
+ type: "set"
287
+ }).c("query", {
288
+ xmlns: Strophe.NS.MUC_OWNER
289
+ }).c("x", {
290
+ xmlns: "jabber:x:data",
291
+ type: "cancel"
292
+ });
293
+ stanza = config.tree();
294
+ return this._connection.sendIQ(stanza);
295
+ },
296
+ /*Function
297
+ Save a room configuration.
298
+ Parameters:
299
+ (String) room - The multi-user chat room name.
300
+ (Array) configarray - an array of form elements used to configure the room.
301
+ Returns:
302
+ id - the unique id used to save the configuration.
303
+ */
304
+ saveConfiguration: function(room, configarray) {
305
+ var conf, config, stanza, _i, _len;
306
+ config = $iq({
307
+ to: room,
308
+ type: "set"
309
+ }).c("query", {
310
+ xmlns: Strophe.NS.MUC_OWNER
311
+ }).c("x", {
312
+ xmlns: "jabber:x:data",
313
+ type: "submit"
314
+ });
315
+ for (_i = 0, _len = configarray.length; _i < _len; _i++) {
316
+ conf = configarray[_i];
317
+ config.cnode(conf).up();
318
+ }
319
+ stanza = config.tree();
320
+ return this._connection.sendIQ(stanza);
321
+ },
322
+ /*Function
323
+ Parameters:
324
+ (String) room - The multi-user chat room name.
325
+ Returns:
326
+ id - the unique id used to create the chat room.
327
+ */
328
+ createInstantRoom: function(room) {
329
+ var roomiq;
330
+ roomiq = $iq({
331
+ to: room,
332
+ type: "set"
333
+ }).c("query", {
334
+ xmlns: Strophe.NS.MUC_OWNER
335
+ }).c("x", {
336
+ xmlns: "jabber:x:data",
337
+ type: "submit"
338
+ });
339
+ return this._connection.sendIQ(roomiq.tree());
340
+ },
341
+ /*Function
342
+ Set the topic of the chat room.
343
+ Parameters:
344
+ (String) room - The multi-user chat room name.
345
+ (String) topic - Topic message.
346
+ */
347
+ setTopic: function(room, topic) {
348
+ var msg;
349
+ msg = $msg({
350
+ to: room,
351
+ from: this._connection.jid,
352
+ type: "groupchat"
353
+ }).c("subject", {
354
+ xmlns: "jabber:client"
355
+ }).t(topic);
356
+ return this._connection.send(msg.tree());
357
+ },
358
+ /*Function
359
+ Internal Function that Changes the role or affiliation of a member
360
+ of a MUC room. This function is used by modifyRole and modifyAffiliation.
361
+ The modification can only be done by a room moderator. An error will be
362
+ returned if the user doesn't have permission.
363
+ Parameters:
364
+ (String) room - The multi-user chat room name.
365
+ (Object) item - Object with nick and role or jid and affiliation attribute
366
+ (String) reason - Optional reason for the change.
367
+ (Function) handler_cb - Optional callback for success
368
+ (Function) errer_cb - Optional callback for error
369
+ Returns:
370
+ iq - the id of the mode change request.
371
+ */
372
+ _modifyPrivilege: function(room, item, reason, handler_cb, error_cb) {
373
+ var iq;
374
+ iq = $iq({
375
+ to: room,
376
+ type: "set"
377
+ }).c("query", {
378
+ xmlns: Strophe.NS.MUC_ADMIN
379
+ }).cnode(item.node);
380
+ if (reason != null) iq.c("reason", reason);
381
+ return this._connection.sendIQ(iq.tree(), handler_cb, error_cb);
382
+ },
383
+ /*Function
384
+ Changes the role of a member of a MUC room.
385
+ The modification can only be done by a room moderator. An error will be
386
+ returned if the user doesn't have permission.
387
+ Parameters:
388
+ (String) room - The multi-user chat room name.
389
+ (String) nick - The nick name of the user to modify.
390
+ (String) role - The new role of the user.
391
+ (String) affiliation - The new affiliation of the user.
392
+ (String) reason - Optional reason for the change.
393
+ (Function) handler_cb - Optional callback for success
394
+ (Function) errer_cb - Optional callback for error
395
+ Returns:
396
+ iq - the id of the mode change request.
397
+ */
398
+ modifyRole: function(room, nick, role, reason, handler_cb, error_cb) {
399
+ var item;
400
+ item = $build("item", {
401
+ nick: nick,
402
+ role: role
403
+ });
404
+ return this._modifyPrivilege(room, item, reason, handler_cb, error_cb);
405
+ },
406
+ kick: function(room, nick, reason, handler_cb, error_cb) {
407
+ return this.modifyRole(room, nick, 'none', reason, handler_cb, error_cb);
408
+ },
409
+ voice: function(room, nick, reason, handler_cb, error_cb) {
410
+ return this.modifyRole(room, nick, 'participant', reason, handler_cb, error_cb);
411
+ },
412
+ mute: function(room, nick, reason, handler_cb, error_cb) {
413
+ return this.modifyRole(room, nick, 'visitor', reason, handler_cb, error_cb);
414
+ },
415
+ op: function(room, nick, reason, handler_cb, error_cb) {
416
+ return this.modifyRole(room, nick, 'moderator', reason, handler_cb, error_cb);
417
+ },
418
+ deop: function(room, nick, reason, handler_cb, error_cb) {
419
+ return this.modifyRole(room, nick, 'participant', reason, handler_cb, error_cb);
420
+ },
421
+ /*Function
422
+ Changes the affiliation of a member of a MUC room.
423
+ The modification can only be done by a room moderator. An error will be
424
+ returned if the user doesn't have permission.
425
+ Parameters:
426
+ (String) room - The multi-user chat room name.
427
+ (String) jid - The jid of the user to modify.
428
+ (String) affiliation - The new affiliation of the user.
429
+ (String) reason - Optional reason for the change.
430
+ (Function) handler_cb - Optional callback for success
431
+ (Function) errer_cb - Optional callback for error
432
+ Returns:
433
+ iq - the id of the mode change request.
434
+ */
435
+ modifyAffiliation: function(room, jid, affiliation, reason, handler_cb, error_cb) {
436
+ var item;
437
+ item = $build("item", {
438
+ jid: jid,
439
+ affiliation: affiliation
440
+ });
441
+ return this._modifyPrivilege(room, item, reason, handler_cb, error_cb);
442
+ },
443
+ ban: function(room, jid, reason, handler_cb, error_cb) {
444
+ return this.modifyAffiliation(room, jid, 'outcast', reason, handler_cb, error_cb);
445
+ },
446
+ member: function(room, jid, reason, handler_cb, error_cb) {
447
+ return this.modifyAffiliation(room, jid, 'member', reason, handler_cb, error_cb);
448
+ },
449
+ revoke: function(room, jid, reason, handler_cb, error_cb) {
450
+ return this.modifyAffiliation(room, jid, 'none', reason, handler_cb, error_cb);
451
+ },
452
+ owner: function(room, jid, reason, handler_cb, error_cb) {
453
+ return this.modifyAffiliation(room, jid, 'owner', reason, handler_cb, error_cb);
454
+ },
455
+ admin: function(room, jid, reason, handler_cb, error_cb) {
456
+ return this.modifyAffiliation(room, jid, 'admin', reason, handler_cb, error_cb);
457
+ },
458
+ /*Function
459
+ Change the current users nick name.
460
+ Parameters:
461
+ (String) room - The multi-user chat room name.
462
+ (String) user - The new nick name.
463
+ */
464
+ changeNick: function(room, user) {
465
+ var presence, room_nick;
466
+ room_nick = this.test_append_nick(room, user);
467
+ presence = $pres({
468
+ from: this._connection.jid,
469
+ to: room_nick,
470
+ id: this._connection.getUniqueId()
471
+ });
472
+ return this._connection.send(presence.tree());
473
+ },
474
+ /*Function
475
+ Change the current users status.
476
+ Parameters:
477
+ (String) room - The multi-user chat room name.
478
+ (String) user - The current nick.
479
+ (String) show - The new show-text.
480
+ (String) status - The new status-text.
481
+ */
482
+ setStatus: function(room, user, show, status) {
483
+ var presence, room_nick;
484
+ room_nick = this.test_append_nick(room, user);
485
+ presence = $pres({
486
+ from: this._connection.jid,
487
+ to: room_nick
488
+ });
489
+ if (show != null) presence.c('show', show).up();
490
+ if (status != null) presence.c('status', status);
491
+ return this._connection.send(presence.tree());
492
+ },
493
+ /*Function
494
+ List all chat room available on a server.
495
+ Parameters:
496
+ (String) server - name of chat server.
497
+ (String) handle_cb - Function to call for room list return.
498
+ */
499
+ listRooms: function(server, handle_cb) {
500
+ var iq;
501
+ iq = $iq({
502
+ to: server,
503
+ from: this._connection.jid,
504
+ type: "get"
505
+ }).c("query", {
506
+ xmlns: Strophe.NS.DISCO_ITEMS
507
+ });
508
+ return this._connection.sendIQ(iq, handle_cb);
509
+ },
510
+ test_append_nick: function(room, nick) {
511
+ return room + (nick != null ? "/" + (Strophe.escapeNode(nick)) : "");
512
+ }
513
+ });
514
+
515
+ XmppRoom = (function() {
516
+
517
+ XmppRoom.prototype.roster = {};
518
+
519
+ XmppRoom.prototype._message_handlers = {};
520
+
521
+ XmppRoom.prototype._presence_handlers = {};
522
+
523
+ XmppRoom.prototype._roster_handlers = {};
524
+
525
+ XmppRoom.prototype._handler_ids = 0;
526
+
527
+ function XmppRoom(client, name, nick, password) {
528
+ this.client = client;
529
+ this.name = name;
530
+ this.nick = nick;
531
+ this.password = password;
532
+ this._roomRosterHandler = __bind(this._roomRosterHandler, this);
533
+ this._addOccupant = __bind(this._addOccupant, this);
534
+ if (client.muc) this.client = client.muc;
535
+ this.name = Strophe.getBareJidFromJid(name);
536
+ this.client.rooms[this.name] = this;
537
+ this.addHandler('presence', this._roomRosterHandler);
538
+ }
539
+
540
+ XmppRoom.prototype.join = function(msg_handler_cb, pres_handler_cb) {
541
+ if (!this.client.rooms[this.name]) {
542
+ return this.client.join(this.name, this.nick, msg_handler_cb, pres_handler_cb, this.password);
543
+ }
544
+ };
545
+
546
+ XmppRoom.prototype.leave = function(handler_cb, message) {
547
+ this.client.leave(this.name, this.nick, handler_cb, message);
548
+ return delete this.client.rooms[this.name];
549
+ };
550
+
551
+ XmppRoom.prototype.message = function(nick, message, html_message, type) {
552
+ return this.client.message(this.name, nick, message, html_message, type);
553
+ };
554
+
555
+ XmppRoom.prototype.groupchat = function(message, html_message) {
556
+ return this.client.groupchat(this.name, message, html_message);
557
+ };
558
+
559
+ XmppRoom.prototype.invite = function(receiver, reason) {
560
+ return this.client.invite(this.name, receiver, reason);
561
+ };
562
+
563
+ XmppRoom.prototype.directInvite = function(receiver, reason) {
564
+ return this.client.directInvite(this.name, receiver, reason, this.password);
565
+ };
566
+
567
+ XmppRoom.prototype.configure = function(handler_cb) {
568
+ return this.client.configure(this.name, handler_cb);
569
+ };
570
+
571
+ XmppRoom.prototype.cancelConfigure = function() {
572
+ return this.client.cancelConfigure(this.name);
573
+ };
574
+
575
+ XmppRoom.prototype.saveConfiguration = function(configarray) {
576
+ return this.client.saveConfiguration(this.name, configarray);
577
+ };
578
+
579
+ XmppRoom.prototype.queryOccupants = function(success_cb, error_cb) {
580
+ return this.client.queryOccupants(this.name, success_cb, error_cb);
581
+ };
582
+
583
+ XmppRoom.prototype.setTopic = function(topic) {
584
+ return this.client.setTopic(this.name, topic);
585
+ };
586
+
587
+ XmppRoom.prototype.modifyRole = function(nick, role, reason, success_cb, error_cb) {
588
+ return this.client.modifyRole(this.name, nick, role, reason, success_cb, error_cb);
589
+ };
590
+
591
+ XmppRoom.prototype.kick = function(nick, reason, handler_cb, error_cb) {
592
+ return this.client.kick(this.name, nick, reason, handler_cb, error_cb);
593
+ };
594
+
595
+ XmppRoom.prototype.voice = function(nick, reason, handler_cb, error_cb) {
596
+ return this.client.voice(this.name, nick, reason, handler_cb, error_cb);
597
+ };
598
+
599
+ XmppRoom.prototype.mute = function(nick, reason, handler_cb, error_cb) {
600
+ return this.client.mute(this.name, nick, reason, handler_cb, error_cb);
601
+ };
602
+
603
+ XmppRoom.prototype.op = function(nick, reason, handler_cb, error_cb) {
604
+ return this.client.op(this.name, nick, reason, handler_cb, error_cb);
605
+ };
606
+
607
+ XmppRoom.prototype.deop = function(nick, reason, handler_cb, error_cb) {
608
+ return this.client.deop(this.name, nick, reason, handler_cb, error_cb);
609
+ };
610
+
611
+ XmppRoom.prototype.modifyAffiliation = function(jid, affiliation, reason, success_cb, error_cb) {
612
+ return this.client.modifyAffiliation(this.name, jid, affiliation, reason, success_cb, error_cb);
613
+ };
614
+
615
+ XmppRoom.prototype.ban = function(jid, reason, handler_cb, error_cb) {
616
+ return this.client.ban(this.name, jid, reason, handler_cb, error_cb);
617
+ };
618
+
619
+ XmppRoom.prototype.member = function(jid, reason, handler_cb, error_cb) {
620
+ return this.client.member(this.name, jid, reason, handler_cb, error_cb);
621
+ };
622
+
623
+ XmppRoom.prototype.revoke = function(jid, reason, handler_cb, error_cb) {
624
+ return this.client.revoke(this.name, jid, reason, handler_cb, error_cb);
625
+ };
626
+
627
+ XmppRoom.prototype.owner = function(jid, reason, handler_cb, error_cb) {
628
+ return this.client.owner(this.name, jid, reason, handler_cb, error_cb);
629
+ };
630
+
631
+ XmppRoom.prototype.admin = function(jid, reason, handler_cb, error_cb) {
632
+ return this.client.admin(this.name, jid, reason, handler_cb, error_cb);
633
+ };
634
+
635
+ XmppRoom.prototype.changeNick = function(nick) {
636
+ this.nick = nick;
637
+ return this.client.changeNick(this.name, nick);
638
+ };
639
+
640
+ XmppRoom.prototype.setStatus = function(show, status) {
641
+ return this.client.setStatus(this.name, this.nick, show, status);
642
+ };
643
+
644
+ /*Function
645
+ Adds a handler to the MUC room.
646
+ Parameters:
647
+ (String) handler_type - 'message', 'presence' or 'roster'.
648
+ (Function) handler - The handler function.
649
+ Returns:
650
+ id - the id of handler.
651
+ */
652
+
653
+ XmppRoom.prototype.addHandler = function(handler_type, handler) {
654
+ var id;
655
+ id = this._handler_ids++;
656
+ switch (handler_type) {
657
+ case 'presence':
658
+ this._presence_handlers[id] = handler;
659
+ break;
660
+ case 'message':
661
+ this._message_handlers[id] = handler;
662
+ break;
663
+ case 'roster':
664
+ this._roster_handlers[id] = handler;
665
+ break;
666
+ default:
667
+ this._handler_ids--;
668
+ return null;
669
+ }
670
+ return id;
671
+ };
672
+
673
+ /*Function
674
+ Removes a handler from the MUC room.
675
+ This function takes ONLY ids returned by the addHandler function
676
+ of this room. passing handler ids returned by connection.addHandler
677
+ may brake things!
678
+ Parameters:
679
+ (number) id - the id of the handler
680
+ */
681
+
682
+ XmppRoom.prototype.removeHandler = function(id) {
683
+ delete this._presence_handlers[id];
684
+ delete this._message_handlers[id];
685
+ return delete this._roster_handlers[id];
686
+ };
687
+
688
+ /*Function
689
+ Creates and adds an Occupant to the Room Roster.
690
+ Parameters:
691
+ (Object) data - the data the Occupant is filled with
692
+ Returns:
693
+ occ - the created Occupant.
694
+ */
695
+
696
+ XmppRoom.prototype._addOccupant = function(data) {
697
+ var occ;
698
+ occ = new Occupant(data, this);
699
+ this.roster[occ.nick] = occ;
700
+ return occ;
701
+ };
702
+
703
+ /*Function
704
+ The standard handler that managed the Room Roster.
705
+ Parameters:
706
+ (Object) pres - the presence stanza containing user information
707
+ */
708
+
709
+ XmppRoom.prototype._roomRosterHandler = function(pres) {
710
+ var data, handler, id, newnick, nick, _ref;
711
+ data = XmppRoom._parsePresence(pres);
712
+ nick = data.nick;
713
+ newnick = data.newnick || null;
714
+ switch (data.type) {
715
+ case 'error':
716
+ return;
717
+ case 'unavailable':
718
+ if (newnick) {
719
+ data.nick = newnick;
720
+ if (this.roster[nick] && this.roster[newnick]) {
721
+ this.roster[nick].update(this.roster[newnick]);
722
+ this.roster[newnick] = this.roster[nick];
723
+ }
724
+ if (this.roster[nick] && !this.roster[newnick]) {
725
+ this.roster[newnick] = this.roster[nick].update(data);
726
+ }
727
+ }
728
+ delete this.roster[nick];
729
+ break;
730
+ default:
731
+ if (this.roster[nick]) {
732
+ this.roster[nick].update(data);
733
+ } else {
734
+ this._addOccupant(data);
735
+ }
736
+ }
737
+ _ref = this._roster_handlers;
738
+ for (id in _ref) {
739
+ handler = _ref[id];
740
+ if (!handler(this.roster, this)) delete this._roster_handlers[id];
741
+ }
742
+ return true;
743
+ };
744
+
745
+ /*Function
746
+ Parses a presence stanza
747
+ Parameters:
748
+ (Object) data - the data extracted from the presence stanza
749
+ */
750
+
751
+ XmppRoom._parsePresence = function(pres) {
752
+ var a, c, c2, data, _i, _j, _len, _len2, _ref, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8;
753
+ data = {};
754
+ a = pres.attributes;
755
+ data.nick = Strophe.getResourceFromJid(a.from.textContent);
756
+ data.type = ((_ref = a.type) != null ? _ref.textContent : void 0) || null;
757
+ data.states = [];
758
+ _ref2 = pres.children;
759
+ for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
760
+ c = _ref2[_i];
761
+ switch (c.nodeName) {
762
+ case "status":
763
+ data.status = c.textContent || null;
764
+ break;
765
+ case "show":
766
+ data.show = c.textContent || null;
767
+ break;
768
+ case "x":
769
+ a = c.attributes;
770
+ if (((_ref3 = a.xmlns) != null ? _ref3.textContent : void 0) === Strophe.NS.MUC_USER) {
771
+ _ref4 = c.children;
772
+ for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) {
773
+ c2 = _ref4[_j];
774
+ switch (c2.nodeName) {
775
+ case "item":
776
+ a = c2.attributes;
777
+ data.affiliation = ((_ref5 = a.affiliation) != null ? _ref5.textContent : void 0) || null;
778
+ data.role = ((_ref6 = a.role) != null ? _ref6.textContent : void 0) || null;
779
+ data.jid = ((_ref7 = a.jid) != null ? _ref7.textContent : void 0) || null;
780
+ data.newnick = ((_ref8 = a.nick) != null ? _ref8.textContent : void 0) || null;
781
+ break;
782
+ case "status":
783
+ if (c2.attributes.code) {
784
+ data.states.push(c2.attributes.code.textContent);
785
+ }
786
+ }
787
+ }
788
+ }
789
+ }
790
+ }
791
+ return data;
792
+ };
793
+
794
+ return XmppRoom;
795
+
796
+ })();
797
+
798
+ RoomConfig = (function() {
799
+
800
+ function RoomConfig(info) {
801
+ this.parse = __bind(this.parse, this); if (info != null) this.parse(info);
802
+ }
803
+
804
+ RoomConfig.prototype.parse = function(result) {
805
+ var attr, attrs, child, field, identity, query, _i, _j, _k, _len, _len2, _len3, _ref;
806
+ query = result.getElementsByTagName("query")[0].children;
807
+ this.identities = [];
808
+ this.features = [];
809
+ this.x = [];
810
+ for (_i = 0, _len = query.length; _i < _len; _i++) {
811
+ child = query[_i];
812
+ attrs = child.attributes;
813
+ switch (child.nodeName) {
814
+ case "identity":
815
+ identity = {};
816
+ for (_j = 0, _len2 = attrs.length; _j < _len2; _j++) {
817
+ attr = attrs[_j];
818
+ identity[attr.name] = attr.textContent;
819
+ }
820
+ this.identities.push(identity);
821
+ break;
822
+ case "feature":
823
+ this.features.push(attrs["var"].textContent);
824
+ break;
825
+ case "x":
826
+ attrs = child.children[0].attributes;
827
+ if ((!attrs["var"].textContent === 'FORM_TYPE') || (!attrs.type.textContent === 'hidden')) {
828
+ break;
829
+ }
830
+ _ref = child.children;
831
+ for (_k = 0, _len3 = _ref.length; _k < _len3; _k++) {
832
+ field = _ref[_k];
833
+ if (!(!field.attributes.type)) continue;
834
+ attrs = field.attributes;
835
+ this.x.push({
836
+ "var": attrs["var"].textContent,
837
+ label: attrs.label.textContent || "",
838
+ value: field.firstChild.textContent || ""
839
+ });
840
+ }
841
+ }
842
+ }
843
+ return {
844
+ "identities": this.identities,
845
+ "features": this.features,
846
+ "x": this.x
847
+ };
848
+ };
849
+
850
+ return RoomConfig;
851
+
852
+ })();
853
+
854
+ Occupant = (function() {
855
+
856
+ function Occupant(data, room) {
857
+ this.room = room;
858
+ this.update = __bind(this.update, this);
859
+ this.admin = __bind(this.admin, this);
860
+ this.owner = __bind(this.owner, this);
861
+ this.revoke = __bind(this.revoke, this);
862
+ this.member = __bind(this.member, this);
863
+ this.ban = __bind(this.ban, this);
864
+ this.modifyAffiliation = __bind(this.modifyAffiliation, this);
865
+ this.deop = __bind(this.deop, this);
866
+ this.op = __bind(this.op, this);
867
+ this.mute = __bind(this.mute, this);
868
+ this.voice = __bind(this.voice, this);
869
+ this.kick = __bind(this.kick, this);
870
+ this.modifyRole = __bind(this.modifyRole, this);
871
+ this.update(data);
872
+ }
873
+
874
+ Occupant.prototype.modifyRole = function(role, reason, success_cb, error_cb) {
875
+ return this.room.modifyRole(this.nick, role, reason, success_cb, error_cb);
876
+ };
877
+
878
+ Occupant.prototype.kick = function(reason, handler_cb, error_cb) {
879
+ return this.room.kick(this.nick, reason, handler_cb, error_cb);
880
+ };
881
+
882
+ Occupant.prototype.voice = function(reason, handler_cb, error_cb) {
883
+ return this.room.voice(this.nick, reason, handler_cb, error_cb);
884
+ };
885
+
886
+ Occupant.prototype.mute = function(reason, handler_cb, error_cb) {
887
+ return this.room.mute(this.nick, reason, handler_cb, error_cb);
888
+ };
889
+
890
+ Occupant.prototype.op = function(reason, handler_cb, error_cb) {
891
+ return this.room.op(this.nick, reason, handler_cb, error_cb);
892
+ };
893
+
894
+ Occupant.prototype.deop = function(reason, handler_cb, error_cb) {
895
+ return this.room.deop(this.nick, reason, handler_cb, error_cb);
896
+ };
897
+
898
+ Occupant.prototype.modifyAffiliation = function(affiliation, reason, success_cb, error_cb) {
899
+ return this.room.modifyAffiliation(this.jid, affiliation, reason, success_cb, error_cb);
900
+ };
901
+
902
+ Occupant.prototype.ban = function(reason, handler_cb, error_cb) {
903
+ return this.room.ban(this.jid, reason, handler_cb, error_cb);
904
+ };
905
+
906
+ Occupant.prototype.member = function(reason, handler_cb, error_cb) {
907
+ return this.room.member(this.jid, reason, handler_cb, error_cb);
908
+ };
909
+
910
+ Occupant.prototype.revoke = function(reason, handler_cb, error_cb) {
911
+ return this.room.revoke(this.jid, reason, handler_cb, error_cb);
912
+ };
913
+
914
+ Occupant.prototype.owner = function(reason, handler_cb, error_cb) {
915
+ return this.room.owner(this.jid, reason, handler_cb, error_cb);
916
+ };
917
+
918
+ Occupant.prototype.admin = function(reason, handler_cb, error_cb) {
919
+ return this.room.admin(this.jid, reason, handler_cb, error_cb);
920
+ };
921
+
922
+ Occupant.prototype.update = function(data) {
923
+ this.nick = data.nick || null;
924
+ this.affiliation = data.affiliation || null;
925
+ this.role = data.role || null;
926
+ this.jid = data.jid || null;
927
+ this.status = data.status || null;
928
+ this.show = data.show || null;
929
+ return this;
930
+ };
931
+
932
+ return Occupant;
933
+
934
+ })();