spinderella-client 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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Darcy Laycock
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ = spinderella-client
2
+
3
+ A set of client libraries for spinderella.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Darcy Laycock. See LICENSE for details.
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "spinderella-client"
8
+ gem.summary = %Q{A Simple, Synchronous TCPSocket client for Spinderella}
9
+ gem.description = %Q{A client library for spinderella (http://github.com/Sutto/spinderella)}
10
+ gem.email = "sutto@sutto.net"
11
+ gem.homepage = "http://github.com/Sutto/spinderella-client"
12
+ gem.authors = ["Darcy Laycock"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.add_dependency "perennial", ">= 1.2.4"
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "spinderella-client #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), 'spinderella', 'client')
@@ -0,0 +1,9 @@
1
+ lib_path = File.expand_path(File.dirname(File.dirname(__FILE__)))
2
+ $LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include?(lib_path)
3
+
4
+ module Spinderella
5
+ module Client
6
+ autoload :Broadcaster, 'spinderella/client/broadcaster'
7
+ autoload :Subscriber, 'spinderella/client/subscriber'
8
+ end
9
+ end
@@ -0,0 +1,96 @@
1
+ require 'perennial/protocols/pure_ruby/json_transport'
2
+ require 'thread'
3
+
4
+ module Spinderella
5
+ module Client
6
+ class Broadcaster < Perennial::Protocols::PureRuby::JSONTransport
7
+
8
+ def initialize(options = {})
9
+ @authenticated = false
10
+ @auth_callback = []
11
+ @options = options
12
+ @host = (options[:host] || "localhost").to_s
13
+ @port = (options[:port] || 42341).to_i
14
+ @timeout = (options[:timeout] || 15).to_f
15
+ @read_timeout = (options[:read_timeout] || 5).to_f
16
+ @token = options[:token]
17
+ @mutex = Mutex.new
18
+ authenticate(@token) if @token
19
+ end
20
+
21
+ def authenticate(token)
22
+ write_message(:authenticate, :token => token)
23
+ action, payload = read_message(@timeout)
24
+ @authenticated = (action == "authenticated")
25
+ if @authenticated
26
+ @auth_callback.each { |b| b.call }
27
+ @auth_callback = []
28
+ end
29
+ @authenticated
30
+ rescue NoConnection
31
+ @authenticated = false
32
+ return false
33
+ end
34
+
35
+ def authenticated?
36
+ !!@authenticated
37
+ end
38
+
39
+ def close
40
+ super
41
+ @authenticated = false
42
+ end
43
+
44
+ def broadcast_to_all(message)
45
+ once_authenticated do
46
+ write_message :broadcast, "type" => "all", "message" => message.to_s
47
+ end
48
+ end
49
+
50
+ def broadcast_to_users(message, users)
51
+ once_authenticated do
52
+ write_message :broadcast, "type" => "users", "message" => message.to_s,
53
+ "users" => Array(users).map { |u| u.to_s }
54
+ end
55
+ end
56
+
57
+ def broadcast_to_channels(message, channels)
58
+ once_authenticated do
59
+ write_message :broadcast, "type" => "channels", "message" => message.to_s,
60
+ "channels" => Array(channels).map { |c| c.to_s }
61
+ end
62
+ end
63
+
64
+ def broadcast_to_channel(message, channel)
65
+ once_authenticated do
66
+ write_message :broadcast, "type" => "channel", "message" => message.to_s, "channel" => channel.to_s
67
+ end
68
+ end
69
+
70
+ def inspect
71
+ "#<#{self.class.name} authenticated=#{authenticated?}, host=\"#{@host}:#{@port}\" connected=#{alive?}>"
72
+ end
73
+
74
+ protected
75
+
76
+ def once_authenticated(&blk)
77
+ if authenticated?
78
+ blk.call
79
+ else
80
+ @auth_callback << blk
81
+ end
82
+ nil
83
+ end
84
+
85
+ def write_message(name, data = {})
86
+ @mutex.synchronize { super }
87
+ end
88
+
89
+ def read_message(timeout = nil)
90
+ @mutex.synchronize { super }
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,115 @@
1
+ require 'perennial/protocols/pure_ruby/json_transport'
2
+ require 'thread'
3
+
4
+ module Spinderella
5
+ module Client
6
+ class Subscriber < Perennial::Protocols::PureRuby::JSONTransport
7
+
8
+ attr_writer :should_stop
9
+
10
+ def initialize(options = {})
11
+ @options = options
12
+ @host = (options[:host] || "localhost").to_s
13
+ @port = (options[:port] || 42340).to_i
14
+ @timeout = (options[:timeout] || 15).to_f
15
+ @read_timeout = (options[:read_timeout] || 5).to_f
16
+ @callbacks = {}
17
+ @mutex = Mutex.new
18
+ @should_stop = false
19
+ end
20
+
21
+ def subscribe(*channels)
22
+ write_message :subscribe, :channels => Array(channels)
23
+ true
24
+ end
25
+
26
+ def unsubscribe(*channels)
27
+ write_message :unsubscribe, :channels => Array(channels)
28
+ true
29
+ end
30
+
31
+ def identify(identifier)
32
+ write_message :identify, :identifier => identifier
33
+ true
34
+ end
35
+
36
+ def channels
37
+ write_message :channels
38
+ action, payload = read_message(@read_timeout)
39
+ if action == "channels"
40
+ Array(payload["channels"])
41
+ else
42
+ []
43
+ end
44
+ end
45
+
46
+ def watch
47
+ loop do
48
+ action, payload = read_message(@read_timeout)
49
+ # When action is nil, it means there is nothing to read yet.
50
+ case action
51
+ when "ping"
52
+ write_message :pong
53
+ when "disconnected"
54
+ @should_stop = true
55
+ close
56
+ when "receive_message"
57
+ process_message(payload)
58
+ end
59
+ break if @should_stop
60
+ # In the case we didn't receive data, sleep for half a second
61
+ # so as not to steal all of the available CPU.
62
+ sleep 0.5 if action.nil?
63
+ end
64
+ end
65
+
66
+ def on_user(&blk)
67
+ (@callbacks[:user] ||= []) << blk
68
+ true
69
+ end
70
+
71
+ def on_channels(*channels, &blk)
72
+ channel_callbacks = @callbacks[:channels] ||= {}
73
+ (channel_callbacks[channels] ||= []) << blk
74
+ true
75
+ end
76
+
77
+ def on_broadcast(&blk)
78
+ (@callbacks[:broadcast] ||= []) << blk
79
+ true
80
+ end
81
+
82
+ def stop
83
+ @should_stop = true
84
+ end
85
+
86
+ protected
87
+
88
+ def process_message(payload)
89
+ type, message = payload["type"], payload["message"]
90
+ case type
91
+ when "user"
92
+ Array(@callbacks[:user]).each { |cb| cb.call(message) }
93
+ when "broadcast"
94
+ Array(@callbacks[:broadcast]).each { |cb| cb.call(message) }
95
+ when "channel", "channels"
96
+ channels = Array(payload["channels"] || payload["channel"])
97
+ channel_callbacks = @callbacks[:channels] ||= {}
98
+ channel_callbacks.each_pair do |c, callbacks|
99
+ p(channels & Array(c))
100
+ callbacks.each { |cb| p cb; cb.call(message) } if !(channels & Array(c)).empty?
101
+ end
102
+ end
103
+ end
104
+
105
+ def write_message(name, data = {})
106
+ @mutex.synchronize { super }
107
+ end
108
+
109
+ def read_message(timeout = nil)
110
+ @mutex.synchronize { super }
111
+ end
112
+
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,60 @@
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{spinderella-client}
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 = ["Darcy Laycock"]
12
+ s.date = %q{2010-01-03}
13
+ s.description = %q{A client library for spinderella (http://github.com/Sutto/spinderella)}
14
+ s.email = %q{sutto@sutto.net}
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/spinderella-client.rb",
27
+ "lib/spinderella/client.rb",
28
+ "lib/spinderella/client/broadcaster.rb",
29
+ "lib/spinderella/client/subscriber.rb",
30
+ "spinderella-client.gemspec",
31
+ "test/helper.rb",
32
+ "test/test_spinderella-client.rb"
33
+ ]
34
+ s.homepage = %q{http://github.com/Sutto/spinderella-client}
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.5}
38
+ s.summary = %q{A Simple, Synchronous TCPSocket client for Spinderella}
39
+ s.test_files = [
40
+ "test/helper.rb",
41
+ "test/test_spinderella-client.rb"
42
+ ]
43
+
44
+ if s.respond_to? :specification_version then
45
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
+ s.specification_version = 3
47
+
48
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
49
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
50
+ s.add_runtime_dependency(%q<perennial>, [">= 1.2.4"])
51
+ else
52
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
53
+ s.add_dependency(%q<perennial>, [">= 1.2.4"])
54
+ end
55
+ else
56
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
57
+ s.add_dependency(%q<perennial>, [">= 1.2.4"])
58
+ end
59
+ end
60
+
@@ -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 'spinderella-client'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestSpinderellaClient < 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
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spinderella-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Darcy Laycock
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-03 00:00:00 +08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: perennial
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.4
34
+ version:
35
+ description: A client library for spinderella (http://github.com/Sutto/spinderella)
36
+ email: sutto@sutto.net
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.rdoc
44
+ files:
45
+ - .document
46
+ - .gitignore
47
+ - LICENSE
48
+ - README.rdoc
49
+ - Rakefile
50
+ - VERSION
51
+ - lib/spinderella-client.rb
52
+ - lib/spinderella/client.rb
53
+ - lib/spinderella/client/broadcaster.rb
54
+ - lib/spinderella/client/subscriber.rb
55
+ - spinderella-client.gemspec
56
+ - test/helper.rb
57
+ - test/test_spinderella-client.rb
58
+ has_rdoc: true
59
+ homepage: http://github.com/Sutto/spinderella-client
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options:
64
+ - --charset=UTF-8
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ requirements: []
80
+
81
+ rubyforge_project:
82
+ rubygems_version: 1.3.5
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: A Simple, Synchronous TCPSocket client for Spinderella
86
+ test_files:
87
+ - test/helper.rb
88
+ - test/test_spinderella-client.rb