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.
Files changed (70) hide show
  1. data/Changelog.txt +21 -1
  2. data/Rakefile +2 -2
  3. data/lib/cerberus/cli.rb +1 -1
  4. data/lib/cerberus/constants.rb +1 -1
  5. data/lib/cerberus/manager.rb +5 -5
  6. data/lib/cerberus/publisher/base.rb +1 -1
  7. data/lib/cerberus/publisher/irc.rb +8 -13
  8. data/lib/cerberus/publisher/mail.rb +1 -0
  9. data/lib/cerberus/scm/git.rb +1 -1
  10. data/lib/vendor/addressable/CHANGELOG +88 -0
  11. data/lib/vendor/addressable/LICENSE +20 -0
  12. data/lib/vendor/addressable/README +50 -0
  13. data/lib/vendor/addressable/Rakefile +74 -0
  14. data/lib/vendor/addressable/addressable.gemspec +30 -0
  15. data/lib/vendor/addressable/lib/addressable/idna.rb +4871 -0
  16. data/lib/vendor/addressable/lib/addressable/template.rb +1049 -0
  17. data/lib/vendor/addressable/lib/addressable/uri.rb +2078 -0
  18. data/lib/vendor/addressable/lib/addressable/version.rb +36 -0
  19. data/lib/vendor/addressable/spec/addressable/idna_spec.rb +194 -0
  20. data/lib/vendor/addressable/spec/addressable/template_spec.rb +2152 -0
  21. data/lib/vendor/addressable/spec/addressable/uri_spec.rb +3914 -0
  22. data/lib/vendor/addressable/spec/data/rfc3986.txt +3419 -0
  23. data/lib/vendor/addressable/tasks/clobber.rake +2 -0
  24. data/lib/vendor/addressable/tasks/gem.rake +68 -0
  25. data/lib/vendor/addressable/tasks/git.rake +40 -0
  26. data/lib/vendor/addressable/tasks/metrics.rake +22 -0
  27. data/lib/vendor/addressable/tasks/rdoc.rake +29 -0
  28. data/lib/vendor/addressable/tasks/rubyforge.rake +89 -0
  29. data/lib/vendor/addressable/tasks/spec.rake +47 -0
  30. data/lib/vendor/addressable/website/index.html +110 -0
  31. data/lib/vendor/shout-bot/TODO +2 -0
  32. data/lib/vendor/shout-bot/lib/shout-bot.rb +76 -0
  33. data/lib/vendor/shout-bot/shout-bot.gemspec +13 -0
  34. data/lib/vendor/tinder/CHANGELOG.txt +39 -0
  35. data/lib/vendor/tinder/Manifest.txt +10 -0
  36. data/lib/vendor/tinder/README.txt +48 -0
  37. data/lib/vendor/tinder/Rakefile +45 -0
  38. data/lib/vendor/tinder/VERSION +1 -0
  39. data/lib/vendor/tinder/init.rb +1 -0
  40. data/lib/vendor/tinder/lib/tinder.rb +12 -0
  41. data/lib/vendor/tinder/lib/tinder/campfire.rb +75 -0
  42. data/lib/vendor/tinder/lib/tinder/connection.rb +74 -0
  43. data/lib/vendor/tinder/lib/tinder/multipart.rb +63 -0
  44. data/lib/vendor/tinder/lib/tinder/room.rb +225 -0
  45. data/lib/vendor/tinder/site/index.html +101 -0
  46. data/lib/vendor/tinder/site/stylesheets/style.css +77 -0
  47. data/lib/vendor/tinder/spec/fixtures/rooms.json +18 -0
  48. data/lib/vendor/tinder/spec/fixtures/rooms/room80749.json +21 -0
  49. data/lib/vendor/tinder/spec/fixtures/rooms/room80751.json +21 -0
  50. data/lib/vendor/tinder/spec/fixtures/rooms/show.json +21 -0
  51. data/lib/vendor/tinder/spec/fixtures/users/me.json +11 -0
  52. data/lib/vendor/tinder/spec/spec.opts +2 -0
  53. data/lib/vendor/tinder/spec/spec_helper.rb +12 -0
  54. data/lib/vendor/tinder/spec/tinder/campfire_spec.rb +53 -0
  55. data/lib/vendor/tinder/spec/tinder/connection_spec.rb +29 -0
  56. data/lib/vendor/tinder/spec/tinder/room_spec.rb +98 -0
  57. data/lib/vendor/tinder/tinder.gemspec +79 -0
  58. data/test/functional_test.rb +19 -4
  59. data/test/integration_test.rb +1 -1
  60. data/test/irc_publisher_test.rb +4 -4
  61. data/test/mock/manager.rb +1 -1
  62. metadata +58 -20
  63. data/lib/vendor/irc/README +0 -23
  64. data/lib/vendor/irc/lib/IRC.rb +0 -164
  65. data/lib/vendor/irc/lib/IRCChannel.rb +0 -33
  66. data/lib/vendor/irc/lib/IRCConnection.rb +0 -134
  67. data/lib/vendor/irc/lib/IRCEvent.rb +0 -91
  68. data/lib/vendor/irc/lib/IRCUser.rb +0 -23
  69. data/lib/vendor/irc/lib/IRCUtil.rb +0 -49
  70. 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,10 @@
1
+ CHANGELOG.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ init.rb
6
+ lib/tinder.rb
7
+ lib/tinder/campfire.rb
8
+ lib/tinder/multipart.rb
9
+ lib/tinder/room.rb
10
+ lib/tinder/version.rb
@@ -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