firering 0.1.1 → 1.0.0

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.
@@ -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