strophe.muc.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005
  1. // Generated by CoffeeScript 1.3.3
  2. /*
  3. *Plugin to implement the MUC extension.
  4. http://xmpp.org/extensions/xep-0045.html
  5. *Previous Author:
  6. Nathan Zorn <nathan.zorn@gmail.com>
  7. *Complete CoffeeScript rewrite:
  8. Andreas Guth <guth@dbis.rwth-aachen.de>
  9. */
  10. var Occupant, RoomConfig, XmppRoom,
  11. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  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, _ref, _ref1,
  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) {
  50. msg.cnode(Strophe.xmlElement("password", [], password));
  51. }
  52. if ((_ref = this._muc_handler) == null) {
  53. this._muc_handler = this._connection.addHandler(function(stanza) {
  54. var from, handler, handlers, id, roomname, x, xmlns, xquery, _i, _len;
  55. from = stanza.getAttribute('from');
  56. if (!from) {
  57. return true;
  58. }
  59. roomname = from.split("/")[0];
  60. if (!_this.rooms[roomname]) {
  61. return true;
  62. }
  63. room = _this.rooms[roomname];
  64. handlers = {};
  65. if (stanza.nodeName === "message") {
  66. handlers = room._message_handlers;
  67. } else if (stanza.nodeName === "presence") {
  68. xquery = stanza.getElementsByTagName("x");
  69. if (xquery.length > 0) {
  70. for (_i = 0, _len = xquery.length; _i < _len; _i++) {
  71. x = xquery[_i];
  72. xmlns = x.getAttribute("xmlns");
  73. if (xmlns && xmlns.match(Strophe.NS.MUC)) {
  74. handlers = room._presence_handlers;
  75. break;
  76. }
  77. }
  78. }
  79. }
  80. for (id in handlers) {
  81. handler = handlers[id];
  82. if (!handler(stanza, room)) {
  83. delete handlers[id];
  84. }
  85. }
  86. return true;
  87. });
  88. }
  89. if ((_ref1 = (_base = this.rooms)[room]) == null) {
  90. _base[room] = new XmppRoom(this, room, nick, password);
  91. }
  92. if (pres_handler_cb) {
  93. this.rooms[room].addHandler('presence', pres_handler_cb);
  94. }
  95. if (msg_handler_cb) {
  96. this.rooms[room].addHandler('message', msg_handler_cb);
  97. }
  98. if (roster_cb) {
  99. this.rooms[room].addHandler('roster', roster_cb);
  100. }
  101. return this._connection.send(msg);
  102. },
  103. /*Function
  104. Leave a multi-user chat room
  105. Parameters:
  106. (String) room - The multi-user chat room to leave.
  107. (String) nick - The nick name used in the room.
  108. (Function) handler_cb - Optional function to handle the successful leave.
  109. (String) exit_msg - optional exit message.
  110. Returns:
  111. iqid - The unique id for the room leave.
  112. */
  113. leave: function(room, nick, handler_cb, exit_msg) {
  114. var presence, presenceid, room_nick;
  115. delete this.rooms[room];
  116. if (this.rooms.length === 0) {
  117. this._connection.deleteHandler(this._muc_handler);
  118. this._muc_handler = null;
  119. }
  120. room_nick = this.test_append_nick(room, nick);
  121. presenceid = this._connection.getUniqueId();
  122. presence = $pres({
  123. type: "unavailable",
  124. id: presenceid,
  125. from: this._connection.jid,
  126. to: room_nick
  127. });
  128. if (exit_msg != null) {
  129. presence.c("status", exit_msg);
  130. }
  131. if (handler_cb != null) {
  132. this._connection.addHandler(handler_cb, null, "presence", null, presenceid);
  133. }
  134. this._connection.send(presence);
  135. return presenceid;
  136. },
  137. /*Function
  138. Parameters:
  139. (String) room - The multi-user chat room name.
  140. (String) nick - The nick name used in the chat room.
  141. (String) message - The plaintext message to send to the room.
  142. (String) html_message - The message to send to the room with html markup.
  143. (String) type - "groupchat" for group chat messages o
  144. "chat" for private chat messages
  145. Returns:
  146. msgiq - the unique id used to send the message
  147. */
  148. message: function(room, nick, message, html_message, type) {
  149. var msg, msgid, parent, room_nick;
  150. room_nick = this.test_append_nick(room, nick);
  151. type = type || (nick != null ? "chat" : "groupchat");
  152. msgid = this._connection.getUniqueId();
  153. msg = $msg({
  154. to: room_nick,
  155. from: this._connection.jid,
  156. type: type,
  157. id: msgid
  158. }).c("body", {
  159. xmlns: Strophe.NS.CLIENT
  160. }).t(message);
  161. msg.up();
  162. if (html_message != null) {
  163. msg.c("html", {
  164. xmlns: Strophe.NS.XHTML_IM
  165. }).c("body", {
  166. xmlns: Strophe.NS.XHTML
  167. }).h(html_message);
  168. if (msg.node.childNodes.length === 0) {
  169. parent = msg.node.parentNode;
  170. msg.up().up();
  171. msg.node.removeChild(parent);
  172. } else {
  173. msg.up().up();
  174. }
  175. }
  176. msg.c("x", {
  177. xmlns: "jabber:x:event"
  178. }).c("composing");
  179. this._connection.send(msg);
  180. return msgid;
  181. },
  182. /*Function
  183. Convenience Function to send a Message to all Occupants
  184. Parameters:
  185. (String) room - The multi-user chat room name.
  186. (String) message - The plaintext message to send to the room.
  187. (String) html_message - The message to send to the room with html markup.
  188. Returns:
  189. msgiq - the unique id used to send the message
  190. */
  191. groupchat: function(room, message, html_message) {
  192. return this.message(room, null, message, html_message);
  193. },
  194. /*Function
  195. Send a mediated invitation.
  196. Parameters:
  197. (String) room - The multi-user chat room name.
  198. (String) receiver - The invitation's receiver.
  199. (String) reason - Optional reason for joining the room.
  200. Returns:
  201. msgiq - the unique id used to send the invitation
  202. */
  203. invite: function(room, receiver, reason) {
  204. var invitation, msgid;
  205. msgid = this._connection.getUniqueId();
  206. invitation = $msg({
  207. from: this._connection.jid,
  208. to: room,
  209. id: msgid
  210. }).c('x', {
  211. xmlns: Strophe.NS.MUC_USER
  212. }).c('invite', {
  213. to: receiver
  214. });
  215. if (reason != null) {
  216. invitation.c('reason', reason);
  217. }
  218. this._connection.send(invitation);
  219. return msgid;
  220. },
  221. /*Function
  222. Send a direct invitation.
  223. Parameters:
  224. (String) room - The multi-user chat room name.
  225. (String) receiver - The invitation's receiver.
  226. (String) reason - Optional reason for joining the room.
  227. (String) password - Optional password for the room.
  228. Returns:
  229. msgiq - the unique id used to send the invitation
  230. */
  231. directInvite: function(room, receiver, reason, password) {
  232. var attrs, invitation, msgid;
  233. msgid = this._connection.getUniqueId();
  234. attrs = {
  235. xmlns: 'jabber:x:conference',
  236. jid: room
  237. };
  238. if (reason != null) {
  239. attrs.reason = reason;
  240. }
  241. if (password != null) {
  242. attrs.password = password;
  243. }
  244. invitation = $msg({
  245. from: this._connection.jid,
  246. to: receiver,
  247. id: msgid
  248. }).c('x', attrs);
  249. this._connection.send(invitation);
  250. return msgid;
  251. },
  252. /*Function
  253. Queries a room for a list of occupants
  254. (String) room - The multi-user chat room name.
  255. (Function) success_cb - Optional function to handle the info.
  256. (Function) error_cb - Optional function to handle an error.
  257. Returns:
  258. id - the unique id used to send the info request
  259. */
  260. queryOccupants: function(room, success_cb, error_cb) {
  261. var attrs, info;
  262. attrs = {
  263. xmlns: Strophe.NS.DISCO_ITEMS
  264. };
  265. info = $iq({
  266. from: this._connection.jid,
  267. to: room,
  268. type: 'get'
  269. }).c('query', attrs);
  270. return this._connection.sendIQ(info, success_cb, error_cb);
  271. },
  272. /*Function
  273. Start a room configuration.
  274. Parameters:
  275. (String) room - The multi-user chat room name.
  276. (Function) handler_cb - Optional function to handle the config form.
  277. Returns:
  278. id - the unique id used to send the configuration request
  279. */
  280. configure: function(room, handler_cb, error_cb) {
  281. var config, stanza;
  282. config = $iq({
  283. to: room,
  284. type: "get"
  285. }).c("query", {
  286. xmlns: Strophe.NS.MUC_OWNER
  287. });
  288. stanza = config.tree();
  289. return this._connection.sendIQ(stanza, handler_cb, error_cb);
  290. },
  291. /*Function
  292. Cancel the room configuration
  293. Parameters:
  294. (String) room - The multi-user chat room name.
  295. Returns:
  296. id - the unique id used to cancel the configuration.
  297. */
  298. cancelConfigure: function(room) {
  299. var config, stanza;
  300. config = $iq({
  301. to: room,
  302. type: "set"
  303. }).c("query", {
  304. xmlns: Strophe.NS.MUC_OWNER
  305. }).c("x", {
  306. xmlns: "jabber:x:data",
  307. type: "cancel"
  308. });
  309. stanza = config.tree();
  310. return this._connection.sendIQ(stanza);
  311. },
  312. /*Function
  313. Save a room configuration.
  314. Parameters:
  315. (String) room - The multi-user chat room name.
  316. (Array) config- Form Object or an array of form elements used to configure the room.
  317. Returns:
  318. id - the unique id used to save the configuration.
  319. */
  320. saveConfiguration: function(room, config, success_cb, error_cb) {
  321. var conf, iq, stanza, _i, _len;
  322. iq = $iq({
  323. to: room,
  324. type: "set"
  325. }).c("query", {
  326. xmlns: Strophe.NS.MUC_OWNER
  327. });
  328. if (config instanceof Form) {
  329. config.type = "submit";
  330. iq.cnode(config.toXML());
  331. } else {
  332. iq.c("x", {
  333. xmlns: "jabber:x:data",
  334. type: "submit"
  335. });
  336. for (_i = 0, _len = config.length; _i < _len; _i++) {
  337. conf = config[_i];
  338. iq.cnode(conf).up();
  339. }
  340. }
  341. stanza = iq.tree();
  342. return this._connection.sendIQ(stanza, success_cb, error_cb);
  343. },
  344. /*Function
  345. Parameters:
  346. (String) room - The multi-user chat room name.
  347. Returns:
  348. id - the unique id used to create the chat room.
  349. */
  350. createInstantRoom: function(room, success_cb, error_cb) {
  351. var roomiq;
  352. roomiq = $iq({
  353. to: room,
  354. type: "set"
  355. }).c("query", {
  356. xmlns: Strophe.NS.MUC_OWNER
  357. }).c("x", {
  358. xmlns: "jabber:x:data",
  359. type: "submit"
  360. });
  361. return this._connection.sendIQ(roomiq.tree(), success_cb, error_cb);
  362. },
  363. /*Function
  364. Set the topic of the chat room.
  365. Parameters:
  366. (String) room - The multi-user chat room name.
  367. (String) topic - Topic message.
  368. */
  369. setTopic: function(room, topic) {
  370. var msg;
  371. msg = $msg({
  372. to: room,
  373. from: this._connection.jid,
  374. type: "groupchat"
  375. }).c("subject", {
  376. xmlns: "jabber:client"
  377. }).t(topic);
  378. return this._connection.send(msg.tree());
  379. },
  380. /*Function
  381. Internal Function that Changes the role or affiliation of a member
  382. of a MUC room. This function is used by modifyRole and modifyAffiliation.
  383. The modification can only be done by a room moderator. An error will be
  384. returned if the user doesn't have permission.
  385. Parameters:
  386. (String) room - The multi-user chat room name.
  387. (Object) item - Object with nick and role or jid and affiliation attribute
  388. (String) reason - Optional reason for the change.
  389. (Function) handler_cb - Optional callback for success
  390. (Function) error_cb - Optional callback for error
  391. Returns:
  392. iq - the id of the mode change request.
  393. */
  394. _modifyPrivilege: function(room, item, reason, handler_cb, error_cb) {
  395. var iq;
  396. iq = $iq({
  397. to: room,
  398. type: "set"
  399. }).c("query", {
  400. xmlns: Strophe.NS.MUC_ADMIN
  401. }).cnode(item.node);
  402. if (reason != null) {
  403. iq.c("reason", reason);
  404. }
  405. return this._connection.sendIQ(iq.tree(), handler_cb, error_cb);
  406. },
  407. /*Function
  408. Changes the role of a member of a MUC room.
  409. The modification can only be done by a room moderator. An error will be
  410. returned if the user doesn't have permission.
  411. Parameters:
  412. (String) room - The multi-user chat room name.
  413. (String) nick - The nick name of the user to modify.
  414. (String) role - The new role of the user.
  415. (String) affiliation - The new affiliation of the user.
  416. (String) reason - Optional reason for the change.
  417. (Function) handler_cb - Optional callback for success
  418. (Function) error_cb - Optional callback for error
  419. Returns:
  420. iq - the id of the mode change request.
  421. */
  422. modifyRole: function(room, nick, role, reason, handler_cb, error_cb) {
  423. var item;
  424. item = $build("item", {
  425. nick: nick,
  426. role: role
  427. });
  428. return this._modifyPrivilege(room, item, reason, handler_cb, error_cb);
  429. },
  430. kick: function(room, nick, reason, handler_cb, error_cb) {
  431. return this.modifyRole(room, nick, 'none', reason, handler_cb, error_cb);
  432. },
  433. voice: function(room, nick, reason, handler_cb, error_cb) {
  434. return this.modifyRole(room, nick, 'participant', reason, handler_cb, error_cb);
  435. },
  436. mute: function(room, nick, reason, handler_cb, error_cb) {
  437. return this.modifyRole(room, nick, 'visitor', reason, handler_cb, error_cb);
  438. },
  439. op: function(room, nick, reason, handler_cb, error_cb) {
  440. return this.modifyRole(room, nick, 'moderator', reason, handler_cb, error_cb);
  441. },
  442. deop: function(room, nick, reason, handler_cb, error_cb) {
  443. return this.modifyRole(room, nick, 'participant', reason, handler_cb, error_cb);
  444. },
  445. /*Function
  446. Changes the affiliation of a member of a MUC room.
  447. The modification can only be done by a room moderator. An error will be
  448. returned if the user doesn't have permission.
  449. Parameters:
  450. (String) room - The multi-user chat room name.
  451. (String) jid - The jid of the user to modify.
  452. (String) affiliation - The new affiliation of the user.
  453. (String) reason - Optional reason for the change.
  454. (Function) handler_cb - Optional callback for success
  455. (Function) error_cb - Optional callback for error
  456. Returns:
  457. iq - the id of the mode change request.
  458. */
  459. modifyAffiliation: function(room, jid, affiliation, reason, handler_cb, error_cb) {
  460. var item;
  461. item = $build("item", {
  462. jid: jid,
  463. affiliation: affiliation
  464. });
  465. return this._modifyPrivilege(room, item, reason, handler_cb, error_cb);
  466. },
  467. ban: function(room, jid, reason, handler_cb, error_cb) {
  468. return this.modifyAffiliation(room, jid, 'outcast', reason, handler_cb, error_cb);
  469. },
  470. member: function(room, jid, reason, handler_cb, error_cb) {
  471. return this.modifyAffiliation(room, jid, 'member', reason, handler_cb, error_cb);
  472. },
  473. revoke: function(room, jid, reason, handler_cb, error_cb) {
  474. return this.modifyAffiliation(room, jid, 'none', reason, handler_cb, error_cb);
  475. },
  476. owner: function(room, jid, reason, handler_cb, error_cb) {
  477. return this.modifyAffiliation(room, jid, 'owner', reason, handler_cb, error_cb);
  478. },
  479. admin: function(room, jid, reason, handler_cb, error_cb) {
  480. return this.modifyAffiliation(room, jid, 'admin', reason, handler_cb, error_cb);
  481. },
  482. /*Function
  483. Change the current users nick name.
  484. Parameters:
  485. (String) room - The multi-user chat room name.
  486. (String) user - The new nick name.
  487. */
  488. changeNick: function(room, user) {
  489. var presence, room_nick;
  490. room_nick = this.test_append_nick(room, user);
  491. presence = $pres({
  492. from: this._connection.jid,
  493. to: room_nick,
  494. id: this._connection.getUniqueId()
  495. });
  496. return this._connection.send(presence.tree());
  497. },
  498. /*Function
  499. Change the current users status.
  500. Parameters:
  501. (String) room - The multi-user chat room name.
  502. (String) user - The current nick.
  503. (String) show - The new show-text.
  504. (String) status - The new status-text.
  505. */
  506. setStatus: function(room, user, show, status) {
  507. var presence, room_nick;
  508. room_nick = this.test_append_nick(room, user);
  509. presence = $pres({
  510. from: this._connection.jid,
  511. to: room_nick
  512. });
  513. if (show != null) {
  514. presence.c('show', show).up();
  515. }
  516. if (status != null) {
  517. presence.c('status', status);
  518. }
  519. return this._connection.send(presence.tree());
  520. },
  521. /*Function
  522. List all chat room available on a server.
  523. Parameters:
  524. (String) server - name of chat server.
  525. (String) handle_cb - Function to call for room list return.
  526. (String) error_cb - Function to call on error.
  527. */
  528. listRooms: function(server, handle_cb, error_cb) {
  529. var iq;
  530. iq = $iq({
  531. to: server,
  532. from: this._connection.jid,
  533. type: "get"
  534. }).c("query", {
  535. xmlns: Strophe.NS.DISCO_ITEMS
  536. });
  537. return this._connection.sendIQ(iq, handle_cb, error_cb);
  538. },
  539. test_append_nick: function(room, nick) {
  540. return room + (nick != null ? "/" + (Strophe.escapeNode(nick)) : "");
  541. }
  542. });
  543. XmppRoom = (function() {
  544. function XmppRoom(client, name, nick, password) {
  545. this.roster = {};
  546. this._message_handlers = {};
  547. this._presence_handlers = {};
  548. this._roster_handlers = {};
  549. this._handler_ids = 0;
  550. this.client = client;
  551. this.name = name;
  552. this.nick = nick;
  553. this.password = password;
  554. this._roomRosterHandler = __bind(this._roomRosterHandler, this);
  555. this._addOccupant = __bind(this._addOccupant, this);
  556. if (client.muc) {
  557. this.client = client.muc;
  558. }
  559. this.name = Strophe.getBareJidFromJid(name);
  560. this.client.rooms[this.name] = this;
  561. this.addHandler('presence', this._roomRosterHandler);
  562. }
  563. XmppRoom.prototype.join = function(msg_handler_cb, pres_handler_cb, roster_cb) {
  564. return this.client.join(this.name, this.nick, msg_handler_cb, pres_handler_cb, roster_cb, this.password);
  565. };
  566. XmppRoom.prototype.leave = function(handler_cb, message) {
  567. this.client.leave(this.name, this.nick, handler_cb, message);
  568. return delete this.client.rooms[this.name];
  569. };
  570. XmppRoom.prototype.message = function(nick, message, html_message, type) {
  571. return this.client.message(this.name, nick, message, html_message, type);
  572. };
  573. XmppRoom.prototype.groupchat = function(message, html_message) {
  574. return this.client.groupchat(this.name, message, html_message);
  575. };
  576. XmppRoom.prototype.invite = function(receiver, reason) {
  577. return this.client.invite(this.name, receiver, reason);
  578. };
  579. XmppRoom.prototype.directInvite = function(receiver, reason) {
  580. return this.client.directInvite(this.name, receiver, reason, this.password);
  581. };
  582. XmppRoom.prototype.configure = function(handler_cb) {
  583. return this.client.configure(this.name, handler_cb);
  584. };
  585. XmppRoom.prototype.cancelConfigure = function() {
  586. return this.client.cancelConfigure(this.name);
  587. };
  588. XmppRoom.prototype.saveConfiguration = function(config) {
  589. return this.client.saveConfiguration(this.name, config);
  590. };
  591. XmppRoom.prototype.queryOccupants = function(success_cb, error_cb) {
  592. return this.client.queryOccupants(this.name, success_cb, error_cb);
  593. };
  594. XmppRoom.prototype.setTopic = function(topic) {
  595. return this.client.setTopic(this.name, topic);
  596. };
  597. XmppRoom.prototype.modifyRole = function(nick, role, reason, success_cb, error_cb) {
  598. return this.client.modifyRole(this.name, nick, role, reason, success_cb, error_cb);
  599. };
  600. XmppRoom.prototype.kick = function(nick, reason, handler_cb, error_cb) {
  601. return this.client.kick(this.name, nick, reason, handler_cb, error_cb);
  602. };
  603. XmppRoom.prototype.voice = function(nick, reason, handler_cb, error_cb) {
  604. return this.client.voice(this.name, nick, reason, handler_cb, error_cb);
  605. };
  606. XmppRoom.prototype.mute = function(nick, reason, handler_cb, error_cb) {
  607. return this.client.mute(this.name, nick, reason, handler_cb, error_cb);
  608. };
  609. XmppRoom.prototype.op = function(nick, reason, handler_cb, error_cb) {
  610. return this.client.op(this.name, nick, reason, handler_cb, error_cb);
  611. };
  612. XmppRoom.prototype.deop = function(nick, reason, handler_cb, error_cb) {
  613. return this.client.deop(this.name, nick, reason, handler_cb, error_cb);
  614. };
  615. XmppRoom.prototype.modifyAffiliation = function(jid, affiliation, reason, success_cb, error_cb) {
  616. return this.client.modifyAffiliation(this.name, jid, affiliation, reason, success_cb, error_cb);
  617. };
  618. XmppRoom.prototype.ban = function(jid, reason, handler_cb, error_cb) {
  619. return this.client.ban(this.name, jid, reason, handler_cb, error_cb);
  620. };
  621. XmppRoom.prototype.member = function(jid, reason, handler_cb, error_cb) {
  622. return this.client.member(this.name, jid, reason, handler_cb, error_cb);
  623. };
  624. XmppRoom.prototype.revoke = function(jid, reason, handler_cb, error_cb) {
  625. return this.client.revoke(this.name, jid, reason, handler_cb, error_cb);
  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. XmppRoom.prototype.admin = function(jid, reason, handler_cb, error_cb) {
  631. return this.client.admin(this.name, jid, reason, handler_cb, error_cb);
  632. };
  633. XmppRoom.prototype.changeNick = function(nick) {
  634. this.nick = nick;
  635. return this.client.changeNick(this.name, nick);
  636. };
  637. XmppRoom.prototype.setStatus = function(show, status) {
  638. return this.client.setStatus(this.name, this.nick, show, status);
  639. };
  640. /*Function
  641. Adds a handler to the MUC room.
  642. Parameters:
  643. (String) handler_type - 'message', 'presence' or 'roster'.
  644. (Function) handler - The handler function.
  645. Returns:
  646. id - the id of handler.
  647. */
  648. XmppRoom.prototype.addHandler = function(handler_type, handler) {
  649. var id;
  650. id = this._handler_ids++;
  651. switch (handler_type) {
  652. case 'presence':
  653. this._presence_handlers[id] = handler;
  654. break;
  655. case 'message':
  656. this._message_handlers[id] = handler;
  657. break;
  658. case 'roster':
  659. this._roster_handlers[id] = handler;
  660. break;
  661. default:
  662. this._handler_ids--;
  663. return null;
  664. }
  665. return id;
  666. };
  667. /*Function
  668. Removes a handler from the MUC room.
  669. This function takes ONLY ids returned by the addHandler function
  670. of this room. passing handler ids returned by connection.addHandler
  671. may brake things!
  672. Parameters:
  673. (number) id - the id of the handler
  674. */
  675. XmppRoom.prototype.removeHandler = function(id) {
  676. delete this._presence_handlers[id];
  677. delete this._message_handlers[id];
  678. return delete this._roster_handlers[id];
  679. };
  680. /*Function
  681. Creates and adds an Occupant to the Room Roster.
  682. Parameters:
  683. (Object) data - the data the Occupant is filled with
  684. Returns:
  685. occ - the created Occupant.
  686. */
  687. XmppRoom.prototype._addOccupant = function(data) {
  688. var occ;
  689. occ = new Occupant(data, this);
  690. this.roster[occ.nick] = occ;
  691. return occ;
  692. };
  693. /*Function
  694. The standard handler that managed the Room Roster.
  695. Parameters:
  696. (Object) pres - the presence stanza containing user information
  697. */
  698. XmppRoom.prototype._roomRosterHandler = function(pres) {
  699. var data, handler, id, newnick, nick, _ref;
  700. data = XmppRoom._parsePresence(pres);
  701. nick = data.nick;
  702. newnick = data.newnick || null;
  703. switch (data.type) {
  704. case 'error':
  705. return;
  706. case 'unavailable':
  707. if (newnick) {
  708. data.nick = newnick;
  709. if (this.roster[nick] && this.roster[newnick]) {
  710. this.roster[nick].update(this.roster[newnick]);
  711. this.roster[newnick] = this.roster[nick];
  712. }
  713. if (this.roster[nick] && !this.roster[newnick]) {
  714. this.roster[newnick] = this.roster[nick].update(data);
  715. }
  716. }
  717. delete this.roster[nick];
  718. break;
  719. default:
  720. if (this.roster[nick]) {
  721. this.roster[nick].update(data);
  722. } else {
  723. this._addOccupant(data);
  724. }
  725. }
  726. _ref = this._roster_handlers;
  727. for (id in _ref) {
  728. handler = _ref[id];
  729. if (!handler(this.roster, this)) {
  730. delete this._roster_handlers[id];
  731. }
  732. }
  733. return true;
  734. };
  735. /*Function
  736. Parses a presence stanza
  737. Parameters:
  738. (Object) data - the data extracted from the presence stanza
  739. */
  740. XmppRoom._parsePresence = function(pres) {
  741. var a, c, c2, data, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;
  742. data = {};
  743. a = pres.attributes;
  744. data.nick = Strophe.getResourceFromJid(a.from.textContent);
  745. data.type = ((_ref = a.type) != null ? _ref.textContent : void 0) || null;
  746. data.states = [];
  747. _ref1 = pres.childNodes;
  748. for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
  749. c = _ref1[_i];
  750. switch (c.nodeName) {
  751. case "status":
  752. data.status = c.textContent || null;
  753. break;
  754. case "show":
  755. data.show = c.textContent || null;
  756. break;
  757. case "x":
  758. a = c.attributes;
  759. if (((_ref2 = a.xmlns) != null ? _ref2.textContent : void 0) === Strophe.NS.MUC_USER) {
  760. _ref3 = c.childNodes;
  761. for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
  762. c2 = _ref3[_j];
  763. switch (c2.nodeName) {
  764. case "item":
  765. a = c2.attributes;
  766. data.affiliation = ((_ref4 = a.affiliation) != null ? _ref4.textContent : void 0) || null;
  767. data.role = ((_ref5 = a.role) != null ? _ref5.textContent : void 0) || null;
  768. data.jid = ((_ref6 = a.jid) != null ? _ref6.textContent : void 0) || null;
  769. data.newnick = ((_ref7 = a.nick) != null ? _ref7.textContent : void 0) || null;
  770. break;
  771. case "status":
  772. if (c2.attributes.code) {
  773. data.states.push(c2.attributes.code.textContent);
  774. }
  775. }
  776. }
  777. }
  778. }
  779. }
  780. return data;
  781. };
  782. return XmppRoom;
  783. })();
  784. RoomConfig = (function() {
  785. function RoomConfig(info) {
  786. this.parse = __bind(this.parse, this);
  787. if (info != null) {
  788. this.parse(info);
  789. }
  790. }
  791. RoomConfig.prototype.parse = function(result) {
  792. var attr, attrs, child, field, identity, query, _i, _j, _k, _len, _len1, _len2, _ref;
  793. query = result.getElementsByTagName("query")[0].childNodes;
  794. this.identities = [];
  795. this.features = [];
  796. this.x = [];
  797. for (_i = 0, _len = query.length; _i < _len; _i++) {
  798. child = query[_i];
  799. attrs = child.attributes;
  800. switch (child.nodeName) {
  801. case "identity":
  802. identity = {};
  803. for (_j = 0, _len1 = attrs.length; _j < _len1; _j++) {
  804. attr = attrs[_j];
  805. identity[attr.name] = attr.textContent;
  806. }
  807. this.identities.push(identity);
  808. break;
  809. case "feature":
  810. this.features.push(attrs["var"].textContent);
  811. break;
  812. case "x":
  813. attrs = child.childNodes[0].attributes;
  814. if ((!attrs["var"].textContent === 'FORM_TYPE') || (!attrs.type.textContent === 'hidden')) {
  815. break;
  816. }
  817. _ref = child.childNodes;
  818. for (_k = 0, _len2 = _ref.length; _k < _len2; _k++) {
  819. field = _ref[_k];
  820. if (!(!field.attributes.type)) {
  821. continue;
  822. }
  823. attrs = field.attributes;
  824. this.x.push({
  825. "var": attrs["var"].textContent,
  826. label: attrs.label.textContent || "",
  827. value: field.firstChild.textContent || ""
  828. });
  829. }
  830. }
  831. }
  832. return {
  833. "identities": this.identities,
  834. "features": this.features,
  835. "x": this.x
  836. };
  837. };
  838. return RoomConfig;
  839. })();
  840. Occupant = (function() {
  841. function Occupant(data, room) {
  842. this.room = room;
  843. this.update = __bind(this.update, this);
  844. this.admin = __bind(this.admin, this);
  845. this.owner = __bind(this.owner, this);
  846. this.revoke = __bind(this.revoke, this);
  847. this.member = __bind(this.member, this);
  848. this.ban = __bind(this.ban, this);
  849. this.modifyAffiliation = __bind(this.modifyAffiliation, this);
  850. this.deop = __bind(this.deop, this);
  851. this.op = __bind(this.op, this);
  852. this.mute = __bind(this.mute, this);
  853. this.voice = __bind(this.voice, this);
  854. this.kick = __bind(this.kick, this);
  855. this.modifyRole = __bind(this.modifyRole, this);
  856. this.update(data);
  857. }
  858. Occupant.prototype.modifyRole = function(role, reason, success_cb, error_cb) {
  859. return this.room.modifyRole(this.nick, role, reason, success_cb, error_cb);
  860. };
  861. Occupant.prototype.kick = function(reason, handler_cb, error_cb) {
  862. return this.room.kick(this.nick, reason, handler_cb, error_cb);
  863. };
  864. Occupant.prototype.voice = function(reason, handler_cb, error_cb) {
  865. return this.room.voice(this.nick, reason, handler_cb, error_cb);
  866. };
  867. Occupant.prototype.mute = function(reason, handler_cb, error_cb) {
  868. return this.room.mute(this.nick, reason, handler_cb, error_cb);
  869. };
  870. Occupant.prototype.op = function(reason, handler_cb, error_cb) {
  871. return this.room.op(this.nick, reason, handler_cb, error_cb);
  872. };
  873. Occupant.prototype.deop = function(reason, handler_cb, error_cb) {
  874. return this.room.deop(this.nick, reason, handler_cb, error_cb);
  875. };
  876. Occupant.prototype.modifyAffiliation = function(affiliation, reason, success_cb, error_cb) {
  877. return this.room.modifyAffiliation(this.jid, affiliation, reason, success_cb, error_cb);
  878. };
  879. Occupant.prototype.ban = function(reason, handler_cb, error_cb) {
  880. return this.room.ban(this.jid, reason, handler_cb, error_cb);
  881. };
  882. Occupant.prototype.member = function(reason, handler_cb, error_cb) {
  883. return this.room.member(this.jid, reason, handler_cb, error_cb);
  884. };
  885. Occupant.prototype.revoke = function(reason, handler_cb, error_cb) {
  886. return this.room.revoke(this.jid, reason, handler_cb, error_cb);
  887. };
  888. Occupant.prototype.owner = function(reason, handler_cb, error_cb) {
  889. return this.room.owner(this.jid, reason, handler_cb, error_cb);
  890. };
  891. Occupant.prototype.admin = function(reason, handler_cb, error_cb) {
  892. return this.room.admin(this.jid, reason, handler_cb, error_cb);
  893. };
  894. Occupant.prototype.update = function(data) {
  895. this.nick = data.nick || null;
  896. this.affiliation = data.affiliation || null;
  897. this.role = data.role || null;
  898. this.jid = data.jid || null;
  899. this.status = data.status || null;
  900. this.show = data.show || null;
  901. return this;
  902. };
  903. return Occupant;
  904. })();