adding embedded hubot

pull/184/head
Gabriel Engel 11 years ago
parent f4560afd6c
commit d1d6017f91
  1. 215
      packages/rocketchat-hubot/.npm/package/npm-shrinkwrap.json
  2. 193
      packages/rocketchat-hubot/hubot.coffee
  3. 187
      packages/rocketchat-hubot/hubot.coffee.new
  4. 11
      packages/rocketchat-hubot/package.js
  5. 7
      server/methods/sendMessage.coffee

@ -1,5 +1,220 @@
{
"dependencies": {
"codex-blackboard-hubot-scripts": {
"version": "https://github.com/cscott/codex-blackboard-hubot-scripts/tarball/f57c178a2faee9b36d07a7905c29093b9824e0b0",
"dependencies": {
"hubot-calculator": {
"version": "0.4.0",
"dependencies": {
"coffee-script": {
"version": "1.6.3"
},
"mathjs": {
"version": "1.7.0",
"dependencies": {
"decimal.js": {
"version": "4.0.2"
}
}
}
}
},
"hubot-google-hangouts": {
"version": "0.7.1",
"dependencies": {
"coffee-script": {
"version": "1.6.3"
},
"googleapis": {
"version": "0.4.7",
"dependencies": {
"request": {
"version": "2.25.0",
"dependencies": {
"qs": {
"version": "0.6.6"
},
"json-stringify-safe": {
"version": "5.0.1"
},
"forever-agent": {
"version": "0.5.2"
},
"tunnel-agent": {
"version": "0.3.0"
},
"http-signature": {
"version": "0.10.1",
"dependencies": {
"assert-plus": {
"version": "0.1.5"
},
"asn1": {
"version": "0.1.11"
},
"ctype": {
"version": "0.5.3"
}
}
},
"hawk": {
"version": "1.0.0",
"dependencies": {
"hoek": {
"version": "0.9.1"
},
"boom": {
"version": "0.4.2"
},
"cryptiles": {
"version": "0.2.2"
},
"sntp": {
"version": "0.2.4"
}
}
},
"aws-sign": {
"version": "0.3.0"
},
"oauth-sign": {
"version": "0.3.0"
},
"cookie-jar": {
"version": "0.3.0"
},
"node-uuid": {
"version": "1.4.3"
},
"mime": {
"version": "1.2.11"
},
"form-data": {
"version": "0.1.4",
"dependencies": {
"combined-stream": {
"version": "0.0.7",
"dependencies": {
"delayed-stream": {
"version": "0.0.5"
}
}
},
"async": {
"version": "0.9.2"
}
}
}
}
},
"async": {
"version": "0.2.6"
},
"gapitoken": {
"version": "0.1.0",
"dependencies": {
"jws": {
"version": "0.0.2",
"dependencies": {
"tap": {
"version": "0.3.3",
"dependencies": {
"inherits": {
"version": "1.0.0"
},
"yamlish": {
"version": "0.0.5"
},
"slide": {
"version": "1.1.6"
},
"runforcover": {
"version": "0.0.2",
"dependencies": {
"bunker": {
"version": "0.1.2",
"dependencies": {
"burrito": {
"version": "0.2.12",
"dependencies": {
"traverse": {
"version": "0.5.2"
},
"uglify-js": {
"version": "1.1.1"
}
}
}
}
}
}
},
"nopt": {
"version": "2.2.1",
"dependencies": {
"abbrev": {
"version": "1.0.7"
}
}
},
"mkdirp": {
"version": "0.3.5"
},
"difflet": {
"version": "0.2.6",
"dependencies": {
"traverse": {
"version": "0.6.6"
},
"charm": {
"version": "0.1.2"
},
"deep-is": {
"version": "0.1.3"
}
}
},
"deep-equal": {
"version": "0.0.0"
},
"buffer-equal": {
"version": "0.0.1"
}
}
},
"base64url": {
"version": "0.0.3"
}
}
}
}
}
}
}
}
},
"hubot-google-images": {
"version": "0.1.5"
},
"hubot-google-translate": {
"version": "0.1.0"
},
"hubot-help": {
"version": "0.1.1"
},
"hubot-scripts": {
"version": "2.16.1",
"dependencies": {
"redis": {
"version": "0.8.4"
}
}
},
"hubot-youtube": {
"version": "0.1.2"
}
}
},
"coffee-script": {
"version": "1.9.3"
},

@ -1,4 +1,197 @@
CoffeeScript = Npm.require('coffee-script')
CoffeeScript.register()
HubotScripts = Npm.require('codex-blackboard-hubot-scripts');
Hubot = Npm.require('hubot')
# Start a hubot, connected to our chat room.
'use strict'
# Log messages?
DEBUG = true
# Monkey-patch Hubot to support private messages
Hubot.Response::priv = (strings...) ->
@robot.adapter.priv @envelope, strings...
# More monkey-patching
Hubot.Robot::loadAdapter = -> # disable
# grrrr, Meteor.bindEnvironment doesn't preserve `this` apparently
bind = (f) ->
g = Meteor.bindEnvironment (self, args...) -> f.apply(self, args)
(args...) -> g @, args...
class Robot extends Hubot.Robot
constructor: (args...) ->
super args...
@hear = bind @hear
@respond = bind @respond
@enter = bind @enter
@leave = bind @leave
@topic = bind @topic
@error = bind @error
@catchAll = bind @catchAll
loadAdapter: -> false
hear: (regex, callback) -> super regex, Meteor.bindEnvironment callback
respond: (regex, callback) -> super regex, Meteor.bindEnvironment callback
enter: (callback) -> super Meteor.bindEnvironment(callback)
leave: (callback) -> super Meteor.bindEnvironment(callback)
topic: (callback) -> super Meteor.bindEnvironment(callback)
error: (callback) -> super Meteor.bindEnvironment(callback)
catchAll: (callback) -> super Meteor.bindEnvironment(callback)
sendHelper = Meteor.bindEnvironment (robot, envelope, strings, map) ->
while strings.length > 0
string = strings.shift()
if typeof(string) == 'function'
string()
else
try
map(string)
catch err
console.error "Hubot error: #{err}" if DEBUG
robot.logger.error "RocketChat send error: #{err}"
class RocketChatAdapter extends Hubot.Adapter
# Public: Raw method for sending data back to the chat source. Extend this.
#
# envelope - A Object with message, room and user details.
# strings - One or more Strings for each message to send.
#
# Returns nothing.
send: (envelope, strings...) ->
sendHelper @robot, envelope, strings, (string) =>
console.log "send #{envelope.rid}: #{string} (#{envelope.u.username})" if DEBUG
return @priv envelope, string if envelope.message.private
Meteor.call "sendMessage",
u:
username: "rocketbot"
msg: string
rid: envelope.rid
# Public: Raw method for sending emote data back to the chat source.
#
# envelope - A Object with message, room and user details.
# strings - One or more Strings for each message to send.
#
# Returns nothing.
emote: (envelope, strings...) ->
sendHelper @robot, envelope, strings, (string) =>
console.log "emote #{envelope.rid}: #{string} (#{envelope.u.username})" if DEBUG
return @priv envelope, "*** #{string} ***" if envelope.message.private
Meteor.call "sendMessage",
u:
username: "rocketbot"
msg: string
rid: envelope.rid
action: true
# Priv: our extension -- send a PM to user
priv: (envelope, strings...) ->
sendHelper @robot, envelope, strings, (string) ->
console.log "priv #{envelope.rid}: #{string} (#{envelope.u.username})" if DEBUG
Meteor.call "sendMessage",
u:
username: "rocketbot"
to: "#{envelope.u.username}"
msg: string
rid: envelope.rid
# Public: Raw method for building a reply and sending it back to the chat
# source. Extend this.
#
# envelope - A Object with message, room and user details.
# strings - One or more Strings for each reply to send.
#
# Returns nothing.
reply: (envelope, strings...) ->
if envelope.message.private
@priv envelope, strings...
else
@send envelope, strings.map((str) -> "#{envelope.u.username}: #{str}")...
# Public: Raw method for setting a topic on the chat source. Extend this.
#
# envelope - A Object with message, room and user details.
# strings - One more more Strings to set as the topic.
#
# Returns nothing.
topic: (envelope, strings...) ->
# Public: Raw method for playing a sound in the chat source. Extend this.
#
# envelope - A Object with message, room and user details.
# strings - One or more strings for each play message to send.
#
# Returns nothing
play: (envelope, strings...) ->
# Public: Raw method for invoking the bot to run. Extend this.
#
# Returns nothing.
run: ->
# Public: Raw method for shutting the bot down. Extend this.
#
# Returns nothing.
close: ->
class RocketBotReceiver
constructor: (message) ->
RocketBotUser = new Hubot.User(message.u.username, rid: message.rid)
RocketBotTextMessage = new Hubot.TextMessage(RocketBotUser, message.msg, message._id)
RocketBot.adapter.receive RocketBotTextMessage
console.log RocketBot;
return message
RocketBot = new Robot null, null, false, Meteor.settings?.botname ? 'rocketbot'
RocketBot.alias = 'bot'
RocketBot.adapter = new RocketChatAdapter RocketBot
RocketChat.callbacks.add 'afterSaveMessage', RocketBotReceiver, RocketChat.callbacks.priority.LOW
# Meteor.startup ->
# console.log RocketBot;
# # what's (the regexp for) my name?
# robot.respond /(?:)/, -> false
# mynameRE = robot.listeners.pop().regex
# # register scripts
# HubotScripts(robot)
# Object.keys(share.hubot).forEach (scriptName) ->
# console.log "Loading hubot script: #{scriptName}"
# share.hubot[scriptName](robot)
# # register our nick
# n = Meteor.call 'newNick', {name: 'rocketbot'}
# Meteor.call 'setTag', {type:'nicks', object:n._id, name:'Gravatar', value:'codex@printf.net', who:n.canon}
# # register our presence in general chat
# keepalive = -> Meteor.call 'setPresence',
# u:
# username: 'rocketbot'
# rid: '57om6EQCcFami9wuT'
# present: true
# foreground: true
# keepalive()
# Meteor.setInterval keepalive, 30*1000 # every 30s refresh presence
# # listen to the chat room, ignoring messages sent before we startup
# startup = true
# ChatMessage.find({}).observe
# added: (message) ->
# return if startup
# return if message.u.username is "rocketbot" or message.u.username is ""
# return if message.system or message.action or message.oplog or message.bodyIsHtml
# console.log "Received from #{message.u.username} in #{message.rid}: #{message.body}"\
# if DEBUG
# user = new Hubot.User(message.u.username, room: message.rid)
# tm = new Hubot.TextMessage(user, message.body, message._id)
# tm.private = message.to?
# # if private, ensure it's treated as a direct address
# if tm.private and not mynameRE.test(tm.text)
# tm.text = "#{robot.name} #{tm.text}"
# adapter.receive tm
# startup = false
# Meteor.call "sendMessage",
# rid: '57om6EQCcFami9wuT'
# msg: 'wakes up'
# u:
# username: "rocketbot"
# action: true

@ -1,187 +0,0 @@
hubot = Npm.require('hubot')
Hubot = hubot;
# Start a hubot, connected to our chat room.
'use strict'
model = share.model # import
# Log messages?
DEBUG = true
# Monkey-patch Hubot to support private messages
Hubot.Response::priv = (strings...) ->
@robot.adapter.priv @envelope, strings...
# More monkey-patching
Hubot.Robot::loadAdapter = -> # disable
# grrrr, Meteor.bindEnvironment doesn't preserve `this` apparently
bind = (f) ->
g = Meteor.bindEnvironment (self, args...) -> f.apply(self, args)
(args...) -> g @, args...
class Robot extends Hubot.Robot
constructor: (args...) ->
super args...
@hear = bind @hear
@respond = bind @respond
@enter = bind @enter
@leave = bind @leave
@topic = bind @topic
@error = bind @error
@catchAll = bind @catchAll
loadAdapter: -> false
hear: (regex, callback) -> super regex, Meteor.bindEnvironment callback
respond: (regex, callback) -> super regex, Meteor.bindEnvironment callback
enter: (callback) -> super Meteor.bindEnvironment(callback)
leave: (callback) -> super Meteor.bindEnvironment(callback)
topic: (callback) -> super Meteor.bindEnvironment(callback)
error: (callback) -> super Meteor.bindEnvironment(callback)
catchAll: (callback) -> super Meteor.bindEnvironment(callback)
sendHelper = Meteor.bindEnvironment (robot, envelope, strings, map) ->
# be present in the room
try
Meteor.call 'setPresence',
nick: 'codexbot'
room_name: envelope.room
present: true
foreground: true
while strings.length > 0
string = strings.shift()
if typeof(string) == 'function'
string()
else
try
map(string)
catch err
console.error "Hubot error: #{err}" if DEBUG
robot.logger.error "Blackboard send error: #{err}"
class BlackboardAdapter extends Hubot.Adapter
# Public: Raw method for sending data back to the chat source. Extend this.
#
# envelope - A Object with message, room and user details.
# strings - One or more Strings for each message to send.
#
# Returns nothing.
send: (envelope, strings...) ->
sendHelper @robot, envelope, strings, (string) =>
console.log "send #{envelope.room}: #{string} (#{envelope.user.id})" if DEBUG
return @priv envelope, string if envelope.message.private
Meteor.call "newMessage",
nick: "codexbot"
body: string
room_name: envelope.room
# Public: Raw method for sending emote data back to the chat source.
#
# envelope - A Object with message, room and user details.
# strings - One or more Strings for each message to send.
#
# Returns nothing.
emote: (envelope, strings...) ->
sendHelper @robot, envelope, strings, (string) =>
console.log "emote #{envelope.room}: #{string} (#{envelope.user.id})" if DEBUG
return @priv envelope, "*** #{string} ***" if envelope.message.private
Meteor.call "newMessage",
nick: "codexbot"
body: string
room_name: envelope.room
action: true
# Priv: our extension -- send a PM to user
priv: (envelope, strings...) ->
sendHelper @robot, envelope, strings, (string) ->
console.log "priv #{envelope.room}: #{string} (#{envelope.user.id})" if DEBUG
Meteor.call "newMessage",
nick: "codexbot"
to: "#{envelope.user.id}"
body: string
room_name: envelope.room
# Public: Raw method for building a reply and sending it back to the chat
# source. Extend this.
#
# envelope - A Object with message, room and user details.
# strings - One or more Strings for each reply to send.
#
# Returns nothing.
reply: (envelope, strings...) ->
if envelope.message.private
@priv envelope, strings...
else
@send envelope, strings.map((str) -> "#{envelope.user.id}: #{str}")...
# Public: Raw method for setting a topic on the chat source. Extend this.
#
# envelope - A Object with message, room and user details.
# strings - One more more Strings to set as the topic.
#
# Returns nothing.
topic: (envelope, strings...) ->
# Public: Raw method for playing a sound in the chat source. Extend this.
#
# envelope - A Object with message, room and user details.
# strings - One or more strings for each play message to send.
#
# Returns nothing
play: (envelope, strings...) ->
# Public: Raw method for invoking the bot to run. Extend this.
#
# Returns nothing.
run: ->
# Public: Raw method for shutting the bot down. Extend this.
#
# Returns nothing.
close: ->
Meteor.startup ->
robot = new Robot null, null, false, Meteor.settings?.botname ? 'codexbot'
robot.alias = 'bot'
adapter = robot.adapter = new BlackboardAdapter robot
# what's (the regexp for) my name?
robot.respond /(?:)/, -> false
mynameRE = robot.listeners.pop().regex
# register scripts
HubotScripts(robot)
Object.keys(share.hubot).forEach (scriptName) ->
console.log "Loading hubot script: #{scriptName}"
share.hubot[scriptName](robot)
# register our nick
n = Meteor.call 'newNick', {name: 'codexbot'}
Meteor.call 'setTag', {type:'nicks', object:n._id, name:'Gravatar', value:'codex@printf.net', who:n.canon}
# register our presence in general chat
keepalive = -> Meteor.call 'setPresence',
nick: 'codexbot'
room_name: 'general/0'
present: true
foreground: true
keepalive()
Meteor.setInterval keepalive, 30*1000 # every 30s refresh presence
# listen to the chat room, ignoring messages sent before we startup
startup = true
model.Messages.find({}).observe
added: (msg) ->
return if startup
return if msg.nick is "codexbot" or msg.nick is ""
return if msg.system or msg.action or msg.oplog or msg.bodyIsHtml
console.log "Received from #{msg.nick} in #{msg.room_name}: #{msg.body}"\
if DEBUG
user = new Hubot.User(msg.nick, room: msg.room_name)
tm = new Hubot.TextMessage(user, msg.body, msg._id)
tm.private = msg.to?
# if private, ensure it's treated as a direct address
if tm.private and not mynameRE.test(tm.text)
tm.text = "#{robot.name} #{tm.text}"
adapter.receive tm
startup = false
Meteor.call "newMessage",
nick: "codexbot"
body: 'wakes up'
room_name: 'general/0'
action: true

@ -8,15 +8,24 @@ Package.describe({
Package.onUse(function(api) {
api.versionsFrom('1.0');
api.use(['coffeescript']);
api.use([
'coffeescript',
'rocketchat:lib@0.0.1'
]);
api.addFiles('hubot.coffee', ['server']);
api.export('Hubot', ['server']);
api.export('HubotScripts', ['server']);
api.export('RocketBot', ['server']);
api.export('RocketBotReceiver', ['server']);
api.export('RocketChatAdapter', ['server']);
});
Npm.depends({
"coffee-script": "1.9.3",
"codex-blackboard-hubot-scripts": "https://github.com/cscott/codex-blackboard-hubot-scripts/tarball/f57c178a2faee9b36d07a7905c29093b9824e0b0",
"hubot": "2.13.1"
});

@ -116,3 +116,10 @@ Meteor.methods
$unset:
t: 1
expireAt: 1
Meteor.defer ->
message._id = Random.id()
RocketChat.callbacks.run 'afterSaveMessage', message

Loading…
Cancel
Save