tagbar/tests/coffee/campfire.coffee
2013-04-06 00:59:14 +13:00

252 lines
7.3 KiB
CoffeeScript

Robot = require '../robot'
Adapter = require '../adapter'
HTTPS = require 'https'
EventEmitter = require('events').EventEmitter
class Campfire extends Adapter
send: (user, strings...) ->
if strings.length > 0
@bot.Room(user.room).speak strings.shift(), (err, data) =>
@robot.logger.error "Campfire error: #{err}" if err?
@send user, strings...
reply: (user, strings...) ->
@send user, strings.map((str) -> "#{user.name}: #{str}")...
topic: (user, strings...) ->
@bot.Room(user.room).topic strings.join(" / "), (err, data) =>
@robot.logger.error "Campfire error: #{err}" if err?
run: ->
self = @
options =
token: process.env.HUBOT_CAMPFIRE_TOKEN
rooms: process.env.HUBOT_CAMPFIRE_ROOMS
account: process.env.HUBOT_CAMPFIRE_ACCOUNT
bot = new CampfireStreaming(options, @robot)
withAuthor = (callback) -> (id, created, room, user, body) ->
bot.User user, (err, userData) ->
if userData.user
author = self.userForId(userData.user.id, userData.user)
self.robot.brain.data.users[userData.user.id].name = userData.user.name
self.robot.brain.data.users[userData.user.id].email_address = userData.user.email_address
author.room = room
callback id, created, room, user, body, author
bot.on "TextMessage", withAuthor (id, created, room, user, body, author) ->
unless bot.info.id == author.id
self.receive new Robot.TextMessage(author, body)
bot.on "EnterMessage", withAuthor (id, created, room, user, body, author) ->
unless bot.info.id == author.id
self.receive new Robot.EnterMessage(author)
bot.on "LeaveMessage", withAuthor (id, created, room, user, body, author) ->
unless bot.info.id == author.id
self.receive new Robot.LeaveMessage(author)
bot.Me (err, data) ->
bot.info = data.user
bot.name = bot.info.name
for roomId in bot.rooms
do (roomId) ->
bot.Room(roomId).join (err, callback) ->
bot.Room(roomId).listen()
bot.on "reconnect", (roomId) ->
bot.Room(roomId).join (err, callback) ->
bot.Room(roomId).listen()
@bot = bot
self.emit "connected"
exports.use = (robot) ->
new Campfire robot
class CampfireStreaming extends EventEmitter
constructor: (options, @robot) ->
unless options.token? and options.rooms? and options.account?
@robot.logger.error "Not enough parameters provided. I Need a token, rooms and account"
process.exit(1)
@token = options.token
@rooms = options.rooms.split(",")
@account = options.account
@domain = @account + ".campfirenow.com"
@authorization = "Basic " + new Buffer("#{@token}:x").toString("base64")
Rooms: (callback) ->
@get "/rooms", callback
User: (id, callback) ->
@get "/users/#{id}", callback
Me: (callback) ->
@get "/users/me", callback
Room: (id) ->
self = @
logger = @robot.logger
show: (callback) ->
self.post "/room/#{id}", "", callback
join: (callback) ->
self.post "/room/#{id}/join", "", callback
leave: (callback) ->
self.post "/room/#{id}/leave", "", callback
lock: (callback) ->
self.post "/room/#{id}/lock", "", callback
unlock: (callback) ->
self.post "/room/#{id}/unlock", "", callback
# say things to this channel on behalf of the token user
paste: (text, callback) ->
@message text, "PasteMessage", callback
topic: (text, callback) ->
body = {room: {topic: text}}
self.put "/room/#{id}", body, callback
sound: (text, callback) ->
@message text, "SoundMessage", callback
speak: (text, callback) ->
body = { message: { "body":text } }
self.post "/room/#{id}/speak", body, callback
message: (text, type, callback) ->
body = { message: { "body":text, "type":type } }
self.post "/room/#{id}/speak", body, callback
# listen for activity in channels
listen: ->
headers =
"Host" : "streaming.campfirenow.com"
"Authorization" : self.authorization
options =
"agent" : false
"host" : "streaming.campfirenow.com"
"port" : 443
"path" : "/room/#{id}/live.json"
"method" : "GET"
"headers": headers
request = HTTPS.request options, (response) ->
response.setEncoding("utf8")
buf = ''
response.on "data", (chunk) ->
if chunk is ' '
# campfire api sends a ' ' heartbeat every 3s
else if chunk.match(/^\s*Access Denied/)
# errors are not json formatted
logger.error "Campfire error on room #{id}: #{chunk}"
else
# api uses newline terminated json payloads
# buffer across tcp packets and parse out lines
buf += chunk
while (offset = buf.indexOf("\r")) > -1
part = buf.substr(0, offset)
buf = buf.substr(offset + 1)
if part
try
data = JSON.parse part
self.emit data.type, data.id, data.created_at, data.room_id, data.user_id, data.body
catch err
logger.error "Campfire error: #{err}"
response.on "end", ->
logger.error "Streaming connection closed for room #{id}. :("
setTimeout (->
self.emit "reconnect", id
), 5000
response.on "error", (err) ->
logger.error "Campfire response error: #{err}"
request.on "error", (err) ->
logger.error "Campfire request error: #{err}"
request.end()
# Convenience HTTP Methods for posting on behalf of the token"d user
get: (path, callback) ->
@request "GET", path, null, callback
post: (path, body, callback) ->
@request "POST", path, body, callback
put: (path, body, callback) ->
@request "PUT", path, body, callback
request: (method, path, body, callback) ->
logger = @robot.logger
headers =
"Authorization" : @authorization
"Host" : @domain
"Content-Type" : "application/json"
options =
"agent" : false
"host" : @domain
"port" : 443
"path" : path
"method" : method
"headers": headers
if method is "POST" || method is "PUT"
if typeof(body) isnt "string"
body = JSON.stringify body
body = new Buffer(body)
options.headers["Content-Length"] = body.length
request = HTTPS.request options, (response) ->
data = ""
response.on "data", (chunk) ->
data += chunk
response.on "end", ->
if response.statusCode >= 400
switch response.statusCode
when 401
throw new Error "Invalid access token provided, campfire refused the authentication"
else
logger.error "Campfire error: #{response.statusCode}"
try
callback null, JSON.parse(data)
catch err
callback null, data or { }
response.on "error", (err) ->
logger.error "Campfire response error: #{err}"
callback err, { }
if method is "POST" || method is "PUT"
request.end(body, 'binary')
else
request.end()
request.on "error", (err) ->
logger.error "Campfire request error: #{err}"