firering 0.1.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,13 +1,120 @@
1
- module Firering
2
- class Room < Firering::Data
3
- key :id, :name, :topic, :membership_limit, :full, :open_to_guests, :active_token_value, :updated_at, :created_at, :users, :locked
1
+ class Firering::Room < Firering::Data
4
2
 
5
- alias_method :locked?, :locked
6
- alias_method :full?, :full
7
- alias_method :open_to_guests?, :open_to_guests
3
+ data_attributes :id, :name, :topic, :membership_limit, :full, :open_to_guests,
4
+ :active_token_value, :updated_at, :created_at, :users, :locked
8
5
 
9
- def users
10
- @users ||= (super || []).map { |u| Firering::User.new(u, false) }
6
+ alias_method :locked?, :locked
7
+ alias_method :full?, :full
8
+ alias_method :open_to_guests?, :open_to_guests
9
+
10
+ def stream(&callback)
11
+ join { |data, http| connection.stream(id, &callback) }
12
+ end
13
+
14
+ # we perform a request each time so
15
+ # 1) we always are are up to date with the users currently on the room (even if some left)
16
+ # 2) we make sure the users are here even if the room was instantiated from a
17
+ # /rooms request
18
+ def users(&callback)
19
+ connection.http(:get, "/room/#{id}.json") do |data, http| # data can be blank on locked rooms
20
+ callback.call(data ? data[:room][:users].map { |user| Firering::User.instantiate(self, user) } : Array.new) if callback
21
+ end
22
+ end
23
+
24
+ # Updates an existing room. Only admins can rename a room, although any
25
+ # user (except guests) may set the topic. Omitting either key results in
26
+ # that attribute being ignored. To remove a room topic, simply provide an
27
+ # empty topic key.
28
+ #
29
+ # update "name" => "Name", "topic" => "Topic"
30
+ def update(data, &callback)
31
+ connection.http(:put, "/room/#{id}.json", { :room => data }, &callback)
32
+ end
33
+
34
+ # Returns a collection of upto 100 recent messages in the room. Accepts an
35
+ # additional optional parameter ‘limit’ to restrict the number of messages
36
+ # returned.
37
+ def recent_messages(limit = nil, &callback)
38
+ connection.http(:get, "/room/#{id}/recent.json", (limit ? { :limit => limit } : nil)) do |data, http|
39
+ callback.call(data[:messages].map { |msg| Firering::Message.instantiate(connection, msg) }) if callback
11
40
  end
12
41
  end
42
+
43
+ # Returns all the messages sent today to a room.
44
+ def today_transcript(&callback)
45
+ connection.http(:get, "/room/#{id}/transcript.json") do |data, http|
46
+ callback.call(data[:messages].map { |msg| Firering::Message.instantiate(connection, msg) }) if callback
47
+ end
48
+ end
49
+
50
+ # Returns all the messages sent on a specific date to a room.
51
+ def transcript(year, month, day, &callback)
52
+ connection.http(:get, "/room/#{id}/transcript/#{year}/#{month}/#{day}.json") do |data, http|
53
+ callback.call(data[:messages].map { |msg| Firering::Message.instantiate(connection, msg) }) if callback
54
+ end
55
+ end
56
+
57
+ # Join a room.
58
+ def join(&callback)
59
+ connection.http(:post, "/room/#{id}/join.json", &callback)
60
+ end
61
+
62
+ # Leave a room.
63
+ def leave(&callback)
64
+ connection.http(:post, "/room/#{id}/leave.json", &callback)
65
+ end
66
+
67
+ # Locks a room.
68
+ def lock(&callback)
69
+ connection.http(:post, "/room/#{id}/lock.json", &callback)
70
+ end
71
+
72
+ # Unlocks a room.
73
+ def unlock(&callback)
74
+ connection.http(:post, "/room/#{id}/unlock.json", &callback)
75
+ end
76
+
77
+ # Sends a new message with the currently authenticated user as the sender.
78
+ # The XML for the new message is returned on a successful request.
79
+ #
80
+ # The valid types are:
81
+ #
82
+ # * TextMessage (regular chat message)
83
+ # * PasteMessage (pre-formatted message, rendered in a fixed-width font)
84
+ # * SoundMessage (plays a sound as determined by the message, which can be either “rimshot”, “crickets”, or “trombone”)
85
+ # * TweetMessage (a Twitter status URL to be fetched and inserted into the chat)
86
+ #
87
+ # If an explicit type is omitted, it will be inferred from the content (e.g.,
88
+ # if the message contains new line characters, it will be considered a paste).
89
+ #
90
+ # :type => "TextMessage", :body => "Hello"
91
+ def speak(data, &callback)
92
+ connection.http(:post, "/room/#{id}/speak.json", "message" => data) do |data, http| # Response Status: 201 Created
93
+ callback.call(Firering::Message.instantiate(connection, data))
94
+ end
95
+ end
96
+
97
+ def text(text, &callback)
98
+ speak({:type => "TextMessage", :body => text}, &callback)
99
+ end
100
+
101
+ def paste(paste, &callback)
102
+ speak({:type => "PasteMessage", :body => paste}, &callback)
103
+ end
104
+
105
+ def rimshot(&callback)
106
+ speak({:type => "SoundMessage", :body => "rimshot"}, &callback)
107
+ end
108
+
109
+ def crickets(&callback)
110
+ speak({:type => "SoundMessage", :body => "crickets"}, &callback)
111
+ end
112
+
113
+ def trombone(&callback)
114
+ speak({:type => "SoundMessage", :body => "trombone"}, &callback)
115
+ end
116
+
117
+ def tweet(tweet_url, &callback)
118
+ speak({:type => "TweetMessage", :body => tweet_url}, &callback)
119
+ end
13
120
  end
@@ -1,5 +1,6 @@
1
- module Firering
2
- class Upload < Firering::Data
3
- key :id, :name, :room_id, :user_id, :byte_size, :content_type, :full_url, :created_at
4
- end
1
+ class Firering::Upload < Firering::Data
2
+
3
+ data_attributes :id, :name, :room_id, :user_id, :byte_size, :content_type,
4
+ :full_url, :created_at
5
+
5
6
  end
@@ -1,16 +1,18 @@
1
- module Firering
2
- class User < Firering::Data
3
- key :id, :name, :email_address, :admin, :created_at, :type, :api_auth_token
1
+ class Firering::User < Firering::Data
4
2
 
5
- alias_method :token, :api_auth_token
6
- alias_method :admin?, :admin
3
+ data_attributes :id, :name, :email_address, :admin, :created_at, :type,
4
+ :api_auth_token
7
5
 
8
- def member?
9
- type == "Member"
10
- end
6
+ alias_method :token, :api_auth_token
7
+ alias_method :admin?, :admin
11
8
 
12
- def gest?
13
- type == "Guest"
14
- end
9
+ def member?
10
+ type == "Member"
15
11
  end
12
+
13
+ def gest?
14
+ type == "Guest"
15
+ end
16
+
17
+ alias_method :to_s, :name
16
18
  end
data/lib/firering/data.rb CHANGED
@@ -1,35 +1,42 @@
1
1
  module Firering
2
2
  class Data
3
+ # Generates methods to access the data stored in the @data Hash
4
+ def self.data_attributes(*keys)
5
+ include Module.new {
6
+ keys.each do |key|
7
+ module_eval <<-CODE, __FILE__, __LINE__
8
+ def #{key}
9
+ @_attributes[#{key.to_sym.inspect}]
10
+ end
11
+ CODE
12
+ end
13
+ }
14
+ end
3
15
 
4
- # generates methods to access the data stored in the @data Hash
5
- def self.key(*keys)
6
- methods = keys.map do |key|
7
- <<-CODE
8
- def #{key}
9
- @data[#{key.to_sym.inspect}]
10
- end
11
- CODE
12
- end
16
+ attr_accessor :connection
13
17
 
14
- include(Module.new do
15
- module_eval methods.join("\n"), __FILE__, __LINE__
16
- end)
18
+ # factory method to instantiate data classes
19
+ def self.instantiate(conn, data, base_key= nil, &callback)
20
+ instance = new
21
+ instance.connection = conn
22
+ instance.initialize_attributes(data, base_key)
23
+ callback.call(instance) if callback
24
+ instance
17
25
  end
18
26
 
19
27
  # data is a hash or a json encoded hash (String)
20
28
  # base_key if present is the main data key on the hash.
21
- def initialize(data, base_key = nil)
22
- @data = data.is_a?(Hash) ? data : Yajl::Parser.parse(data, :symbolize_keys => true)
23
- @data = @data[base_key] if base_key
29
+ def initialize_attributes(data, base_key = nil)
30
+ @_attributes = data.is_a?(Hash) ? data : Yajl::Parser.parse(data, :symbolize_keys => true)
31
+ @_attributes = @_attributes[base_key] if base_key
24
32
 
25
- @data.each do |key, val|
26
- @data[key] = Date.parse(val) rescue val if key.to_s =~ /(_at|_on)$/
33
+ @_attributes.each do |key, val|
34
+ @_attributes[key] = Date.parse(val) rescue val if key.to_s =~ /(_at|_on)$/
27
35
  end
28
36
  end
29
37
 
30
38
  def inspect
31
- "<#{self.class.name} #{@data.inspect}>"
39
+ "<#{self.class.name} #{@_attributes.inspect}>"
32
40
  end
33
-
34
41
  end
35
42
  end
@@ -1,185 +1,49 @@
1
1
  module Firering
2
- include Firering::HTTP
3
- include Firering::Streaming
2
+ module Requests
4
3
 
5
- extend self
6
-
7
- attr_accessor :token, :subdomain
8
-
9
- # calls /users/me route on campfire to get the authenticated user information, including token
10
- def authenticate(subdomain, user, password, &block)
11
- Firering.subdomain = subdomain
12
- user("me", user, password) do |user|
13
- Firering.token = user.token
14
- block.call(user)
15
- end
16
- end
17
-
18
- # non default user and password parameters are only used when user id is "me"
19
- # to authenticate the user and get his auth token.
20
- def user(id, user = Firering.token, password = "X", &block)
21
- http(:get, "/users/#{id}.json", nil, user, password) do |http|
22
- user = Firering::User.new(http.response, :user)
23
- block.call(user)
24
- end
25
- end
26
-
27
- # returns all rooms. For getting the users, each specific room must be queries with Firering.room
28
- # multi: if true, gets all the users from each room as Firering::User objects
29
- def rooms(multi = true, &block)
30
- http(:get, "/rooms.json") do |http|
31
-
32
- rooms = Yajl::Parser.parse(http.response, :symbolize_keys => true)[:rooms]
33
- rooms.map! { |room| Firering::Room.new(room) }
34
-
35
- if multi
36
- rooms_multi(rooms, &block)
37
- else
38
- block.call(rooms)
4
+ # Calls /users/me route on campfire to get the authenticated user information, including token
5
+ def authenticate(&callback)
6
+ user("me") do |user|
7
+ self.token = user.token
8
+ callback.call(user)
39
9
  end
40
10
  end
41
- end
42
-
43
- # helper for returning all rooms with all existing users (saves the step of going through each room)
44
- def rooms_multi(rooms, &block)
45
- multi = EventMachine::MultiRequest.new
46
- final_rooms = []
47
11
 
48
- rooms.each do |room|
49
- if room.locked? # can't retrieve aditional info on a locked room.
50
- final_rooms << room
51
- else
52
- multi.add(room(room.id) { |req_room| final_rooms << req_room })
12
+ # returns a user by id
13
+ def user(id, &callback)
14
+ http(:get, "/users/#{id}.json") do |data, http|
15
+ Firering::User.instantiate(self, data, :user, &callback)
53
16
  end
54
17
  end
55
18
 
56
- multi.callback { block.call(final_rooms) }
57
- end
58
-
59
- # Returns an existing room. Also includes all the users currently inside the room.
60
- def room(id, &block)
61
- http(:get, "/room/#{id}.json") do |http|
62
- room = Firering::Room.new(http.response, :room)
63
- block.call(room)
64
- end
65
- end
66
-
67
- # Updates an existing room. Only admins can rename a room, although any
68
- # user (except guests) may set the topic. Omitting either tag results in
69
- # that attribute being ignored. To remove a room topic, simply provide an
70
- # empty topic tag.
71
- #
72
- # update_room "1", "name" => "Name", "topic" => "Topic"
73
- def update_room(id, data, &block)
74
- http(:put, "/room/#{id}.json", { :room => data }, &block)
75
- end
76
-
77
- # Returns a collection of upto 100 recent messages in the room. Accepts an
78
- # additional optional parameter ‘limit’ to restrict the number of messages
79
- # returned.
80
- def room_recent_messages(id, limit = nil, &block)
81
- http(:get, "/room/#{id}/recent.json", (limit ? { :limit => limit } : nil)) do |http|
82
- messages = Yajl::Parser.parse(http.response, :symbolize_keys => true)[:messages]
83
- messages.map! { |msg| Firering::Message.new(msg) }
84
- block.call(messages)
85
- end
86
- end
87
-
88
- # Returns all the messages containing the supplied term.
89
- def search_messages(query, &block)
90
- http(:get, "/search/#{query}.json") do |http|
91
- messages = Yajl::Parser.parse(http.response, :symbolize_keys => true)[:messages]
92
- messages.map! { |msg| Firering::Message.new(msg) }
93
- block.call(messages)
19
+ # returns a room by id
20
+ def room(id, &callback)
21
+ http(:get, "/room/#{id}.json") do |data, http|
22
+ Firering::Room.instantiate(self, data, :room, &callback)
23
+ end
94
24
  end
95
- end
96
25
 
97
- # Returns all the messages sent today to a room.
98
- def today_messages(room_id, &block)
99
- http(:get, "/room/#{room_id}/transcript.json") do |http|
100
- messages = Yajl::Parser.parse(http.response, :symbolize_keys => true)[:messages]
101
- messages.map! { |msg| Firering::Message.new(msg) }
102
- block.call(messages)
26
+ # Returns all rooms. For getting the users, each specific room must be queries with Firering.room
27
+ # multi: if true, gets all the users from each room as Firering::User objects
28
+ def rooms(&callback)
29
+ http(:get, "/rooms.json") do |data, http|
30
+ callback.call(data[:rooms].map{|room| Firering::Room.instantiate(self, room)}) if callback
31
+ end
103
32
  end
104
- end
105
33
 
106
- # Returns all the messages sent on a specific date to a room.
107
- def messages_on(room_id, year, month, day, &block)
108
- http(:get, "/room/#{room_id}/transcript/#{year}/#{month}/#{day}.xml") do |http|
109
- messages = Yajl::Parser.parse(http.response, :symbolize_keys => true)[:messages]
110
- messages.map! { |msg| Firering::Message.new(msg) }
111
- block.call(messages)
34
+ # Returns all the messages containing the supplied term.
35
+ def search_messages(query, &callback)
36
+ http(:get, "/search/#{query}.json") do |data, http|
37
+ callback.call(data[:messages].map { |msg| Firering::Message.instantiate(self, msg) }) if callback
38
+ end
112
39
  end
113
- end
114
-
115
- # Join a room.
116
- def room_join(room_id, &block)
117
- http(:post, "/room/#{room_id}/join.json", &block)
118
- end
119
40
 
120
- # Leave a room.
121
- def room_leave(room_id, &block)
122
- http(:post, "/room/#{room_id}/leave.json", &block)
123
- end
124
-
125
- # Locks a room.
126
- def room_lock(room_id, &block)
127
- http(:post, "/room/#{room_id}/lock.json", &block)
128
- end
129
-
130
- # Unlocks a room.
131
- def room_unlock(room_id, &block)
132
- http(:post, "/room/#{room_id}/unlock.json", &block)
133
- end
134
-
135
- # Sends a new message with the currently authenticated user as the sender.
136
- # The XML for the new message is returned on a successful request.
137
- #
138
- # The valid types are:
139
- #
140
- # * TextMessage (regular chat message)
141
- # * PasteMessage (pre-formatted message, rendered in a fixed-width font)
142
- # * SoundMessage (plays a sound as determined by the message, which can be either “rimshot”, “crickets”, or “trombone”)
143
- # * TweetMessage (a Twitter status URL to be fetched and inserted into the chat)
144
- #
145
- # If an explicit type is omitted, it will be inferred from the content (e.g.,
146
- # if the message contains new line characters, it will be considered a paste).
147
- #
148
- # :type => "TextMessage", :body => "Hello"
149
- def speak(room_id, data, &block)
150
- # Response Status: 201 Created
151
- http(:post, "/room/#{room_id}/speak.json", "message" => data) do |http|
152
- block.call(Firering::Message.new(http.response))
41
+ # Toggles the star next to a message
42
+ def star_message(id, yes_or_no = true, &callback)
43
+ http(yes_or_no ? :post : :delete, "/messages/#{id}/star.json") do |data, http|
44
+ callback.call(data) if callback
45
+ end
153
46
  end
154
- end
155
47
 
156
- def text(room_id, text, &block)
157
- speak(room_id, {:type => "TextMessage", :body => text}, &block)
158
48
  end
159
-
160
- def paste(room_id, paste, &block)
161
- speak(room_id, {:type => "PasteMessage", :body => paste}, &block)
162
- end
163
-
164
- def rimshot(room_id, &block)
165
- speak(room_id, {:type => "SoundMessage", :body => "rimshot"}, &block)
166
- end
167
-
168
- def crickets(room_id, &block)
169
- speak(room_id, {:type => "SoundMessage", :body => "crickets"}, &block)
170
- end
171
-
172
- def trombone(room_id, &block)
173
- speak(room_id, {:type => "SoundMessage", :body => "trombone"}, &block)
174
- end
175
-
176
- def tweet(room_id, tweet_url, &block)
177
- speak(room_id, {:type => "TweetMessage", :body => tweet_url}, &block)
178
- end
179
-
180
- # Highlights a message / Removes a message highlight.
181
- def highlight_message(message_id, yes_or_no = true, &block)
182
- http(yes_or_no ? :post : :delete, "/messages/#{message_id}/star.json", &block)
183
- end
184
-
185
49
  end
data/lib/firering.rb CHANGED
@@ -1,21 +1,20 @@
1
+ require 'logger'
2
+ require 'date'
1
3
  require 'eventmachine'
2
4
  require 'yajl'
3
5
  require 'em-http'
4
- require 'date'
5
6
 
6
7
  module Firering
7
- VERSION = '0.1.1'
8
+ VERSION = '1.0.0'
8
9
 
9
10
  class Error < StandardError; end
10
11
 
11
- autoload :Data , "firering/data"
12
+ autoload :Requests , "firering/requests"
13
+ autoload :Connection , "firering/connection"
12
14
 
13
- autoload :User , "firering/data/user"
14
- autoload :Message , "firering/data/message"
15
- autoload :Room , "firering/data/room"
16
- autoload :Upload , "firering/data/upload"
15
+ autoload :Data , "firering/data"
16
+ autoload :User , "firering/data/user"
17
+ autoload :Message , "firering/data/message"
18
+ autoload :Room , "firering/data/room"
19
+ autoload :Upload , "firering/data/upload"
17
20
  end
18
-
19
- require 'firering/http'
20
- require 'firering/streaming'
21
- require 'firering/requests'
data/log/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe Firering::Connection do
4
+
5
+ it "authenticates a user" do
6
+ EM.run {
7
+ conn.authenticate do |user|
8
+ user.token.should == "token"
9
+ EM.stop
10
+ end
11
+ }
12
+ end
13
+
14
+ it "stream messages" do
15
+ EM.run {
16
+ conn.stream(304355) do |message|
17
+ message.should be_an_instance_of(Firering::Message)
18
+ end
19
+ EM.add_timer(1) do
20
+ EM.stop
21
+ end
22
+ }
23
+ end
24
+
25
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe Firering::Message do
4
+
5
+ it "gets a collection of recent messages" do
6
+ EM.run {
7
+ conn.room(304355) do |room|
8
+ room.recent_messages do |messages|
9
+
10
+ messages.each do |m|
11
+ m.should be_an_instance_of(Firering::Message)
12
+ end
13
+
14
+ message = messages.first
15
+ message.should be_timestamp
16
+ message.room_id.should == 304355
17
+ message.created_at.should == Date.parse("2010/05/29 22:05:00 +0000")
18
+ message.body.should be_nil
19
+ message.id.should == 224587718
20
+ message.user_id.should be_nil
21
+
22
+ EM.stop
23
+
24
+ end
25
+ end
26
+ }
27
+ end
28
+
29
+ it "returns a collection of messages matching certain pattern" do
30
+ EM.run {
31
+ conn.search_messages("harmless") do |messages|
32
+ messages.length.should == 3
33
+
34
+ messages.each do |m|
35
+ m.should be_an_instance_of(Firering::Message)
36
+ end
37
+
38
+ message = messages.last
39
+ message.should be_text
40
+ message.room_id.should == 177718
41
+ message.created_at.should == Date.parse("2009/06/02 21:20:32 +0000")
42
+ message.body.should == "q: should i add :case_sensitive =\u003E false to the validation of title name? Looks harmless but who knows..."
43
+ message.id.should == 134405854
44
+ message.user_id.should == 415731
45
+
46
+ EM.stop
47
+ end
48
+ }
49
+ end
50
+
51
+ it "is able to star / un-star a message" do
52
+ EM.run {
53
+ conn.star_message(224590113) {
54
+ conn.star_message(224590113, false) {
55
+ EM.stop
56
+ }
57
+ }
58
+ }
59
+ end
60
+
61
+ end