ucengine 0.1.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.
data/lib/ucengine.rb ADDED
@@ -0,0 +1,192 @@
1
+ require 'json'
2
+
3
+ require 'net/http'
4
+ require 'cgi'
5
+
6
+ # ucengine.rb implements the UCEngine API, it can currently handle
7
+ # publish/subscribe to any event stream.
8
+ #
9
+ # Author:: Victor Goya (victor.goya@af83.com)
10
+ # Copyright:: Copyright (c) 2010 AF83
11
+ # License:: LGPL
12
+ # Website:: http://ucengine.org/
13
+
14
+ # This class is the main and only class in ucengine.rb, it handles
15
+ # connections and request to the UCEngine server.
16
+ #
17
+ # uce = UCEngine.new("localhost", 4567)
18
+ # uce.connect("bibi", :password => 'abcd') do |uce|
19
+ # uce.subscribe(["af83"], :type => 'chat.message.new', :search => 'HTML5') do |event|
20
+ # uce.push(:location => [event['org'], event['meeting']]
21
+ # :from => 'bot',
22
+ # :type => 'chat.message.new',
23
+ # :metadata => {"text" => "Hey, you were talking about HTML5"})
24
+ # end
25
+ # end
26
+ class UCEngine
27
+
28
+ # Print every request and everything above.
29
+ DEBUG = 0
30
+ # Print everything that seems fishy.
31
+ WARNING = 1
32
+ # Print regular errors, usually HTTP errors.
33
+ ERROR = 2
34
+ # Only print critical errors (bad hostname or port, etc).
35
+ CRITICAL = 3
36
+ # Don't print anything (default).
37
+ QUIET = 4
38
+
39
+ # Create a new UCEngine object. 'host' is the hostname of the UCEngine server
40
+ # and 'port' is to TCP port to connect to. Note that this method doesn't create
41
+ # a new connection, see the #connect method.
42
+ # An additional 'debug' parameter set the debug level of the library, all the
43
+ # debug information are written in the error output.
44
+ def initialize(host, port, debug = UCEngine::QUIET)
45
+ @host = host
46
+ @port = port
47
+ @http = Net::HTTP.new(host, port)
48
+ @threads = []
49
+ @debug = debug
50
+ debug(UCEngine::DEBUG, "Initialisation complete for #{host}:#{port}.")
51
+ end
52
+
53
+ # Connect to the UCEngine server with the User ID 'uid' and the its credential.
54
+ #
55
+ #
56
+ # uce = UCEngine.new("localhost", 4567)
57
+ # uce.connect("bibi", :password => 'abcd') do |uce|
58
+ # ... your code goes here
59
+ # end
60
+ #
61
+ # It is currently possible to use :token or :password as authentification method.
62
+ def connect(uid, credential)
63
+ @uid = uid
64
+ response = put("/presence/#{@uid}", {:auth => 'token', :credential => credential[:token]})
65
+ @sid = response['result']
66
+ debug(UCEngine::DEBUG, "Authentification complete for #{@uid}/#{@sid}.")
67
+ yield self
68
+ @threads.each do |thread|
69
+ thread.join
70
+ end
71
+ end
72
+
73
+ # Subscribe to an event stream. The 'location' parameter is where you're expecting
74
+ # the events to come:
75
+ # * ["organisation", "meeting"]: events from a specific meeting.
76
+ # * ["organisation"]: events from all meetings of the organisation and for the organisation itself.
77
+ # * []: all events.
78
+ #
79
+ # The function takes extra parameters:
80
+ # :type => the type of event (ex. 'chat.message.new', 'internal.user.add', etc).
81
+ # :from => the origin of the message, the value is an uid.
82
+ # :parent => the id of the the parent event.
83
+ # :search => list of keywords that match the metadata of the returned events
84
+ #
85
+ #
86
+ # uce.subscribe(["af83"], :type => 'internal.meeting.add', :search => 'HTML5') do |event|
87
+ # puts "A new meeting about HTML5 was created"
88
+ # end
89
+ def subscribe(location, params = {})
90
+ debug(UCEngine::DEBUG, "Subscribe to #{location} with #{params}.")
91
+ @threads << Thread.new do
92
+ Net::HTTP.start(@host, @port) do |http|
93
+ params[:_async] = "lp"
94
+ params[:start] = 0 if !params[:start]
95
+ while true
96
+ begin
97
+ events = get("/event/#{location.join("/")}", params, http)['result']
98
+ rescue Timeout::Error
99
+ debug(UCEngine::WARNING, "Subscribe timeout ... retry")
100
+ retry
101
+ rescue EOFError
102
+ debug(UCEngine::WARNING, "Subscribe closed ... retry")
103
+ sleep 10
104
+ retry
105
+ end
106
+ events.each do |event|
107
+ yield event
108
+ end
109
+ params[:start] = events[-1]['datetime'] + 1
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ # Publish an event. Publishing an event require a few mandatories parameters:
116
+ # [:location] As described in the subscribe method: ["organisation", "meeting"] publish the event in a specific meeting, ["organisation"] publish the event in the organisation and []: publish the event in the server root.
117
+ # [:type] The type of event to send, the format of this type is usually 'namespace.object.action', for example: 'chat.message.new', 'twitter.tweet.new', 'internal.user.update'
118
+ # [:parent] The id of the parent, this parameter is useful to build event hierarchy.
119
+ # [:metadata] A hash of freely defined values to append to the event.
120
+ #
121
+ # uce.publish(:location => ["af83", "WebWorkersCamp"],
122
+ # :type => 'presentation.slide.add'
123
+ # :metadata => {:url => 'http://myserver/slides/03.png',
124
+ # :index => 3})
125
+ def publish(event)
126
+ debug(UCEngine::DEBUG, "Publish to #{event[:location]}, type: #{event[:type]}, parent: #{event[:parent]}, metadata: #{event[:metadata]}")
127
+ params = Hash.new
128
+ params[:type] = event[:type]
129
+ params[:parent] = event[:parent] if event[:parent]
130
+ if event[:metadata]
131
+ event[:metadata].each_key do |key|
132
+ params["metadata[#{key}]"] = event[:metadata][key]
133
+ end
134
+ end
135
+ put("/event/#{event[:location].join("/")}", params)
136
+ end
137
+
138
+ # Return the current timestamp from the server. The timestamp is expressed in milliseconds
139
+ # from Epoch (january 1st 1970).
140
+ # This function can be useful if you need to search for events from _now_.
141
+ #
142
+ # uce.time -> 1240394032
143
+ #
144
+ def time
145
+ time = get("/time", Hash.new)['result'].to_i
146
+ debug(UCEngine::DEBUG, "Fecth timestamp from UCEngine: #{time}")
147
+ return time
148
+ end
149
+
150
+ protected
151
+
152
+ # Encode parameters
153
+ def UCEngine.encode(params)
154
+ params.collect { |k,v| "#{k}=#{CGI::escape(v.to_s)}" }.join('&')
155
+ end
156
+
157
+ # Print debug messages
158
+ def debug(level, message)
159
+ $stderr.write("#{message}\n\n") if level >= @debug
160
+ end
161
+
162
+ # Handle GET requests
163
+ def get(path, params, http = @http)
164
+ params[:uid] = @uid if @uid
165
+ params[:sid] = @sid if @sid
166
+ result = JSON.parse(http.get("/api/0.1/#{path}?#{UCEngine.encode(params)}").body)
167
+ debug(UCEngine::DEBUG, "Request: GET /api/0.1/#{path}?#{UCEngine.encode(params)}\nResult: #{result}")
168
+ return result
169
+ end
170
+
171
+ # Handle POST requests
172
+ def post(path, params, http = @http)
173
+ params[:uid] = @uid if @uid
174
+ params[:sid] = @sid if @sid
175
+ result = JSON.parse(http.post("/api/0.1/#{path}", UCEngine.encode(params)).body)
176
+ debug(UCEngine::DEBUG, "Request: POST /api/0.1/#{path}?#{UCEngine.encode(params)}\nResult: #{result}")
177
+ return result
178
+ end
179
+
180
+ # Handle PUT requests
181
+ def put(path, params)
182
+ params['_method'] = "PUT"
183
+ post(path, params)
184
+ end
185
+
186
+ # Handle DELETE requests
187
+ def delete(path, params)
188
+ params['_method'] = "DELETE"
189
+ post(path, params)
190
+ end
191
+
192
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'ucengine.rb'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestUcengine < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,57 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{ucengine.rb}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["AF83"]
12
+ s.date = %q{2010-11-23}
13
+ s.description = %q{ucengine.rb is a Ruby library to consume the UCEngine API}
14
+ s.email = %q{victor.goya@af83.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/ucengine.rb",
27
+ "test/helper.rb",
28
+ "test/test_ucengine.rb.rb",
29
+ "ucengine.rb.gemspec"
30
+ ]
31
+ s.homepage = %q{http://github.com/AF83/ucengine.rb}
32
+ s.rdoc_options = ["--charset=UTF-8"]
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = %q{1.3.7}
35
+ s.summary = %q{Ruby library for UCEngine}
36
+ s.test_files = [
37
+ "test/helper.rb",
38
+ "test/test_ucengine.rb.rb"
39
+ ]
40
+
41
+ if s.respond_to? :specification_version then
42
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
43
+ s.specification_version = 3
44
+
45
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
47
+ s.add_runtime_dependency(%q<json>, [">= 0"])
48
+ else
49
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
50
+ s.add_dependency(%q<json>, [">= 0"])
51
+ end
52
+ else
53
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
54
+ s.add_dependency(%q<json>, [">= 0"])
55
+ end
56
+ end
57
+
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ucengine
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - AF83
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-01 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: thoughtbot-shoulda
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :development
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: json
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ description: ucengine.rb is a Ruby library to consume the UCEngine API
47
+ email: victor.goya@af83.com
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - LICENSE
54
+ - README.rdoc
55
+ files:
56
+ - .document
57
+ - .gitignore
58
+ - LICENSE
59
+ - README.rdoc
60
+ - Rakefile
61
+ - VERSION
62
+ - doc/UCEngine.html
63
+ - doc/UCEngine/Debug.html
64
+ - doc/created.rid
65
+ - doc/images/brick.png
66
+ - doc/images/brick_link.png
67
+ - doc/images/bug.png
68
+ - doc/images/bullet_black.png
69
+ - doc/images/bullet_toggle_minus.png
70
+ - doc/images/bullet_toggle_plus.png
71
+ - doc/images/date.png
72
+ - doc/images/find.png
73
+ - doc/images/loadingAnimation.gif
74
+ - doc/images/macFFBgHack.png
75
+ - doc/images/package.png
76
+ - doc/images/page_green.png
77
+ - doc/images/page_white_text.png
78
+ - doc/images/page_white_width.png
79
+ - doc/images/plugin.png
80
+ - doc/images/ruby.png
81
+ - doc/images/tag_green.png
82
+ - doc/images/wrench.png
83
+ - doc/images/wrench_orange.png
84
+ - doc/images/zoom.png
85
+ - doc/index.html
86
+ - doc/js/darkfish.js
87
+ - doc/js/jquery.js
88
+ - doc/js/quicksearch.js
89
+ - doc/js/thickbox-compressed.js
90
+ - doc/lib/ucengine_rb.html
91
+ - doc/rdoc.css
92
+ - lib/ucengine.rb
93
+ - test/helper.rb
94
+ - test/test_ucengine.rb
95
+ - ucengine.rb.gemspec
96
+ has_rdoc: true
97
+ homepage: http://github.com/AF83/ucengine.rb
98
+ licenses: []
99
+
100
+ post_install_message:
101
+ rdoc_options:
102
+ - --charset=UTF-8
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ segments:
111
+ - 0
112
+ version: "0"
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ segments:
119
+ - 0
120
+ version: "0"
121
+ requirements: []
122
+
123
+ rubyforge_project:
124
+ rubygems_version: 1.3.7
125
+ signing_key:
126
+ specification_version: 3
127
+ summary: Ruby library for UCEngine
128
+ test_files:
129
+ - test/helper.rb
130
+ - test/test_ucengine.rb