Skip to content

Commit

Permalink
fuck a color history
Browse files Browse the repository at this point in the history
  • Loading branch information
atmos committed Aug 27, 2011
0 parents commit b253e94
Show file tree
Hide file tree
Showing 15 changed files with 542 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
node_modules
20 changes: 20 additions & 0 deletions LICENSE.md
@@ -0,0 +1,20 @@
Copyright (c) 2011 GitHub Inc.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 change: 1 addition & 0 deletions Procfile
@@ -0,0 +1 @@
web: node_modules/coffee-script/bin/coffee bin/hubot
60 changes: 60 additions & 0 deletions README.md
@@ -0,0 +1,60 @@
Hubot
=====

This is a version of GitHub's Campfire bot, hubot. He's pretty cool.

This version is designed to be deployed on heroku.


Deployment
==========

% git clone https://github.com/github/hubot.git
% cd hubot
% heroku create --stack cedar
% git push heroku master
% heroku ps:scale web=1

Hubot needs four environmental variables set to run and to keep him
running on heroku.

Campfire Variables
------------------

Create a separate user for your bot and get their token from the web UI.

% heroku config:add HUBOT_CAMPFIRE_TOKEN="..."

Get the numeric ids of the rooms you want the bot to join, comma
delimited.

% heroku config:add HUBOT_CAMPFIRE_ROOMS="42,1024"

Add the subdomain hubot should connect to. If you web URL looks like
`http://mysubdomain.campfirenow.com` then you'd add it like this.

% heroku config:add HUBOT_CAMPFIRE_ACCOUNT="mysubdomain"

The Web Host
------------
In order to keep hubot running, he needs to trick heroku into thinking
he's constantly getting web traffic. Hubot will automatically ping his
HTTP endpoint if you set the `HUBOT_WEB_HOST` variable. You can get the
web endpoint by running `heroku info` and getting the hostname from the
Web URL. Be sure to remove the `http://` prefix from it.

% heroku config:add HUBOT_WEB_HOST="galaxy324.herokuapp.com"


Restart the bot
---------------
You may want to get comfortable with `heroku logs` and `heroku restart`
if you're having issues.

Local Testing
=============

It's easy to test scripts locally with the shell:

% bin/hubot -a stdio

57 changes: 57 additions & 0 deletions bin/hubot
@@ -0,0 +1,57 @@
#!/usr/bin/env coffee
##
# hubot [options]
#
# Launch an interactive hubot
#
require.paths.unshift __dirname + "/../node_modules"
require.paths.unshift __dirname + "/../src"

Path = require 'path'
HTTP = require 'http'
OptParse = require 'optparse'
PortNumber = parseInt(process.env.PORT) || 8080

Switches = [
[ "-h", "--help", "Display the help information"],
[ "-a", "--adapter ADAPTER", "The Adapter to use"]
]

Options =
adapter: "campfire"

Parser = new OptParse.OptionParser(Switches)
Parser.banner = "Usage hubot [options]"

Parser.on "adapter", (opt, value) ->
Options.adapter = value

Parser.parse process.ARGV

Options.adapter

switch Options.adapter
when "stdio"
Hubot = require("hubot/shell").Shell
when "campfire"
Hubot = require("hubot/campfire").Campfire

robot = new Hubot Path.resolve(__dirname, "..", "src", "hubot", "scripts")
robot.run()

server = HTTP.createServer( (req, res) ->
res.writeHead 200, {'Content-Type': 'text/plain'}
res.end 'Hello from Hubot\n'
).listen PortNumber

setInterval(( ->
httpOpts =
host: process.env.HUBOT_WEB_HOST

HTTP.get( httpOpts, (res) ->
console.log "Got response: #{res}" unless res.statusCode == 200
).on 'error', (e) ->
console.log "Got error: #{e.message}"
), 60000)

# vim:ft=coffee
29 changes: 29 additions & 0 deletions package.json
@@ -0,0 +1,29 @@
{
"name": "hubot",
"version": "0.1.0",
"author": "GitHub Inc.",
"keywords": "github hubot campfire bot",
"description": "A simple helpful Robot for your Company",
"licenses": [{
"type": "MIT",
"url": "http://github.com/github/hubot/raw/master/LICENSE"
}],

"repository" : {
"type" : "git",
"url" : "http://github.com/github/hubot.git"
},

"dependencies": {
"coffee-script": "1.1.1",
"optparse": "1.0.1"
},

"directories": {
"lib": "./src"
},
"main": "./src/hubot",
"bin": {
"hubot": "./bin/hubot"
}
}
166 changes: 166 additions & 0 deletions src/hubot/campfire.coffee
@@ -0,0 +1,166 @@
Robot = require "robot"
HTTPS = require "https"
EventEmitter = require("events").EventEmitter

class Campfire extends Robot
send: (user, strings...) ->
strings.forEach (str) =>
@bot.Room(user.room).speak str, (err, data) ->
console.log "#{user}: #{str}"

reply: (user, strings...) ->
strings.forEach (str) =>
@send user, "#{user.name}: #{str}"

run: ->
self = @
options =
token: process.env.HUBOT_CAMPFIRE_TOKEN
rooms: process.env.HUBOT_CAMPFIRE_ROOMS
account: process.env.HUBOT_CAMPFIRE_ACCOUNT

console.log options
bot = new CampfireStreaming(options)
console.log bot

bot.on "TextMessage", (id, created, room, user, body) ->
if body.match new RegExp "^#{bot.info.name}", "i"
bot.User user, (err, userData) ->
self.receive(
text: body
user: { id: user, name: userData.user.name, room: room }
)

bot.Me (err, data) ->
console.log data
bot.info = data.user
bot.rooms.forEach (room_id) ->
bot.Room(room_id).join (err, callback) ->
bot.Room(room_id).listen()

@bot = bot

exports.Campfire = Campfire

class CampfireStreaming extends EventEmitter
constructor: (options) ->
@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 = @

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
sound: (text, callback) ->
@message text, "SoundMessage", callback
speak: (text, callback) ->
@message text, "TextMessage", 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 =
"host" : "streaming.campfirenow.com"
"port" : 443
"path" : "/room/#{id}/live.json"
"method" : "GET"
"headers": headers

request = HTTPS.request options, (response) ->
response.setEncoding("utf8")
response.on "data", (chunk) ->
if chunk.match(/^\S+/)
console.log "#{new Date}: Received #{id} \"#{chunk}\""
try
chunk.split("\r").forEach (part) ->
data = JSON.parse part

self.emit data.type, data.id, data.created_at, data.room_id, data.user_id, data.body
data

response.on "end", ->
console.log "Streaming Connection closed. :("
process.exit(1)

response.on "error", (err) ->
console.log err
request.end()
request.on "error", (err) ->
console.log err
console.log err.stack

# 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

request: (method, path, body, callback) ->
headers =
"Authorization" : @authorization
"Host" : @domain
"Content-Type" : "application/json"

options =
"host" : @domain
"port" : 443
"path" : path
"method" : method
"headers": headers

if method == "POST"
if typeof(body) != "string"
body = JSON.stringify body
options.headers["Content-Length"] = body.length

request = HTTPS.request options, (response) ->
data = ""
response.on "data", (chunk) ->
data += chunk
response.on "end", ->
try
callback null, JSON.parse(data)
catch err
callback null, data || { }
response.on "error", (err) ->
callback err, { }

if method == "POST"
request.end(body)
else
request.end()
request.on "error", (err) ->
console.log err
console.log err.stack
24 changes: 24 additions & 0 deletions src/hubot/scripts/google-images.coffee
@@ -0,0 +1,24 @@
module.exports = (robot) ->
robot.hear /(image|img)( me)? (.*)/i, (response) ->
imagery = response.match[3]
imgurl = 'http://ajax.googleapis.com/ajax/services/search/images?' +
'v=1.0&rsz=8&q=' +escape(imagery)

response.fetch imgurl, (res) ->
images = JSON.parse(res.body)
images = images.responseData.results
image = response.random images

response.send image.unescapedUrl + "#.png"

robot.hear /animate me (.*)/i, (response) ->
imagery = response.match[1]
imgurl = 'http://ajax.googleapis.com/ajax/services/search/images?' +
'v=1.0&rsz=8&as_filetype=gif&q=animted%20' +escape(imagery)

response.fetch imgurl, (res) ->
images = JSON.parse(res.body)
images = images.responseData.results
image = response.random images

response.send image.unescapedUrl + "#.png"
13 changes: 13 additions & 0 deletions src/hubot/scripts/maps.coffee
@@ -0,0 +1,13 @@
module.exports = (robot) ->
robot.hear /(?:(satellite|terrain|hybrid)[- ])?map me (.+)/i, (response) ->
mapType = response.match[1] || "roadmap"
location = response.match[2]
url = "http://maps.google.com/maps/api/staticmap?markers=" +
escape(location) +
"&size=400x400&maptype=" +
mapType +
"&sensor=false" +
"&format=png" # So campfire knows it's an image

response.send url

16 changes: 16 additions & 0 deletions src/hubot/scripts/mustache.coffee
@@ -0,0 +1,16 @@
module.exports = (robot) ->
robot.hear /(?:mo?u)?sta(?:s|c)he?(?: me)? (.*)/i, (response) ->
imagery = response.match[1]
mustachify = "http://mustachify.me/?src="
imageUrl = 'http://ajax.googleapis.com/ajax/services/search/images?' +
'v=1.0&rsz=8&q=' +escape(imagery)

if imagery.match /^https?:\/\//i
response.send "#{mustachify}#{imagery}"
else
response.fetch imageUrl, (res) ->
images = JSON.parse(res.body)
images = images.responseData.results
image = response.random images

response.send "#{mustachify}#{image.unescapedUrl}#.png"

2 comments on commit b253e94

@cmhokej
Copy link

Choose a reason for hiding this comment

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

Ok

@yang980
Copy link

Choose a reason for hiding this comment

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

ทำใหม่เลยนะ

Please sign in to comment.