talker 0.0.1 → 0.0.2

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/README.md CHANGED
@@ -27,8 +27,8 @@ A real-time Talker Ruby client.
27
27
  # Callbacks
28
28
  All arguments are optional.
29
29
 
30
- ## <code>on_connected</code>
31
- Called when the user is authenticated and ready to receive events.
30
+ ## <code>on_connected(user)</code>
31
+ Called when the user is authenticated and ready to receive events. "user" is a Hash containing your user info: <code>{"id"=>1, "name"=>"macournoyer", "email"=>"macournoyer@talkerapp.com"}</code>.
32
32
 
33
33
  ## <code>on_presence(users)</code>
34
34
  Called after <code>on_connected</code> with the list of connected users.
@@ -37,9 +37,13 @@ With <code>users</code> being something like this:
37
37
  [{"id"=>1, "name"=>"macournoyer", "email"=>"macournoyer@talkerapp.com"},
38
38
  {"id"=>2, "name"=>"gary", "email"=>"gary@talkerapp.com"}]
39
39
 
40
- ## <code>on_message(user, message, event)</code>
40
+ ## <code>on_message(user, message)</code>
41
41
  Called when a new message is received.
42
- <code>user</code> is the sender. <code>event</code> contains the full event sent by the server.
42
+ <code>user</code> is the sender.
43
+
44
+ ## <code>on_private_message(user, message)</code>
45
+ Called when a new private message is received.
46
+ <code>user</code> is the sender.
43
47
 
44
48
  ## <code>on_join(user)</code>
45
49
  Called when a user joins the room.
@@ -57,11 +61,19 @@ Called when a user leaves.
57
61
  Called when the connection is closed.
58
62
 
59
63
  ## <code>on_error(error_message)</code>
60
- Called an error is received from the Talker server.
64
+ Called when an error is received from the Talker server.
65
+
66
+ ## <code>on_event(event)</code>
67
+ Called when any kind of event (all of the above) is received. "event" is a Hash: <code>{"type":"event type","id":"unique ID",... event specific attributes}</code>.
61
68
 
62
69
  # Methods
63
70
  Methods of an instance of Talker class.
64
71
 
72
+ ## <code>current_user</code>
73
+ Info about the user currently connected, <code>nil</code> if not yet connected:
74
+
75
+ {"id"=>1, "name"=>"macournoyer", "email"=>"macournoyer@talkerapp.com"}
76
+
65
77
  ## <code>users</code>
66
78
  Array of users currently in the room. In the form:
67
79
 
data/bin/talker-cat CHANGED
@@ -21,12 +21,29 @@ usage: echo 'something' | talker-cat <room_id>
21
21
 
22
22
  EOS
23
23
 
24
- Talker.connect(:room => room, :token => token) do |client|
24
+ # Non-blocking reader for stdin
25
+ module Reader
26
+ attr_accessor :client
27
+
28
+ def notify_readable
29
+ @client.send_message @io.readline.chomp
30
+ rescue EOFError
31
+ detach
32
+ end
33
+
34
+ def unbind
35
+ @client.close
36
+ end
37
+ end
38
+
39
+ Talker.connect(:room => room.to_i, :token => token) do |client|
25
40
  client.on_connected do
26
- client.send_message STDIN.read
27
- client.close
41
+ conn = EM.watch STDIN, Reader
42
+ conn.client = client
43
+ conn.notify_readable = true
28
44
  end
29
45
  client.on_error do |error|
30
46
  puts error
31
47
  end
48
+ trap("INT") { client.close }
32
49
  end
data/bin/talker-shell CHANGED
@@ -22,7 +22,7 @@ module Process
22
22
  attr_accessor :name, :client
23
23
 
24
24
  def receive_data(data)
25
- log data
25
+ log data.chomp
26
26
  end
27
27
 
28
28
  def unbind
@@ -38,7 +38,7 @@ end
38
38
 
39
39
 
40
40
  EM.run do
41
- Talker.connect(:room => room, :token => token) do |client|
41
+ Talker.connect(:room => room.to_i, :token => token) do |client|
42
42
  @process = nil
43
43
 
44
44
  client.on_connected do
data/lib/talker.rb CHANGED
@@ -2,26 +2,27 @@ require "eventmachine"
2
2
  require "yajl"
3
3
 
4
4
  class Talker < EM::Connection
5
+ CALLBACKS = %w( connected message private_message join idle back leave presence error close event )
6
+
5
7
  class Error < RuntimeError; end
6
8
 
7
- attr_accessor :room, :token, :thread
9
+ attr_accessor :connect_options, :thread, :current_user
8
10
 
9
11
  def self.connect(options={})
10
- host = options[:host] || "talkerapp.com"
11
- port = (options[:port] || 8500).to_i
12
- room = options[:room].to_i
13
- token = options[:token]
14
-
12
+ host = options.delete(:host) || "talkerapp.com"
13
+ port = (options.delete(:port) || 8500).to_i
14
+
15
15
  thread = Thread.new { EM.run } unless EM.reactor_running?
16
16
 
17
- EM.connect host, port, self do |c|
17
+ connection = EM.connect host, port, self do |c|
18
18
  c.thread = thread
19
- c.room = room
20
- c.token = token
19
+ c.connect_options = options
21
20
  yield c if block_given?
22
21
  end
23
22
 
24
- thread.join unless thread.nil?
23
+ thread.join if thread
24
+
25
+ connection
25
26
  end
26
27
 
27
28
  def initialize
@@ -29,7 +30,7 @@ class Talker < EM::Connection
29
30
  end
30
31
 
31
32
  # Callbacks
32
- %w( connected message join idle back leave presence error close ).each do |method|
33
+ CALLBACKS.each do |method|
33
34
  class_eval <<-EOS
34
35
  def on_#{method}(&block)
35
36
  @on_#{method} = block
@@ -45,25 +46,19 @@ class Talker < EM::Connection
45
46
  send({ :type => "message", :content => message }.merge(attributes))
46
47
  end
47
48
 
49
+ def find_user!(user_name)
50
+ @users.values.detect { |user| user["name"] == user_name } || raise(Error, "User #{user_name} not found")
51
+ end
52
+
48
53
  def send_private_message(to, message)
49
54
  if to.is_a?(String)
50
- user = @users.values.detect { |user| user["name"] == to }
51
- raise Error, "User #{to} not found" unless user
52
- user_id = user["id"]
55
+ user_id = find_user!(to)["id"]
53
56
  else
54
57
  user_id = to
55
58
  end
56
59
  send_message message, :to => user_id
57
60
  end
58
61
 
59
-
60
- ## EventMachine callbacks
61
-
62
- def connection_completed
63
- send :type => "connect", :room => @room, :token => @token
64
- EM.add_periodic_timer(20) { send :type => "ping" }
65
- end
66
-
67
62
  def leave
68
63
  send :type => "close"
69
64
  close
@@ -73,6 +68,14 @@ class Talker < EM::Connection
73
68
  close_connection_after_writing
74
69
  end
75
70
 
71
+
72
+ ## EventMachine callbacks
73
+
74
+ def connection_completed
75
+ send @connect_options.merge(:type => "connect")
76
+ EM.add_periodic_timer(20) { send :type => "ping" }
77
+ end
78
+
76
79
  def post_init
77
80
  @parser = Yajl::Parser.new
78
81
  @parser.on_parse_complete = method(:event_parsed)
@@ -90,9 +93,12 @@ class Talker < EM::Connection
90
93
 
91
94
  private
92
95
  def event_parsed(event)
96
+ trigger :event, event
97
+
93
98
  case event["type"]
94
99
  when "connected"
95
- trigger :connected
100
+ @current_user = event["user"]
101
+ trigger :connected, event["user"]
96
102
  when "error"
97
103
  if @on_error
98
104
  @on_error.call(event["message"])
@@ -116,10 +122,15 @@ class Talker < EM::Connection
116
122
  trigger :back, event["user"]
117
123
  when "message"
118
124
  @users[event["user"]["id"]] ||= event["user"]
119
- trigger :message, event["user"], event["content"], event
125
+ if event["private"]
126
+ trigger :private_message, event["user"], event["content"]
127
+ else
128
+ trigger :message, event["user"], event["content"]
129
+ end
120
130
  else
121
131
  raise Error, "unknown event type received from server: " + event["type"]
122
132
  end
133
+
123
134
  rescue
124
135
  close
125
136
  raise
@@ -127,7 +138,7 @@ class Talker < EM::Connection
127
138
 
128
139
  def trigger(callback, *args)
129
140
  callback = instance_variable_get(:"@on_#{callback}")
130
- callback.call(*args[0,callback.arity]) if callback
141
+ callback.call(*args) if callback
131
142
  end
132
143
 
133
144
  def send(data)
data/spec/talker_spec.rb CHANGED
@@ -3,7 +3,8 @@ require File.dirname(__FILE__) + "/spec_helper"
3
3
  EM.describe Talker do
4
4
  it "should connect" do
5
5
  connect do |client|
6
- client.on_connected do
6
+ client.on_connected do |user|
7
+ user["name"].should == TALKER_CONFIG["user_name"]
7
8
  done
8
9
  end
9
10
  end
@@ -47,13 +48,21 @@ EM.describe Talker do
47
48
  client.on_presence do
48
49
  client.send_private_message TALKER_CONFIG["user_name"], "private magic"
49
50
  end
50
- client.on_message do |user, message|
51
+ client.on_private_message do |user, message|
51
52
  message.should == "private magic"
52
53
  done
53
54
  end
54
55
  end
55
56
  end
56
57
 
58
+ it "should receive events" do
59
+ connect do |client|
60
+ client.on_event do
61
+ done
62
+ end
63
+ end
64
+ end
65
+
57
66
  # Keep at the end, mmmkay?
58
67
  it "should leave" do
59
68
  connect do |client|
data/talker.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
- s.name = %q{talker}
3
- s.version = "0.0.1"
2
+ s.name = "talker"
3
+ s.version = "0.0.2"
4
4
 
5
5
  s.authors = ["Marc-Andre Cournoyer"]
6
6
  s.email = "macournoyer@talkerapp.com"
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
8
8
  s.homepage = "http://github.com/macournoyer/talker.rb"
9
9
  s.require_paths = ["lib"]
10
10
  s.bindir = "bin"
11
- s.executables = ["talker-cat", "talker-shell"]
11
+ s.executables = Dir["bin/*"].map { |f| File.basename(f) }
12
12
  s.summary = "A real-time Talker Ruby client."
13
13
  s.test_files = Dir["spec/**"]
14
14
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: talker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc-Andre Cournoyer
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-12 00:00:00 -05:00
12
+ date: 2009-12-14 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -52,7 +52,6 @@ files:
52
52
  - spec/talker.example.yml
53
53
  - spec/talker.yml
54
54
  - spec/talker_spec.rb
55
- - talker-0.0.1.gem
56
55
  - talker.gemspec
57
56
  has_rdoc: true
58
57
  homepage: http://github.com/macournoyer/talker.rb