Skip to content

Commit

Permalink
Merge pull request #546 from daniel-beard/dbeard_add_listener_for_fil…
Browse files Browse the repository at this point in the history
…e_share

Add listener for file share
  • Loading branch information
Shane DeWael authored Dec 21, 2018
2 parents 571803a + 4d93e35 commit dc7f2a8
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 4 deletions.
14 changes: 13 additions & 1 deletion src/bot.coffee
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{Adapter, TextMessage, EnterMessage, LeaveMessage, TopicMessage, CatchAllMessage} = require.main.require "hubot"
{SlackTextMessage, ReactionMessage, PresenceMessage} = require "./message"
{SlackTextMessage, ReactionMessage, PresenceMessage, FileSharedMessage} = require "./message"
SlackClient = require "./client"
pkg = require "../package"

Expand Down Expand Up @@ -287,6 +287,18 @@ class SlackBot extends Adapter

@robot.logger.debug "Received presence update message for users: #{u.id for u in users} with status: #{event.presence}"
@receive new PresenceMessage(users, event.presence)

else if event.type is "file_shared"

# Once again Hubot expects all user objects to have a room property that is used in the envelope for the message
# after it is received. If the reaction is to a message, then the `event.item.channel` contain a conversation ID.
# Otherwise reactions can be on files and file comments, which are "global" and aren't contained in a
# conversation. In that situation we fallback to an empty string.
user.room = event.channel_id

@robot.logger.debug "Received file_shared message from: #{user.id}, file_id: #{event.file_id}"
@receive new FileSharedMessage(user, event.file_id, event.event_ts)


# NOTE: we may want to wrap all other incoming events as a generic Message
# else
Expand Down
1 change: 1 addition & 0 deletions src/client.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class SlackClient
@rtm.on "presence_change", @eventWrapper, this
@rtm.on "member_joined_channel", @eventWrapper, this
@rtm.on "member_left_channel", @eventWrapper, this
@rtm.on "file_shared", @eventWrapper, this
@rtm.on "user_change", @updateUserInBrain, this
@eventHandler = undefined

Expand Down
27 changes: 25 additions & 2 deletions src/extensions.coffee
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
{Robot} = require.main.require "hubot"
{ReactionMessage, PresenceMessage, FileSharedMessage} = require "./message"

# Requires the es2015 version of Hubot for v3 or higher so the correct prototype is updated
if Robot.name == "CoffeeScriptCompatibleClass"
{Robot} = require.main.require "hubot/es2015"

{ReactionMessage, PresenceMessage} = require "./message"

###*
# Adds a Listener for ReactionMessages with the provided matcher, options, and callback
#
Expand Down Expand Up @@ -71,5 +70,29 @@ Robot::presenceChange = (matcher, options, callback) ->
options = matcher

@listen matchPresence, options, callback

###*
# Adds a Listener for FileSharedMessages with the provided matcher, options, and callback
#
# @public
# @param {Function} [matcher] - a function to determine if the listener should run. must return something
# truthy if it should and that value with be available on `response.match`.
# @param {Object} [options] - an object of additional parameters keyed on extension name.
# @param {Function} callback - a function that is called with a Response object if the matcher function returns true
###
Robot::fileShared = (matcher, options, callback) ->
matchFileShare = (msg) -> msg instanceof FileSharedMessage

if not options and not callback
return @listen matchFileShare, matcher

else if matcher instanceof Function
matchFileShare = (msg) -> msg instanceof FileSharedMessage && matcher(msg)

else
callback = options
options = matcher

@listen matchFileShare, options, callback

# NOTE: extend Response type with a method for creating a new thread from the incoming message
14 changes: 14 additions & 0 deletions src/message.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ class ReactionMessage extends Message
constructor: (@type, @user, @reaction, @item_user, @item, @event_ts) ->
super @user
@type = @type.replace("reaction_", "")

class FileSharedMessage extends Message

###*
# Represents a message generated by an file_shared event
#
# @constructor
# @param {User} user - A User instance that reacted to the item.
# @param {string} file_id - A String identifying the file_id of the file that was shared.
# @param {string} event_ts - A String of the file_shared event timestamp.
###
constructor: (@user, @file_id, @event_ts) ->
super @user

class PresenceMessage extends Message

Expand Down Expand Up @@ -249,3 +262,4 @@ class SlackTextMessage extends TextMessage
exports.SlackTextMessage = SlackTextMessage
exports.ReactionMessage = ReactionMessage
exports.PresenceMessage = PresenceMessage
exports.FileSharedMessage = FileSharedMessage
55 changes: 54 additions & 1 deletion test/bot.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ hubotSlackMock = require '../slack.coffee'
mockery.registerMock('hubot-slack', hubotSlackMock);

{ EnterMessage, LeaveMessage, TopicMessage, CatchAllMessage, Robot, loadBot } = require.main.require 'hubot'
{ SlackTextMessage, ReactionMessage, PresenceMessage } = require '../src/message'
{ SlackTextMessage, ReactionMessage, PresenceMessage, FileSharedMessage } = require '../src/message'
SlackClient = require '../src/client'
_ = require 'lodash'

Expand All @@ -27,6 +27,7 @@ describe 'Adapter', ->
# Check to make sure presenceChange and react are loaded to Robot
loadedRobot.presenceChange.should.be.an.instanceOf(Function).with.lengthOf(3)
loadedRobot.react.should.be.an.instanceOf(Function).with.lengthOf(3)
loadedRobot.fileShared.should.be.an.instanceOf(Function).with.lengthOf(3)

describe 'Connect', ->
it 'Should connect successfully', ->
Expand Down Expand Up @@ -320,6 +321,16 @@ describe 'Handling incoming messages', ->
should.equal @stubs._received.item_user.id, @stubs.self.id
should.equal @stubs._received.type, 'added'
should.equal @stubs._received.reaction, 'thumbsup'

it 'Should handle file_shared events as envisioned', ->
fileMessage = {
type: 'file_shared', user: @stubs.user,
file_id: 'F2147483862', event_ts: '1360782804.083113'
}
@slackbot.eventHandler fileMessage
should.equal (@stubs._received instanceof FileSharedMessage), true
should.equal @stubs._received.user.id, @stubs.user.id
should.equal @stubs._received.file_id, 'F2147483862'

describe 'Robot.react DEPRECATED', ->
before ->
Expand Down Expand Up @@ -367,6 +378,48 @@ describe 'Robot.react DEPRECATED', ->
@slackbot.robot.react matcher, @handleReaction
listener = @slackbot.robot.listeners.shift()
listener.matcher(@reactionMessage).should.be.false

describe 'Robot.fileShared', ->
before ->
user = { id: @stubs.user.id, room: @stubs.channel.id }
@fileSharedMessage = new FileSharedMessage(user, "F2147483862", '1360782804.083113')
@handleFileShared = (msg) -> "#{msg.file_id} shared"

it 'Should register a Listener with callback only', ->
@slackbot.robot.fileShared @handleFileShared
listener = @slackbot.robot.listeners.shift()
listener.matcher(@fileSharedMessage).should.be.true
listener.options.should.eql({id: null})
listener.callback(@fileSharedMessage).should.eql('F2147483862 shared')

it 'Should register a Listener with opts and callback', ->
@slackbot.robot.fileShared {id: 'foobar'}, @handleFileShared
listener = @slackbot.robot.listeners.shift()
listener.matcher(@fileSharedMessage).should.be.true
listener.options.should.eql({id: 'foobar'})
listener.callback(@fileSharedMessage).should.eql('F2147483862 shared')

it 'Should register a Listener with matcher and callback', ->
matcher = (msg) -> msg.file_id == 'F2147483862'
@slackbot.robot.fileShared matcher, @handleFileShared
listener = @slackbot.robot.listeners.shift()
listener.matcher(@fileSharedMessage).should.be.true
listener.options.should.eql({id: null})
listener.callback(@fileSharedMessage).should.eql('F2147483862 shared')

it 'Should register a Listener with matcher, opts, and callback', ->
matcher = (msg) -> msg.file_id == 'F2147483862'
@slackbot.robot.fileShared matcher, {id: 'foobar'}, @handleFileShared
listener = @slackbot.robot.listeners.shift()
listener.matcher(@fileSharedMessage).should.be.true
listener.options.should.eql({id: 'foobar'})
listener.callback(@fileSharedMessage).should.eql('F2147483862 shared')

it 'Should register a Listener that does not match the ReactionMessage', ->
matcher = (msg) -> msg.file_id == 'J12387ALDFK'
@slackbot.robot.fileShared matcher, @handleFileShared
listener = @slackbot.robot.listeners.shift()
listener.matcher(@fileSharedMessage).should.be.false

describe 'Robot.hearReaction', ->
before ->
Expand Down
1 change: 1 addition & 0 deletions test/stubs.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ beforeEach ->
robot.react = Robot.prototype.react.bind(robot)
robot.hearReaction = Robot.prototype.hearReaction.bind(robot)
robot.presenceChange = Robot.prototype.presenceChange.bind(robot)
robot.fileShared = Robot.prototype.fileShared.bind(robot)
robot
@stubs.callback = do ->
return "done"
Expand Down

0 comments on commit dc7f2a8

Please sign in to comment.