Skip to content

Commit

Permalink
Merge pull request #90 from wayfair/add_invite
Browse files Browse the repository at this point in the history
List users in a room and invite users
  • Loading branch information
markstory committed Sep 29, 2015
2 parents 5c193f5 + 509531f commit 7fbc3a8
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/xmpp.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class XmppBot extends Adapter
# Key is the room JID, value is the private JID
@roomToPrivateJID = {}

# http://stackoverflow.com/a/646643
String::startsWith ?= (s) -> @slice(0, s.length) == s

run: ->
options =
username: process.env.HUBOT_XMPP_USERNAME
Expand Down Expand Up @@ -150,6 +153,44 @@ class XmppBot extends Adapter
to: "#{room.jid}/#{@robot.name}",
type: 'unavailable')

# Send query for users in the room and once the server response is parsed,
# apply the callback against the retrieved data.
# callback should be of the form `(usersInRoom) -> console.log usersInRoom`
# where usersInRoom is an array of username strings.
# For normal use, no need to pass requestId: it's there for testing purposes.
getUsersInRoom: (room, callback, requestId) ->
# (pseudo) random string to keep track of the current request
# Useful in case of concurrent requests
unless requestId
requestId = 'get_users_in_room_' + Date.now() + Math.random().toString(36).slice(2)

# http://xmpp.org/extensions/xep-0045.html#disco-roomitems
@client.send do =>
@robot.logger.debug "Fetching users in the room #{room.jid}"
message = new ltx.Element('iq',
from : @options.username,
id: requestId,
to : room.jid,
type: 'get')
message.c('query',
xmlns : 'http://jabber.org/protocol/disco#items')
return message

# Listen to the event with the current request id, one time only
@once "completedRequest#{requestId}", callback

# XMPP invite to a room, directly - http://xmpp.org/extensions/xep-0249.html
sendInvite: (room, invitee, reason) ->
@client.send do =>
@robot.logger.debug "Inviting #{invitee} to #{room.jid}"
message = new ltx.Element('message',
to : invitee)
message.c('x',
xmlns : 'jabber:x:conference',
jid: room.jid,
reason: reason)
return message

read: (stanza) =>
if stanza.attrs.type is 'error'
@robot.logger.error '[xmpp error]' + stanza
Expand Down Expand Up @@ -177,6 +218,15 @@ class XmppBot extends Adapter

@robot.logger.debug "[sending pong] #{pong}"
@client.send pong
else if ((stanza.attrs.id.startsWith 'get_users_in_room') && stanza.children[0].children)
roomJID = stanza.attrs.from
userItems = stanza.children[0].children

# Note that this contains usernames and NOT the full user JID.
usersInRoom = (item.attrs.name for item in userItems)
@robot.logger.debug "[users in room] #{roomJID} has #{usersInRoom}"

@emit "completedRequest#{stanza.attrs.id}", usersInRoom

readMessage: (stanza) =>
# ignore non-messages
Expand Down
77 changes: 77 additions & 0 deletions test/adapter-test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,19 @@ describe 'XmppBot', ->
done()
bot.readIq stanza

it 'should parse room query iqs for users in the room', (done) ->
stanza.attrs.id = 'get_users_in_room_8139nj32ma'
stanza.attrs.from = '[email protected]'
userItems = [
{ attrs: {name: 'mark'} },
{ attrs: {name: 'anup'} }
]
stanza.children = [ {children: userItems} ]
bot.on "completedRequest#{stanza.attrs.id}", (usersInRoom) ->
assert.deepEqual usersInRoom, (item.attrs.name for item in userItems)
done()
bot.readIq stanza

describe '#readMessage()', ->
stanza = ''
bot = Bot.use()
Expand Down Expand Up @@ -337,6 +350,70 @@ describe 'XmppBot', ->
done()
bot.topic envelope, 'one', 'two'

describe '#getUsersInRoom()', ->
bot = Bot.use()

bot.client =
stub: 'xmpp client'

bot.robot =
name: 'bot'
logger:
debug: () ->

bot.options =
username: '[email protected]'

room =
jid: '[email protected]'
password: false

it 'should call @client.send()', (done) ->
bot.client.send = (message) ->
assert.equal message.attrs.from, bot.options.username
assert.equal (message.attrs.id.startsWith 'get_users_in_room'), true
assert.equal message.attrs.to, room.jid
assert.equal message.attrs.type, 'get'
assert.equal message.children[0].name, 'query'
assert.equal message.children[0].attrs.xmlns, 'http://jabber.org/protocol/disco#items'
done()
bot.getUsersInRoom room, () ->

it 'should call callback on receiving users', (done) ->
users = ['mark', 'anup']
requestId = 'get_users_in_room_8139nj32ma'
bot.client.send = () ->
callback = (usersInRoom) ->
assert.deepEqual usersInRoom, users
done()
bot.getUsersInRoom room, callback, requestId
bot.emit "completedRequest#{requestId}", users

describe '#sendInvite()', ->
bot = Bot.use()

bot.client =
stub: 'xmpp client'

bot.robot =
name: 'bot'
logger:
debug: () ->

room =
jid: '[email protected]'
password: false
invitee = '[email protected]'
reason = 'Inviting to test'

it 'should call @client.send()', (done) ->
bot.client.send = (message) ->
assert.equal message.attrs.to, invitee
assert.equal message.children[0].attrs.jid, room.jid
assert.equal message.children[0].attrs.reason, reason
done()
bot.sendInvite room, invitee, reason

describe '#error()', ->
bot = Bot.use()
bot.robot =
Expand Down

0 comments on commit 7fbc3a8

Please sign in to comment.