Skip to content

Commit

Permalink
Add test
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyuvn committed Apr 9, 2016
1 parent 372394a commit 0d8ec67
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 52 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
language: node_js
node_js:
- "5.8"
12 changes: 12 additions & 0 deletions index.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Facebook = require './src/facebook'
{StickerMessage} = require './src/message'
{StickerListener} = require './src/listener'

module.exports = exports = {
Facebook
StickerMessage
StickerListener
}

exports.use = (robot) ->
new Facebook robot
13 changes: 9 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{
"name": "hubot-facebook",
"version": "0.5.0",
"version": "0.5.2",
"description": "Facebook chat adapter for hubot",
"main": "./src/facebook",
"main": "./index",
"scripts": {
"test": "mocha --compilers coffee:coffee-script/register --reporter spec"
},
"author": "Clicia Scarlet <[email protected]>",
"license": "MIT",
"repository": {
Expand All @@ -11,6 +14,9 @@
},
"dependencies": {
"facebook-chat-api": "1.0.8",
"coffee-script": "~1.7.1",
"should": "~2.0.2",
"mocha": "~1.13.0",
"hubot": "~2.13"
},
"engines": {
Expand All @@ -22,6 +28,5 @@
"name": "blazeu",
"email": "[email protected]"
}
],
"scripts": {}
]
}
166 changes: 121 additions & 45 deletions src/facebook.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ class FbResponse extends Response
sendSticker: (ids...) ->
@robot.adapter.sendSticker @envelope, ids...

sendImage: (string, file_streams...) ->
@robot.adapter.sendImage @envelope, string, file_streams...
sendFile: (string, file_streams...) ->
@robot.adapter.sendFile @envelope, string, file_streams...

read: () ->
@robot.adapter.read @envelope

class Facebook extends Adapter

send: (envelope, strings...) ->
for str in strings
continue unless str
msg = {body: str}
@bot.sendMessage msg, envelope.room

Expand All @@ -33,24 +33,105 @@ class Facebook extends Adapter
msg = {sticker: id}
@bot.sendMessage msg, envelope.room

sendImage: (envelope, string, file_streams...) ->
sendFile: (envelope, string, file_streams...) ->
msg = {body: string, attachment: file_streams}
@bot.sendMessage msg, envelope.room

read: (envelope) ->
@bot.markAsRead envelope.room

reply: (envelope, strings...) ->
name = envelope.user.name.split(' ')[0]
@send envelope, strings.map((str) -> "#{name}: #{str}")...
name = envelope.user?.name?.split(' ')[0] || envelope.message?.user?.name?.split(' ')[0]
@send envelope, strings.map((str) -> "@#{name} #{str}")...

topic: (envelope, strings...) ->
title = strings.join(' ')
thread = envelope.room
@bot.setTitle title, thread

customeMessage: (data) =>
if data.user?.id || data.user?.name
if data.user?.id
room = data.user.id
else
user = @robot.brain.userForName data.user.name
room = user.id if user?
else if data.room?
room = data.room

unless room?
room = if data.room
data.room
else if data.message.envelope
data.message.envelope.room
else data.message.room

msg = {}
msg.sticker = data.sticker if data.sticker?
msg.body = data.text if data.text?
msg.attachment = data.attachment || data.attachments

@bot.sendMessage msg, room

privateMessage: (data) =>
user = data.message.user
@customeMessage user: user

message: (event) ->
# Skip useless data
return if event.type in ["typ", "read_receipt", "read", "presence"]

sender = event.senderID or event.author or event.userID
options = room: event.threadID
name = event.senderName
if event.participantNames? and event.participantIDs?
name = event.participantNames[event.participantIDs.indexOf(sender)]
options.name = name if name
user = @robot.brain.userForId sender, options

switch event.type
when "message"
if event.body?
@robot.logger.debug "#{user.name} -> #{user.room}: #{event.body}"

# If this is a PM, pretend it was addressed to us
event.body = "#{@robot.name} #{event.body}" if "#{sender}" == "#{event.threadID}"

@receive new TextMessage user, event.body, event.messageID

for attachment in event.attachments
switch attachment.type
when "sticker"
@robot.logger.debug "#{user.name} -> #{user.room}: #{attachment.stickerID}"
@receive new StickerMessage user,
(attachment.url || attachment.spriteURI2x || attachment.spriteURI),
event.messageID, attachment
# TODO "file", "photo", "animated_image", "share"
when "event"
switch event.logMessageType
when "log:thread-name"
@receive new TopicMessage user, event.logMessageData.name
when "log:unsubscribe"
@receive new LeaveMessage user
when "log:subscribe"
@receive new EnterMessage user
@robot.logger.debug "#{user.name} -> #{user.room}: #{event.logMessageType}"

setName: (cb) ->
user_id = @bot.getCurrentUserID()
@bot.getUserInfo user_id, (err, res) =>
return @robot.logger.error err if err
# set robot name to first name of the faceobok account
@robot.name = res[user_id].firstName
cb()

run: ->
self = @
# another way to use special send is use @robot.emit
# so hubot don't need to check if respond has special method or not
@robot.on "facebook.sendSticker", @.customeMessage
@robot.on "facebook.sendImage", @.customeMessage
@robot.on "facebook.sendFile", @.customeMessage
@robot.on "facebook.sendPrivate", @.privateMessage

config =
name: if @robot.name is 'hubot' then null else @robot.name
Expand All @@ -59,68 +140,63 @@ class Facebook extends Adapter

# Override the response to provide custom method
@robot.Response = FbResponse
@robot.respondSticker = (regex, callback) =>
@robot.listeners.push new StickerListener @robot, regex, callback

chat email: config.email, password: config.password, (err, bot) ->
return self.robot.logger.error err if err
chat email: config.email, password: config.password, (err, bot) =>
return @robot.logger.error err if err

@bot = bot

# Mute fb-chat-api's logging and allow listen for events
bot.setOptions({logLevel: "silent", listenEvents: true})

self.bot = bot

if not config.name?
config.name = 'hubot'
bot.getUserInfo bot.getCurrentUserID(), (err, res) ->
return self.robot.logger.error err if err
# set robot name to first name of the faceobok account
for prop of res
config.name = res[prop].firstName if (res.hasOwnProperty(prop) && res[prop].firstName)
self.robot.name = config.name
self.emit "connected"
@bot.setOptions({logLevel: "silent", listenEvents: true})

if config.name
@emit "connected"
else
self.emit "connected"
@setName => @emit "connected"

bot.listen (err, event, stop) ->
return self.robot.logger.error err if err or !event

# Skip useless data
bot.listen (err, event, stop) =>
return @robot.logger.error err if err or not event?
return if event.type in ["typ", "read_receipt", "read", "presence"]

sender = event.senderID or event.author or event.userID
user = self.robot.brain.userForId sender, name: event.senderName, room: event.threadID
options = room: event.threadID
name = event.senderName
if event.participantNames? and event.participantIDs?
name = event.participantNames[event.participantIDs.indexOf(sender)]
options.name = name if name
user = @robot.brain.userForId sender, options

switch event.type
when "message"
if event.body
self.robot.logger.debug "#{user.name} -> #{user.room}: #{event.body}"
if event.body?
@robot.logger.debug "#{user.name} -> #{user.room}: #{event.body}"

# If this is a PM, pretend it was addressed to us
event.body = "#{self.robot.name} #{event.body}" if "#{sender}" == "#{event.threadID}"
event.body = "#{@robot.name} #{event.body}" if "#{sender}" == "#{event.threadID}"

self.receive new TextMessage user, event.body, event.messageID
@receive new TextMessage user, event.body, event.messageID

for attachment in event.attachments
switch attachment.type
when "sticker"
self.robot.logger.debug "#{user.name} -> #{user.room}: #{attachment.stickerID}"
self.receive new StickerMessage user, (attachment.spriteURI2x || attachment.spriteURI),
event.messageID, attachment.stickerID
@robot.logger.debug "#{user.name} -> #{user.room}: #{attachment.stickerID}"
@receive new StickerMessage user,
(attachment.url || attachment.spriteURI2x || attachment.spriteURI),
event.messageID, attachment
# TODO "file", "photo", "animated_image", "share"
@bot.markAsRead user.room
when "event"
switch event.logMessageType
when "log:thread-name"
self.receive new TopicMessage user, event.logMessageData.name
@receive new TopicMessage user, event.logMessageData.name
when "log:unsubscribe"
self.receive new LeaveMessage user
@receive new LeaveMessage user
when "log:subscribe"
self.receive new EnterMessage user
self.robot.logger.debug "#{user.name} -> #{user.room}: #{event.logMessageType}"
@receive new EnterMessage user
@robot.logger.debug "#{user.name} -> #{user.room}: #{event.logMessageType}"

module.exports = exports = {
Facebook
StickerMessage
StickerListener
}

exports.use = (robot) ->
new Facebook robot
module.exports = Facebook
6 changes: 3 additions & 3 deletions src/message.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ class StickerMessage extends Message
# text - The sticker url
# id - The id of message
# stickerID - The id of sticker
constructor: (@user, @text="", @id="", @stickerID="") ->
constructor: (@user, @text="", @id="", @fields={}) ->
super @user

match: (regex) ->
@stickerID.match regex
@fields.stickerID.match regex

toString: () ->
"Sticker(#{@stickerID})"
"Sticker(#{@fields.stickerID})"

module.exports = {
StickerMessage
Expand Down
59 changes: 59 additions & 0 deletions test/facebook.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{Facebook} = require '../index'

should = require 'should'

describe 'Adapter', ->
it 'Should initialize with a robot', ->
@facebook.robot.should.eql @stubs.robot

describe 'Login', ->
it 'Should set the robot name', ->
@facebook.setName =>
@facebook.robot.name.should.equal @stubs.self.name

describe 'Send Messages', ->
it 'Should send multiple messages', ->
@facebook.send {room: 'general'}, 'one', 'two', 'three'
@stubs._msg.length.should.equal 3

it 'Should not send empty messages', ->
@facebook.send {room: 'general'}, 'Hello', '', '', 'world!'
@stubs._msg.length.should.equal 2

describe 'Send Private Messages', ->
it 'Should send multiple message', ->
@facebook.sendPrivate {user: id: 'name'}, 'one', 'two', 'three'
@stubs._msg.length.should.equal 3
@stubs._msg[0].msg.body.should.eql 'one'
@stubs._msg[0].thread.should.eql 'name'

it 'Should not send empty messages', ->
@facebook.sendPrivate {user: id: 'name'}, 'Hello', '', '', 'world!'
@stubs._msg.length.should.equal 2

describe 'Send Sticker Messages', ->
it 'Should send multiple sticker', ->
@facebook.sendSticker {room: 'general'}, 'pusheen1', 'pusheen2'
@stubs._msg.length.should.equal 2
@stubs._msg[0].msg.sticker.should.eql 'pusheen1'

# TODO test send file

describe 'Other action', ->
it 'Should mark as read', ->
@facebook.read {room: 'general'}
@stubs._readed.general.should.equal true

it 'Should reply a message', ->
@facebook.reply {room: 'general', message: user: name: "user"}, "test"
@stubs._msg.length.should.equal 1
@stubs._msg[0].msg.body.should.eql '@user test'

it 'Should reply a message only with first name', ->
@facebook.reply {room: 'general', message: user: name: "first last"}, "test"
@stubs._msg.length.should.equal 1
@stubs._msg[0].msg.body.should.eql '@first test'

it 'Should set topic', ->
@facebook.topic {room: 'general'}, 'test1', 'test2'
@stubs._title.general.should.eql 'test1 test2'
Loading

0 comments on commit 0d8ec67

Please sign in to comment.