talker 0.0.1

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 ADDED
@@ -0,0 +1,97 @@
1
+ # Talker Ruby Client
2
+ A real-time Talker Ruby client.
3
+
4
+ # Usage
5
+ 1) Get a Talker account at https://talkerapp.com/signup
6
+
7
+ 2) Get your Talker Token on https://myaccount.talkerapp.com/settings
8
+
9
+ 3) Find the Room ID you want to connect to. This is the last part of the URL:
10
+
11
+ https://myaccount.talkerapp.com/rooms/<room_id>
12
+
13
+ 4) Serve hot and enjoy
14
+
15
+ Talker.connect(:room => ROOM_ID, :token => YOUR_TALKER_TOKEN) do |client|
16
+ client.on_connected do
17
+ client.send_message "hello!"
18
+ end
19
+
20
+ client.on_message do |user, message|
21
+ puts user["name"] + ": " + message
22
+ end
23
+
24
+ trap("INT") { client.close }
25
+ end
26
+
27
+ # Callbacks
28
+ All arguments are optional.
29
+
30
+ ## <code>on_connected</code>
31
+ Called when the user is authenticated and ready to receive events.
32
+
33
+ ## <code>on_presence(users)</code>
34
+ Called after <code>on_connected</code> with the list of connected users.
35
+ With <code>users</code> being something like this:
36
+
37
+ [{"id"=>1, "name"=>"macournoyer", "email"=>"macournoyer@talkerapp.com"},
38
+ {"id"=>2, "name"=>"gary", "email"=>"gary@talkerapp.com"}]
39
+
40
+ ## <code>on_message(user, message, event)</code>
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.
43
+
44
+ ## <code>on_join(user)</code>
45
+ Called when a user joins the room.
46
+
47
+ ## <code>on_idle(user)</code>
48
+ Called when a user becomes idle (closed connection without leaving).
49
+
50
+ ## <code>on_back(user)</code>
51
+ Called when a user is back from idle.
52
+
53
+ ## <code>on_leave(user)</code>
54
+ Called when a user leaves.
55
+
56
+ ## <code>on_close</code>
57
+ Called when the connection is closed.
58
+
59
+ ## <code>on_error(error_message)</code>
60
+ Called an error is received from the Talker server.
61
+
62
+ # Methods
63
+ Methods of an instance of Talker class.
64
+
65
+ ## <code>users</code>
66
+ Array of users currently in the room. In the form:
67
+
68
+ [{"id"=>1, "name"=>"macournoyer", "email"=>"macournoyer@talkerapp.com"},
69
+ {"id"=>2, "name"=>"gary", "email"=>"gary@talkerapp.com"}]
70
+
71
+ ## <code>leave</code>
72
+ Leave the room and close the connection.
73
+
74
+ ## <code>close</code>
75
+ Close the connection without leaving the room.
76
+
77
+ ## <code>send_message(message)</code>
78
+ Send a message.
79
+
80
+ ## <code>send_private_message(user_name, message)</code>
81
+ Send a private message to <code>user_name</code>.
82
+
83
+ # Running the specs
84
+ Howdy brave lil' one! To run the specs you'll need courage, hard work and some luck:
85
+
86
+ 1) Install from source my "special" fork of em-spec at http://github.com/macournoyer/em-spec.
87
+
88
+ 2) Edit the file spec/talker.example.yml with your info and rename it to spec/talker.yml.
89
+
90
+ 3) Run <code>rake</code> and everything should be green, birds should start signing and someone will make you a chocolate cake
91
+
92
+ (results may vary).
93
+
94
+ # Credits & License
95
+ Released under the Ruby License, (c) Talker
96
+
97
+ Thanks to http://github.com/raggi for kicking this off.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "spec/rake/spectask"
2
+
3
+ task :default => :spec
4
+
5
+ Spec::Rake::SpecTask.new do |t|
6
+ t.spec_opts = %w(-fs -c)
7
+ t.spec_files = FileList["spec/**_spec.rb"]
8
+ end
data/bin/talker-cat ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+ require "talker"
3
+ require "talker/cli"
4
+
5
+ token = Talker::CLI.load_token
6
+ room = ARGV.first
7
+
8
+ abort <<-EOS unless room
9
+ usage: echo 'something' | talker-cat <room_id>
10
+
11
+ Send a message to a room:
12
+
13
+ echo 'something' | talker-cat 1
14
+
15
+ Send a file to a room:
16
+
17
+ talker-cat 1 < site_fixer.rb
18
+
19
+ Room ID is the last part of the URL:
20
+ https://myaccount.talkerapp.com/rooms/<room_id>
21
+
22
+ EOS
23
+
24
+ Talker.connect(:room => room, :token => token) do |client|
25
+ client.on_connected do
26
+ client.send_message STDIN.read
27
+ client.close
28
+ end
29
+ client.on_error do |error|
30
+ puts error
31
+ end
32
+ end
data/bin/talker-shell ADDED
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+ require "talker"
3
+ require "talker/cli"
4
+
5
+ token = Talker::CLI.load_token
6
+ room, cmd, process_name = *ARGV
7
+ process_name ||= cmd
8
+
9
+ abort <<-EOS unless room && cmd
10
+ usage: talker-shell <room_id> <command> [name]
11
+ Launch an irb session connected to a room:
12
+
13
+ talker-shell 1 irb
14
+
15
+ Room ID is the last part of the URL:
16
+ https://myaccount.talkerapp.com/rooms/<room_id>
17
+
18
+ EOS
19
+
20
+
21
+ module Process
22
+ attr_accessor :name, :client
23
+
24
+ def receive_data(data)
25
+ log data
26
+ end
27
+
28
+ def unbind
29
+ log "exited"
30
+ @client.close
31
+ end
32
+
33
+ def log(msg)
34
+ puts "> #{msg}"
35
+ @client.send_message("#{name}> #{msg}")
36
+ end
37
+ end
38
+
39
+
40
+ EM.run do
41
+ Talker.connect(:room => room, :token => token) do |client|
42
+ @process = nil
43
+
44
+ client.on_connected do
45
+ EM.popen(cmd, Process) do |process|
46
+ client.send_message "Connected to process: #{cmd}, prefix commands w/ '#{process_name}: '"
47
+
48
+ process.name = process_name
49
+ process.client = client
50
+ trap("INT") { process.close_connection_after_writing }
51
+
52
+ @process = process
53
+ end
54
+ end
55
+
56
+ client.on_message do |user, message|
57
+ if command = message[/^#{process_name}: (.*)$/, 1]
58
+ puts "> #{cmd}"
59
+ @process.send_data command + "\n"
60
+ end
61
+ end
62
+
63
+ client.on_error do |error|
64
+ puts error
65
+ end
66
+
67
+ client.on_close do
68
+ EM.stop
69
+ end
70
+ end
71
+ end
data/lib/talker/cli.rb ADDED
@@ -0,0 +1,16 @@
1
+ class Talker
2
+ class CLI
3
+ def self.load_token
4
+ token_path = File.join(ENV['HOME'], '.talker')
5
+
6
+ unless File.file?(token_path)
7
+ abort <<-EOS
8
+ Place your Talker Token in #{token_path}. You can find your
9
+ token in https://myaccount.talkerapp.com/settings
10
+ EOS
11
+ end
12
+
13
+ File.read(token_path).strip
14
+ end
15
+ end
16
+ end
data/lib/talker.rb ADDED
@@ -0,0 +1,136 @@
1
+ require "eventmachine"
2
+ require "yajl"
3
+
4
+ class Talker < EM::Connection
5
+ class Error < RuntimeError; end
6
+
7
+ attr_accessor :room, :token, :thread
8
+
9
+ 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
+
15
+ thread = Thread.new { EM.run } unless EM.reactor_running?
16
+
17
+ EM.connect host, port, self do |c|
18
+ c.thread = thread
19
+ c.room = room
20
+ c.token = token
21
+ yield c if block_given?
22
+ end
23
+
24
+ thread.join unless thread.nil?
25
+ end
26
+
27
+ def initialize
28
+ @users = {}
29
+ end
30
+
31
+ # Callbacks
32
+ %w( connected message join idle back leave presence error close ).each do |method|
33
+ class_eval <<-EOS
34
+ def on_#{method}(&block)
35
+ @on_#{method} = block
36
+ end
37
+ EOS
38
+ end
39
+
40
+ def users
41
+ @users.values
42
+ end
43
+
44
+ def send_message(message, attributes={})
45
+ send({ :type => "message", :content => message }.merge(attributes))
46
+ end
47
+
48
+ def send_private_message(to, message)
49
+ 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"]
53
+ else
54
+ user_id = to
55
+ end
56
+ send_message message, :to => user_id
57
+ end
58
+
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
+ def leave
68
+ send :type => "close"
69
+ close
70
+ end
71
+
72
+ def close
73
+ close_connection_after_writing
74
+ end
75
+
76
+ def post_init
77
+ @parser = Yajl::Parser.new
78
+ @parser.on_parse_complete = method(:event_parsed)
79
+ end
80
+
81
+ def receive_data(data)
82
+ @parser << data
83
+ end
84
+
85
+ def unbind
86
+ trigger :close
87
+ @thread.kill if @thread
88
+ end
89
+
90
+
91
+ private
92
+ def event_parsed(event)
93
+ case event["type"]
94
+ when "connected"
95
+ trigger :connected
96
+ when "error"
97
+ if @on_error
98
+ @on_error.call(event["message"])
99
+ else
100
+ raise Error, event["message"]
101
+ end
102
+ when "users"
103
+ event["users"].each do |user|
104
+ @users[user["id"]] = user
105
+ end
106
+ trigger :presence, @users.values
107
+ when "join"
108
+ @users[event["user"]["id"]] = event["user"]
109
+ trigger :join, event["user"]
110
+ when "leave"
111
+ @users.delete(event["user"]["id"])
112
+ trigger :leave, event["user"]
113
+ when "idle"
114
+ trigger :idle, event["user"]
115
+ when "back"
116
+ trigger :back, event["user"]
117
+ when "message"
118
+ @users[event["user"]["id"]] ||= event["user"]
119
+ trigger :message, event["user"], event["content"], event
120
+ else
121
+ raise Error, "unknown event type received from server: " + event["type"]
122
+ end
123
+ rescue
124
+ close
125
+ raise
126
+ end
127
+
128
+ def trigger(callback, *args)
129
+ callback = instance_variable_get(:"@on_#{callback}")
130
+ callback.call(*args[0,callback.arity]) if callback
131
+ end
132
+
133
+ def send(data)
134
+ send_data Yajl::Encoder.encode(data) + "\n"
135
+ end
136
+ end
@@ -0,0 +1,22 @@
1
+ require "rubygems"
2
+ require "yaml"
3
+ require 'spec'
4
+ $:.unshift File.dirname(__FILE__) + "/../lib"
5
+ require "talker"
6
+
7
+ # Installing em-spec from http://github.com/macournoyer/em-spec
8
+ require 'em/spec'
9
+ require 'em/spec/rspec'
10
+ EM.spec_backend = EM::Spec::Rspec
11
+
12
+ TALKER_CONFIG = YAML.load_file(File.dirname(__FILE__) + "/talker.yml")
13
+
14
+ module Helpers
15
+ def connect(&callback)
16
+ Talker.connect :room => TALKER_CONFIG["room"].to_i, :token => TALKER_CONFIG["token"], &callback
17
+ end
18
+ end
19
+
20
+ Spec::Runner.configure do |config|
21
+ config.include Helpers
22
+ end
@@ -0,0 +1,7 @@
1
+ # Get your Talker Token on https://myaccount.talkerapp.com/settings
2
+ token: YOUR_TALKER_TOKEN
3
+ # Room ID is the last part of the URL:
4
+ # https://myaccount.talkerapp.com/rooms/<room_id>
5
+ room: ROOM_ID
6
+ # Make sure it matches or some specs will fail
7
+ user_name: YOUR_USER_NAME
data/spec/talker.yml ADDED
@@ -0,0 +1,3 @@
1
+ token: 845a877053137c0bc76acfc027b92ca0e1d3699f
2
+ room: 62
3
+ user_name: ma
@@ -0,0 +1,68 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ EM.describe Talker do
4
+ it "should connect" do
5
+ connect do |client|
6
+ client.on_connected do
7
+ done
8
+ end
9
+ end
10
+ end
11
+
12
+ it "should close" do
13
+ connect do |client|
14
+ client.on_connected do
15
+ client.close
16
+ end
17
+ client.on_close do
18
+ done
19
+ end
20
+ end
21
+ end
22
+
23
+ it "should receive presence" do
24
+ connect do |client|
25
+ client.on_presence do |users|
26
+ users.size.should >= 1
27
+ users.map { |user| user["name"] }.should include(TALKER_CONFIG["user_name"])
28
+ done
29
+ end
30
+ end
31
+ end
32
+
33
+ it "should send and receive message" do
34
+ connect do |client|
35
+ client.on_connected do
36
+ client.send_message "it works, magic!"
37
+ end
38
+ client.on_message do |user, message|
39
+ message.should == "it works, magic!"
40
+ done
41
+ end
42
+ end
43
+ end
44
+
45
+ it "should send and receive private message" do
46
+ connect do |client|
47
+ client.on_presence do
48
+ client.send_private_message TALKER_CONFIG["user_name"], "private magic"
49
+ end
50
+ client.on_message do |user, message|
51
+ message.should == "private magic"
52
+ done
53
+ end
54
+ end
55
+ end
56
+
57
+ # Keep at the end, mmmkay?
58
+ it "should leave" do
59
+ connect do |client|
60
+ client.on_connected do
61
+ client.leave
62
+ end
63
+ client.on_close do
64
+ done
65
+ end
66
+ end
67
+ end
68
+ end
data/talker.gemspec ADDED
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{talker}
3
+ s.version = "0.0.1"
4
+
5
+ s.authors = ["Marc-Andre Cournoyer"]
6
+ s.email = "macournoyer@talkerapp.com"
7
+ s.files = Dir["**/*"]
8
+ s.homepage = "http://github.com/macournoyer/talker.rb"
9
+ s.require_paths = ["lib"]
10
+ s.bindir = "bin"
11
+ s.executables = ["talker-cat", "talker-shell"]
12
+ s.summary = "A real-time Talker Ruby client."
13
+ s.test_files = Dir["spec/**"]
14
+
15
+ s.add_dependency "eventmachine"
16
+ s.add_dependency "yajl-ruby"
17
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: talker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Marc-Andre Cournoyer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-12 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: eventmachine
17
+ type: :runtime
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: yajl-ruby
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description:
36
+ email: macournoyer@talkerapp.com
37
+ executables:
38
+ - talker-cat
39
+ - talker-shell
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - bin/talker-cat
46
+ - bin/talker-shell
47
+ - lib/talker/cli.rb
48
+ - lib/talker.rb
49
+ - Rakefile
50
+ - README.md
51
+ - spec/spec_helper.rb
52
+ - spec/talker.example.yml
53
+ - spec/talker.yml
54
+ - spec/talker_spec.rb
55
+ - talker-0.0.1.gem
56
+ - talker.gemspec
57
+ has_rdoc: true
58
+ homepage: http://github.com/macournoyer/talker.rb
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options: []
63
+
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.3.5
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: A real-time Talker Ruby client.
85
+ test_files:
86
+ - spec/spec_helper.rb
87
+ - spec/talker.example.yml
88
+ - spec/talker.yml
89
+ - spec/talker_spec.rb