Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List users in a room and invite users #90

Merged
merged 5 commits into from
Sep 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sneaky 😄


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