cerberus 0.7.6 → 0.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Changelog.txt +21 -1
- data/Rakefile +2 -2
- data/lib/cerberus/cli.rb +1 -1
- data/lib/cerberus/constants.rb +1 -1
- data/lib/cerberus/manager.rb +5 -5
- data/lib/cerberus/publisher/base.rb +1 -1
- data/lib/cerberus/publisher/irc.rb +8 -13
- data/lib/cerberus/publisher/mail.rb +1 -0
- data/lib/cerberus/scm/git.rb +1 -1
- data/lib/vendor/addressable/CHANGELOG +88 -0
- data/lib/vendor/addressable/LICENSE +20 -0
- data/lib/vendor/addressable/README +50 -0
- data/lib/vendor/addressable/Rakefile +74 -0
- data/lib/vendor/addressable/addressable.gemspec +30 -0
- data/lib/vendor/addressable/lib/addressable/idna.rb +4871 -0
- data/lib/vendor/addressable/lib/addressable/template.rb +1049 -0
- data/lib/vendor/addressable/lib/addressable/uri.rb +2078 -0
- data/lib/vendor/addressable/lib/addressable/version.rb +36 -0
- data/lib/vendor/addressable/spec/addressable/idna_spec.rb +194 -0
- data/lib/vendor/addressable/spec/addressable/template_spec.rb +2152 -0
- data/lib/vendor/addressable/spec/addressable/uri_spec.rb +3914 -0
- data/lib/vendor/addressable/spec/data/rfc3986.txt +3419 -0
- data/lib/vendor/addressable/tasks/clobber.rake +2 -0
- data/lib/vendor/addressable/tasks/gem.rake +68 -0
- data/lib/vendor/addressable/tasks/git.rake +40 -0
- data/lib/vendor/addressable/tasks/metrics.rake +22 -0
- data/lib/vendor/addressable/tasks/rdoc.rake +29 -0
- data/lib/vendor/addressable/tasks/rubyforge.rake +89 -0
- data/lib/vendor/addressable/tasks/spec.rake +47 -0
- data/lib/vendor/addressable/website/index.html +110 -0
- data/lib/vendor/shout-bot/TODO +2 -0
- data/lib/vendor/shout-bot/lib/shout-bot.rb +76 -0
- data/lib/vendor/shout-bot/shout-bot.gemspec +13 -0
- data/lib/vendor/tinder/CHANGELOG.txt +39 -0
- data/lib/vendor/tinder/Manifest.txt +10 -0
- data/lib/vendor/tinder/README.txt +48 -0
- data/lib/vendor/tinder/Rakefile +45 -0
- data/lib/vendor/tinder/VERSION +1 -0
- data/lib/vendor/tinder/init.rb +1 -0
- data/lib/vendor/tinder/lib/tinder.rb +12 -0
- data/lib/vendor/tinder/lib/tinder/campfire.rb +75 -0
- data/lib/vendor/tinder/lib/tinder/connection.rb +74 -0
- data/lib/vendor/tinder/lib/tinder/multipart.rb +63 -0
- data/lib/vendor/tinder/lib/tinder/room.rb +225 -0
- data/lib/vendor/tinder/site/index.html +101 -0
- data/lib/vendor/tinder/site/stylesheets/style.css +77 -0
- data/lib/vendor/tinder/spec/fixtures/rooms.json +18 -0
- data/lib/vendor/tinder/spec/fixtures/rooms/room80749.json +21 -0
- data/lib/vendor/tinder/spec/fixtures/rooms/room80751.json +21 -0
- data/lib/vendor/tinder/spec/fixtures/rooms/show.json +21 -0
- data/lib/vendor/tinder/spec/fixtures/users/me.json +11 -0
- data/lib/vendor/tinder/spec/spec.opts +2 -0
- data/lib/vendor/tinder/spec/spec_helper.rb +12 -0
- data/lib/vendor/tinder/spec/tinder/campfire_spec.rb +53 -0
- data/lib/vendor/tinder/spec/tinder/connection_spec.rb +29 -0
- data/lib/vendor/tinder/spec/tinder/room_spec.rb +98 -0
- data/lib/vendor/tinder/tinder.gemspec +79 -0
- data/test/functional_test.rb +19 -4
- data/test/integration_test.rb +1 -1
- data/test/irc_publisher_test.rb +4 -4
- data/test/mock/manager.rb +1 -1
- metadata +58 -20
- data/lib/vendor/irc/README +0 -23
- data/lib/vendor/irc/lib/IRC.rb +0 -164
- data/lib/vendor/irc/lib/IRCChannel.rb +0 -33
- data/lib/vendor/irc/lib/IRCConnection.rb +0 -134
- data/lib/vendor/irc/lib/IRCEvent.rb +0 -91
- data/lib/vendor/irc/lib/IRCUser.rb +0 -23
- data/lib/vendor/irc/lib/IRCUtil.rb +0 -49
- data/lib/vendor/irc/lib/eventmap.yml +0 -247
@@ -0,0 +1,13 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "shout-bot"
|
3
|
+
s.date = "2009-10-17"
|
4
|
+
s.version = "0.0.5"
|
5
|
+
s.description = "Ridiculously simple library to quickly say something on IRC"
|
6
|
+
s.summary = "Ridiculously simple library to quickly say something on IRC"
|
7
|
+
s.homepage = "http://github.com/sr/shout-bot"
|
8
|
+
s.authors = ["Simon Rozet", "Harry Vangberg"]
|
9
|
+
s.email = "simon@rozet.name"
|
10
|
+
s.files = ["lib/shout-bot.rb"]
|
11
|
+
s.require_paths = ["."]
|
12
|
+
s.add_dependency("addressable")
|
13
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
1.2.1 - 2009-08-27
|
2
|
+
* Fixes for listening after campfire updates [Jordan Byron]
|
3
|
+
|
4
|
+
1.2.0 - 2009-01-28
|
5
|
+
* Get the list of available files [Christopher MacGown]
|
6
|
+
* Upload files [Joshua Wand]
|
7
|
+
* Find rooms even when full [Josh Owens]
|
8
|
+
* Join rooms as a guest [Ian Lesperance]
|
9
|
+
|
10
|
+
1.1.7 - 2008-07-24
|
11
|
+
* Don't join the room when only speaking [Brian Donovan]
|
12
|
+
* Added support for HTTP proxies
|
13
|
+
* Fix listening for messages that contain URLs [Jared Kuolt]
|
14
|
+
|
15
|
+
0.1.6 - 2008-03-07
|
16
|
+
* Added Room#topic for getting the current topic [Even Weaver]
|
17
|
+
* Trap INT in #listen(&block) [borrowed from Chris Shea's Pyre]
|
18
|
+
|
19
|
+
0.1.5 - 2008-01-25
|
20
|
+
* Fixed Room#listen, which was broken by latest Campfire deploy
|
21
|
+
* Fixed timeout when listening but not speaking that will eventually log you out [Clinton R. Nixon]
|
22
|
+
|
23
|
+
0.1.4 - 2007-07-23
|
24
|
+
* Support for transcripts
|
25
|
+
* Fixed Room#leave, which was broken by a Campfire deployment [Andy Smith]
|
26
|
+
|
27
|
+
0.1.3 - 2007-02-12
|
28
|
+
* added ssl support [Tero Parviainen]
|
29
|
+
|
30
|
+
0.1.2 - 2007-01-27
|
31
|
+
* fixed bug preventing #listen from working without a block
|
32
|
+
|
33
|
+
0.1.1 - 2007-01-27
|
34
|
+
* fix bug preventing speak from working
|
35
|
+
* incorporated "watching" from http://soylentfoo.jnewland.com/articles/2006/12/07/updates-to-marshmallow-the-campfire-bot
|
36
|
+
|
37
|
+
0.1.0 - 2007-01-23
|
38
|
+
* Initial release as gem
|
39
|
+
* Get the users in a room [Tero Parviainen]
|
@@ -0,0 +1,48 @@
|
|
1
|
+
= Tinder - get the Campfire started
|
2
|
+
|
3
|
+
Tinder is a library for interfacing with Campfire, the chat application from 37Signals, allowing you to programmatically manage and speak/listen in chat rooms. As of December 2009, thanks to initial work from Joshua Peek at 37signals, it now makes use of the official Campfire API (described at: http://developer.37signals.com/campfire/).
|
4
|
+
|
5
|
+
== Usage
|
6
|
+
|
7
|
+
campfire = Tinder::Campfire.new 'mysubdomain', :token => '546884b3d8fee4d80665g561caf7h9f3ea7b999e'
|
8
|
+
# or you can still use username/password and Tinder will look up your token
|
9
|
+
# campfire = Tinder::Campfire.new 'mysubdomain', :username => 'user', :password => 'pass'
|
10
|
+
|
11
|
+
room = campfire.rooms.first
|
12
|
+
room.rename 'New Room Names'
|
13
|
+
room.speak 'Hello world!'
|
14
|
+
room.paste "my pasted\ncode"
|
15
|
+
|
16
|
+
room = campfire.find_room_by_guest_hash 'abc123', 'John Doe'
|
17
|
+
room.speak 'Hello world!'
|
18
|
+
|
19
|
+
See the RDoc for more details.
|
20
|
+
|
21
|
+
== Installation
|
22
|
+
|
23
|
+
Tinder can be installed as a gem or a Rails plugin:
|
24
|
+
|
25
|
+
gem install tinder
|
26
|
+
|
27
|
+
script/plugin install git://github.com/collectiveidea/tinder.git
|
28
|
+
|
29
|
+
== How to contribute
|
30
|
+
|
31
|
+
If you find what looks like a bug:
|
32
|
+
|
33
|
+
1. Check the GitHub issue tracker to see if anyone else has had the same issue.
|
34
|
+
http://github.com/collectiveidea/tinder/issues/
|
35
|
+
2. If you don't see anything, create an issue with information on how to reproduce it.
|
36
|
+
|
37
|
+
If you want to contribute an enhancement or a fix:
|
38
|
+
|
39
|
+
1. Fork the project on github.
|
40
|
+
http://github.com/collectiveidea/tinder
|
41
|
+
2. Make your changes with tests.
|
42
|
+
3. Commit the changes without making changes to the Rakefile, VERSION, or any other files that aren't related to your enhancement or fix
|
43
|
+
4. Send a pull request.
|
44
|
+
|
45
|
+
== ToDo
|
46
|
+
|
47
|
+
* Tests! (unit and remote)
|
48
|
+
* Marshmallow-style integration scripts for exception notification and continuous integration
|
@@ -0,0 +1,45 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gem|
|
4
|
+
gem.name = "tinder"
|
5
|
+
gem.summary = "Ruby wrapper for the Campfire API"
|
6
|
+
gem.description = "A Ruby API for interfacing with Campfire, the 37Signals chat application."
|
7
|
+
gem.authors = ['Brandon Keepers']
|
8
|
+
gem.email = 'brandon@opensoul.org'
|
9
|
+
gem.homepage = 'http://github.com/collectiveidea/tinder'
|
10
|
+
gem.rubyforge_project = "tinder"
|
11
|
+
gem.add_dependency "activesupport"
|
12
|
+
gem.add_dependency "httparty"
|
13
|
+
gem.add_dependency "mime-types"
|
14
|
+
gem.add_development_dependency "rspec"
|
15
|
+
gem.add_development_dependency "fakeweb"
|
16
|
+
end
|
17
|
+
Jeweler::GemcutterTasks.new
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rake/rdoctask'
|
23
|
+
Rake::RDocTask.new do |rdoc|
|
24
|
+
if File.exist?('VERSION')
|
25
|
+
version = File.read('VERSION')
|
26
|
+
else
|
27
|
+
version = ""
|
28
|
+
end
|
29
|
+
|
30
|
+
rdoc.rdoc_dir = 'rdoc'
|
31
|
+
rdoc.title = "tinder #{version}"
|
32
|
+
rdoc.rdoc_files.include('README*')
|
33
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'spec/rake/spectask'
|
37
|
+
desc "Run the specs under spec"
|
38
|
+
Spec::Rake::SpecTask.new do |t|
|
39
|
+
t.spec_opts = ['--options', "spec/spec.opts"]
|
40
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
41
|
+
end
|
42
|
+
task :spec => :check_dependencies
|
43
|
+
|
44
|
+
desc "Run tests"
|
45
|
+
task :default => :spec
|
@@ -0,0 +1 @@
|
|
1
|
+
1.3.1
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'tinder'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
require 'tinder/connection'
|
4
|
+
require 'tinder/multipart'
|
5
|
+
require 'tinder/campfire'
|
6
|
+
require 'tinder/room'
|
7
|
+
|
8
|
+
module Tinder
|
9
|
+
class Error < StandardError; end
|
10
|
+
class SSLRequiredError < Error; end
|
11
|
+
class AuthenticationFailed < Error; end
|
12
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Tinder
|
2
|
+
|
3
|
+
# == Usage
|
4
|
+
#
|
5
|
+
# campfire = Tinder::Campfire.new 'mysubdomain', :token => 'xyz'
|
6
|
+
#
|
7
|
+
# room = campfire.create_room 'New Room', 'My new campfire room to test tinder'
|
8
|
+
# room.speak 'Hello world!'
|
9
|
+
# room.destroy
|
10
|
+
#
|
11
|
+
# room = campfire.find_room_by_guest_hash 'abc123', 'John Doe'
|
12
|
+
# room.speak 'Hello world!'
|
13
|
+
class Campfire
|
14
|
+
attr_reader :connection
|
15
|
+
|
16
|
+
# Create a new connection to the campfire account with the given +subdomain+.
|
17
|
+
#
|
18
|
+
# == Options:
|
19
|
+
# * +:ssl+: use SSL for the connection, which is required if you have a Campfire SSL account.
|
20
|
+
# Defaults to false
|
21
|
+
# * +:proxy+: a proxy URI. (e.g. :proxy => 'http://user:pass@example.com:8000')
|
22
|
+
#
|
23
|
+
# c = Tinder::Campfire.new("mysubdomain", :ssl => true)
|
24
|
+
def initialize(subdomain, options = {})
|
25
|
+
@connection = Connection.new(subdomain, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get an array of all the available rooms
|
29
|
+
# TODO: detect rooms that are full (no link)
|
30
|
+
def rooms
|
31
|
+
connection.get('/rooms.json')['rooms'].map do |room|
|
32
|
+
Room.new(connection, room)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Find a campfire room by name
|
37
|
+
def find_room_by_name(name)
|
38
|
+
rooms.detect { |room| room.name == name }
|
39
|
+
end
|
40
|
+
|
41
|
+
# Find a campfire room by its guest hash
|
42
|
+
def find_room_by_guest_hash(hash, name)
|
43
|
+
rooms.detect { |room| room.guest_invite_code == hash }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Creates and returns a new Room with the given +name+ and optionally a +topic+
|
47
|
+
def create_room(name, topic = nil)
|
48
|
+
connection.post('/rooms.json', :body => { :room => { :name => name, :topic => topic } }.to_json)
|
49
|
+
find_room_by_name(name)
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_or_create_room_by_name(name)
|
53
|
+
find_room_by_name(name) || create_room(name)
|
54
|
+
end
|
55
|
+
|
56
|
+
# List the users that are currently chatting in any room
|
57
|
+
def users
|
58
|
+
rooms.map(&:users).flatten.compact.uniq.sort_by {|u| u[:name]}
|
59
|
+
end
|
60
|
+
|
61
|
+
# get the user info of the current user
|
62
|
+
def me
|
63
|
+
connection.get("/users/me.json")["user"]
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get the dates of the available transcripts by room
|
67
|
+
#
|
68
|
+
# campfire.available_transcripts
|
69
|
+
# #=> {"15840" => [#<Date: 4908311/2,0,2299161>, #<Date: 4908285/2,0,2299161>]}
|
70
|
+
#
|
71
|
+
def available_transcripts(room = nil)
|
72
|
+
raise NotImplementedError
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
# override HTTParty's json parser to return a HashWithIndifferentAccess
|
4
|
+
module HTTParty
|
5
|
+
class Parser
|
6
|
+
protected
|
7
|
+
def json
|
8
|
+
result = Crack::JSON.parse(body)
|
9
|
+
if result.is_a?(Hash)
|
10
|
+
result = HashWithIndifferentAccess.new(result)
|
11
|
+
end
|
12
|
+
result
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Tinder
|
18
|
+
class Connection
|
19
|
+
HOST = "campfirenow.com"
|
20
|
+
|
21
|
+
attr_reader :subdomain, :uri, :options
|
22
|
+
|
23
|
+
def initialize(subdomain, options = {})
|
24
|
+
@subdomain = subdomain
|
25
|
+
@options = { :ssl => false, :proxy => ENV['HTTP_PROXY'] }.merge(options)
|
26
|
+
@uri = URI.parse("#{@options[:ssl] ? 'https' : 'http' }://#{subdomain}.#{HOST}")
|
27
|
+
@token = options[:token]
|
28
|
+
|
29
|
+
|
30
|
+
class << self
|
31
|
+
include HTTParty
|
32
|
+
extend HTTPartyExtensions
|
33
|
+
|
34
|
+
headers 'Content-Type' => 'application/json'
|
35
|
+
end
|
36
|
+
|
37
|
+
if @options[:proxy]
|
38
|
+
proxy_uri = URI.parse(@options[:proxy])
|
39
|
+
http_proxy proxy_uri.host, proxy_uri.port
|
40
|
+
end
|
41
|
+
base_uri @uri.to_s
|
42
|
+
basic_auth token, 'X'
|
43
|
+
end
|
44
|
+
|
45
|
+
module HTTPartyExtensions
|
46
|
+
def perform_request(http_method, path, options) #:nodoc:
|
47
|
+
response = super
|
48
|
+
raise AuthenticationFailed if response.code == 401
|
49
|
+
response
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def token
|
54
|
+
@token ||= begin
|
55
|
+
self.basic_auth(options[:username], options[:password])
|
56
|
+
self.get('/users/me.json')['user']['api_auth_token']
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def metaclass
|
61
|
+
class << self; self; end
|
62
|
+
end
|
63
|
+
|
64
|
+
def method_missing(*args, &block)
|
65
|
+
metaclass.send(*args, &block)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Is the connection to campfire using ssl?
|
69
|
+
def ssl?
|
70
|
+
uri.scheme == 'https'
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'mime/types'
|
2
|
+
require 'net/http'
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module Multipart #:nodoc:
|
6
|
+
# From: http://deftcode.com/code/flickr_upload/multipartpost.rb
|
7
|
+
## Helper class to prepare an HTTP POST request with a file upload
|
8
|
+
## Mostly taken from
|
9
|
+
#http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/113774
|
10
|
+
### WAS:
|
11
|
+
## Anything that's broken and wrong probably the fault of Bill Stilwell
|
12
|
+
##(bill@marginalia.org)
|
13
|
+
### NOW:
|
14
|
+
## Everything wrong is due to keith@oreilly.com
|
15
|
+
|
16
|
+
class Param #:nodoc:
|
17
|
+
attr_accessor :k, :v
|
18
|
+
def initialize(k, v)
|
19
|
+
@k = k
|
20
|
+
@v = v
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_multipart
|
24
|
+
"Content-Disposition: form-data; name=\"#{k}\"\r\n\r\n#{v}\r\n"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class FileParam #:nodoc:
|
29
|
+
attr_accessor :k, :filename, :content
|
30
|
+
def initialize(k, filename, content)
|
31
|
+
@k = k
|
32
|
+
@filename = filename
|
33
|
+
@content = content
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_multipart
|
37
|
+
"Content-Disposition: form-data; name=\"#{k}\"; filename=\"#{filename}\"\r\n" +
|
38
|
+
"Content-Transfer-Encoding: binary\r\n" +
|
39
|
+
"Content-Type: #{MIME::Types.type_for(@filename)}\r\n\r\n" +
|
40
|
+
@content + "\r\n"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class MultipartPost #:nodoc:
|
45
|
+
BOUNDARY = 'campfire-is-awesome'
|
46
|
+
HEADER = {"Content-type" => "multipart/form-data, boundary=" + BOUNDARY + " "}
|
47
|
+
TIMEOUT_SECONDS = 30
|
48
|
+
|
49
|
+
attr_accessor :params, :query, :headers
|
50
|
+
def initialize(params)
|
51
|
+
@params = params
|
52
|
+
@query = {}
|
53
|
+
self.prepare_query
|
54
|
+
end
|
55
|
+
|
56
|
+
def prepare_query()
|
57
|
+
@query = @params.map do |k,v|
|
58
|
+
param = v.respond_to?(:read) ? FileParam.new(k, v.path, v.read) : Param.new(k, v)
|
59
|
+
"--#{BOUNDARY}\r\n#{param.to_multipart}"
|
60
|
+
end.join("") + "--#{BOUNDARY}--"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
module Tinder
|
2
|
+
# A campfire room
|
3
|
+
class Room
|
4
|
+
attr_reader :id, :name
|
5
|
+
|
6
|
+
def initialize(connection, attributes = {})
|
7
|
+
@connection = connection
|
8
|
+
@id = attributes['id']
|
9
|
+
@name = attributes['name']
|
10
|
+
@loaded = false
|
11
|
+
end
|
12
|
+
|
13
|
+
# Join the room. Pass +true+ to join even if you've already joined.
|
14
|
+
def join(force = false)
|
15
|
+
post 'join'
|
16
|
+
end
|
17
|
+
|
18
|
+
# Leave a room
|
19
|
+
def leave
|
20
|
+
post 'leave'
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get the url for guest access
|
24
|
+
def guest_url
|
25
|
+
"#{@connection.uri}/#{guest_invite_code}" if guest_access_enabled?
|
26
|
+
end
|
27
|
+
|
28
|
+
def guest_access_enabled?
|
29
|
+
load
|
30
|
+
@open_to_guests ? true : false
|
31
|
+
end
|
32
|
+
|
33
|
+
# The invite code use for guest
|
34
|
+
def guest_invite_code
|
35
|
+
load
|
36
|
+
@active_token_value
|
37
|
+
end
|
38
|
+
|
39
|
+
# Change the name of the room
|
40
|
+
def name=(name)
|
41
|
+
connection.put("/room/#{@id}.json", :body => {:room => {:name => name}}.to_json)
|
42
|
+
end
|
43
|
+
alias_method :rename, :name=
|
44
|
+
|
45
|
+
# Change the topic
|
46
|
+
def topic=(topic)
|
47
|
+
connection.put("/room/#{@id}.json", :body => {:room => {:topic => topic}}.to_json)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get the current topic
|
51
|
+
def topic
|
52
|
+
load
|
53
|
+
@topic
|
54
|
+
end
|
55
|
+
|
56
|
+
# Lock the room to prevent new users from entering and to disable logging
|
57
|
+
def lock
|
58
|
+
post :lock
|
59
|
+
end
|
60
|
+
|
61
|
+
# Unlock the room
|
62
|
+
def unlock
|
63
|
+
post :unlock
|
64
|
+
end
|
65
|
+
|
66
|
+
def ping(force = false)
|
67
|
+
raise NotImplementedError
|
68
|
+
end
|
69
|
+
|
70
|
+
def destroy
|
71
|
+
raise NotImplementedError
|
72
|
+
end
|
73
|
+
|
74
|
+
# Post a new message to the chat room
|
75
|
+
def speak(message, options = {})
|
76
|
+
send_message(message)
|
77
|
+
end
|
78
|
+
|
79
|
+
def paste(message)
|
80
|
+
send_message(message, 'PasteMessage')
|
81
|
+
end
|
82
|
+
|
83
|
+
def play(sound)
|
84
|
+
send_message(sound, 'SoundMessage')
|
85
|
+
end
|
86
|
+
|
87
|
+
# Get the list of users currently chatting for this room
|
88
|
+
def users
|
89
|
+
reload!
|
90
|
+
@users
|
91
|
+
end
|
92
|
+
|
93
|
+
# return the user with the given id; if it isn't in our room cache, do a request to get it
|
94
|
+
def user(id)
|
95
|
+
if id
|
96
|
+
user = users.detect {|u| u[:id] == id }
|
97
|
+
unless user
|
98
|
+
user_data = connection.get("/users/#{id}.json")
|
99
|
+
user = user_data && user_data[:user]
|
100
|
+
end
|
101
|
+
user[:created_at] = Time.parse(user[:created_at])
|
102
|
+
user
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Listen for new messages in the room, yielding them to the provided block as they arrive.
|
107
|
+
# Each message is a hash with:
|
108
|
+
# * +:body+: the body of the message
|
109
|
+
# * +:user+: Campfire user, which is itself a hash, of:
|
110
|
+
# * +:id+: User id
|
111
|
+
# * +:name+: User name
|
112
|
+
# * +:email_address+: Email address
|
113
|
+
# * +:admin+: Boolean admin flag
|
114
|
+
# * +:created_at+: User creation timestamp
|
115
|
+
# * +:type+: User type (e.g. Member)
|
116
|
+
# * +:id+: Campfire message id
|
117
|
+
# * +:type+: Campfire message type
|
118
|
+
# * +:room_id+: Campfire room id
|
119
|
+
# * +:created_at+: Message creation timestamp
|
120
|
+
#
|
121
|
+
# room.listen do |m|
|
122
|
+
# room.speak "Go away!" if m[:body] =~ /Java/i
|
123
|
+
# end
|
124
|
+
def listen
|
125
|
+
raise "no block provided" unless block_given?
|
126
|
+
|
127
|
+
require 'twitter/json_stream'
|
128
|
+
|
129
|
+
join # you have to be in the room to listen
|
130
|
+
auth = connection.default_options[:basic_auth]
|
131
|
+
options = {
|
132
|
+
:host => "streaming.#{Connection::HOST}",
|
133
|
+
:path => room_url_for(:live),
|
134
|
+
:auth => "#{auth[:username]}:#{auth[:password]}",
|
135
|
+
:timeout => 2
|
136
|
+
}
|
137
|
+
EventMachine::run do
|
138
|
+
stream = Twitter::JSONStream.connect(options)
|
139
|
+
stream.each_item do |message|
|
140
|
+
message = HashWithIndifferentAccess.new(JSON.parse(message))
|
141
|
+
message[:user] = user(message.delete(:user_id))
|
142
|
+
message[:created_at] = Time.parse(message[:created_at])
|
143
|
+
yield(message)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Get the dates for the available transcripts for this room
|
149
|
+
def available_transcripts
|
150
|
+
raise NotImplementedError
|
151
|
+
end
|
152
|
+
|
153
|
+
# Get the transcript for the given date (Returns a hash in the same format as #listen)
|
154
|
+
#
|
155
|
+
# room.transcript(room.available_transcripts.first)
|
156
|
+
# #=> [{:message=>"foobar!",
|
157
|
+
# :user_id=>"99999",
|
158
|
+
# :person=>"Brandon",
|
159
|
+
# :id=>"18659245",
|
160
|
+
# :timestamp=>=>Tue May 05 07:15:00 -0700 2009}]
|
161
|
+
#
|
162
|
+
# The timestamp slot will typically have a granularity of five minutes.
|
163
|
+
#
|
164
|
+
def transcript(transcript_date)
|
165
|
+
url = "/room/#{@id}/transcript/#{transcript_date.to_date.strftime('%Y/%m/%d')}.json"
|
166
|
+
connection.get(url)['messages'].map do |room|
|
167
|
+
{ :id => room['id'],
|
168
|
+
:user_id => room['user_id'],
|
169
|
+
:message => room['body'],
|
170
|
+
:timestamp => Time.parse(room['created_at']) }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def upload(filename)
|
175
|
+
File.open(filename, "rb") do |file|
|
176
|
+
params = Multipart::MultipartPost.new('upload' => file)
|
177
|
+
post(:uploads, :body => params.query)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# Get the list of latest files for this room
|
182
|
+
def files(count = 5)
|
183
|
+
get(:uploads)['uploads'].map { |u| u['full_url'] }
|
184
|
+
end
|
185
|
+
|
186
|
+
protected
|
187
|
+
def load
|
188
|
+
reload! unless @loaded
|
189
|
+
end
|
190
|
+
|
191
|
+
def reload!
|
192
|
+
attributes = connection.get("/room/#{@id}.json")['room']
|
193
|
+
|
194
|
+
@id = attributes['id']
|
195
|
+
@name = attributes['name']
|
196
|
+
@topic = attributes['topic']
|
197
|
+
@full = attributes['full']
|
198
|
+
@open_to_guests = attributes['open_to_guests']
|
199
|
+
@active_token_value = attributes['active_token_value']
|
200
|
+
@users = attributes['users']
|
201
|
+
|
202
|
+
@loaded = true
|
203
|
+
end
|
204
|
+
|
205
|
+
def send_message(message, type = 'TextMessage')
|
206
|
+
post 'speak', :body => {:message => {:body => message, :type => type}}.to_json
|
207
|
+
end
|
208
|
+
|
209
|
+
def get(action, options = {})
|
210
|
+
connection.get(room_url_for(action), options)
|
211
|
+
end
|
212
|
+
|
213
|
+
def post(action, options = {})
|
214
|
+
connection.post(room_url_for(action), options)
|
215
|
+
end
|
216
|
+
|
217
|
+
def room_url_for(action)
|
218
|
+
"/room/#{@id}/#{action}.json"
|
219
|
+
end
|
220
|
+
|
221
|
+
def connection
|
222
|
+
@connection
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|