chirpstream 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |s|
4
+ s.name = "chirpstream"
5
+ s.description = s.summary = "Eventmachine-based Chirpstream client"
6
+ s.email = "joshbuddy@gmail.com"
7
+ s.homepage = "http://github.com/joshbuddy/chirpstream"
8
+ s.authors = ["Joshua Hull"]
9
+ s.files = FileList["[A-Z]*", "{lib}/**/*"]
10
+ end
11
+ Jeweler::GemcutterTasks.new
12
+ rescue LoadError
13
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
14
+ end
data/Readme.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = Chirpstream
2
+
3
+ == About
4
+
5
+ This is an experimental client for http://chirpstream.twitter.com.
6
+
7
+ == Usage
8
+
9
+ require 'rubygems'
10
+ require 'chirpstream'
11
+ require 'rainbow'
12
+
13
+ chirp = Chirpstream.new('joshbuddy', 'xxxxxxxx')
14
+ chirp.reconnect{ puts "reconnecting..." }
15
+ chirp.tweet {|t| puts "#{t['text']} (from #{t['user']['name'].foreground(:red)} (#{('@' + t['user']['screen_name']).foreground(:green)}))" }
16
+ chirp.follow {|t| puts "#{t.data['source'].data['screen_name'].foreground(:green)} following #{t.data['target'].data['screen_name'].foreground(:green)}" }
17
+ chirp.favorite {|t| puts "#{t.data['source'].data['screen_name'].foreground(:green)} <3 -> #{t.data['target_object'].data['text']}" }
18
+ chirp.retweet {|t| puts "#{t.data['source'].data['screen_name'].foreground(:green)} RT -> #{t.data['target_object'].data['text']}" }
19
+ chirp.connect
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,4 @@
1
+ class Chirpstream
2
+ class Delete < Event
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ class Chirpstream
2
+ class Favorite < Event
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ class Chirpstream
2
+ class Follow < Event
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ class Chirpstream
2
+ class Retweet < Event
3
+ end
4
+ end
@@ -0,0 +1,19 @@
1
+ class Chirpstream
2
+
3
+ class Event
4
+
5
+ attr_reader :data
6
+
7
+ def initialize(data)
8
+ @data = data
9
+ end
10
+
11
+ def load_all(&block)
12
+ if unloaded_data = @data.values.find{|d| d.respond_to?(:loaded?) && !d.loaded? }
13
+ unloaded_data.load { load_all(&block) }
14
+ else
15
+ block.call(self)
16
+ end
17
+ end
18
+ end
19
+ end
File without changes
@@ -0,0 +1,29 @@
1
+ class Chirpstream
2
+ class Tweet
3
+
4
+ URL = "http://api.twitter.com/1/statuses/show/%s.json"
5
+
6
+ attr_reader :id, :data
7
+
8
+ def initialize(base, id)
9
+ @base = base
10
+ @id = id
11
+ end
12
+
13
+ def load
14
+ unless loaded?
15
+ http = EM::HttpRequest.new(URL % id).get(:head => {'authorization' => [@base.username, @base.password]})
16
+ http.callback {
17
+ if http.response_header.status == 200
18
+ @data = JSON.parse(http.response)
19
+ yield self
20
+ end
21
+ }
22
+ end
23
+ end
24
+
25
+ def loaded?
26
+ @data
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ class Chirpstream
2
+ class User
3
+
4
+ URL = "http://api.twitter.com/1/users/show/%s.json"
5
+
6
+ attr_reader :id, :data
7
+
8
+ def initialize(base, id)
9
+ @base = base
10
+ @id = id
11
+ end
12
+
13
+ def load
14
+ unless loaded?
15
+ http = EM::HttpRequest.new(URL % id).get(:head => {'authorization' => [@base.username, @base.password]})
16
+ http.callback {
17
+ if http.response_header.status == 200
18
+ @data = JSON.parse(http.response)
19
+ yield self
20
+ end
21
+ }
22
+ end
23
+ end
24
+
25
+ def loaded?
26
+ @data
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,170 @@
1
+ require 'eventmachine'
2
+ require 'em-http'
3
+ require 'json'
4
+ require 'pp'
5
+ require 'load_path_find'
6
+
7
+ $LOAD_PATH.add_current
8
+
9
+ require 'chirpstream/event'
10
+ require 'chirpstream/event/follow'
11
+ require 'chirpstream/event/retweet'
12
+ require 'chirpstream/event/favorite'
13
+ require 'chirpstream/event/delete'
14
+ require 'chirpstream/user'
15
+ require 'chirpstream/tweet'
16
+
17
+ class Chirpstream
18
+
19
+ attr_reader :handlers
20
+
21
+ Handlers = Struct.new(:friend, :tweet, :follow, :favorite, :retweet, :delete, :reconnect)
22
+
23
+ attr_reader :username, :password
24
+
25
+ def initialize(username, password)
26
+ @username = username
27
+ @password = password
28
+ @connect_url = "http://chirpstream.twitter.com/2b/user.json"
29
+ @handlers = Handlers.new([], [], [], [], [], [], [])
30
+ @data = ''
31
+ end
32
+
33
+ def friend(&block)
34
+ @handlers.friend << block
35
+ end
36
+
37
+ def tweet(&block)
38
+ @handlers.tweet << block
39
+ end
40
+
41
+ def follow(&block)
42
+ @handlers.follow << block
43
+ end
44
+
45
+ def favorite(&block)
46
+ @handlers.favorite << block
47
+ end
48
+
49
+ def retweet(&block)
50
+ @handlers.retweet << block
51
+ end
52
+
53
+ def delete(&block)
54
+ @handlers.delete << block
55
+ end
56
+
57
+ def reconnect(&block)
58
+ @handlers.reconnect << block
59
+ end
60
+
61
+ def dispatch_friend(data)
62
+ unless @handlers.friend.empty?
63
+ data['friends'].each_slice(100) do |friend_ids|
64
+ friend_http = EM::HttpRequest.new("http://api.twitter.com/1/users/lookup.json").post(:body => {'user_id' => friend_ids.join(',')}, :head => {'authorization' => [@username, @password]})
65
+ friend_http.callback do
66
+ friends = JSON.parse(friend_http.response)
67
+ friends.each do |friend|
68
+ @handlers.friend.each{|h| h.call(friend)}
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ def dispatch_tweet(data)
76
+ unless @handlers.tweet.empty?
77
+ @handlers.tweet.each{|h| h.call(data)}
78
+ end
79
+ end
80
+
81
+ def dispatch_follow(data)
82
+ unless @handlers.follow.empty?
83
+ data['target'] = User.new(self, data['target']['id'])
84
+ data['source'] = User.new(self, data['source']['id'])
85
+ e = Follow.new(data)
86
+ e.load_all {
87
+ @handlers.follow.each{|h| h.call(e)}
88
+ }
89
+ end
90
+ end
91
+
92
+ def dispatch_favorite(data)
93
+ return if @handlers.follow.empty?
94
+ data['target'] = User.new(self, data['target']['id'])
95
+ data['source'] = User.new(self, data['source']['id'])
96
+ data['target_object'] = Tweet.new(self, data['target_object']['id'])
97
+ e = Favorite.new(data)
98
+ e.load_all {
99
+ @handlers.favorite.each{|h| h.call(e)}
100
+ }
101
+ end
102
+
103
+ def dispatch_retweet(data)
104
+ return if @handlers.retweet.empty?
105
+ data['target'] = User.new(self, data['target']['id'])
106
+ data['source'] = User.new(self, data['source']['id'])
107
+ data['target_object'] = Tweet.new(self, data['target_object']['id'])
108
+ e = Retweet.new(data)
109
+ e.load_all {
110
+ @handlers.retweet.each{|h| h.call(e)}
111
+ }
112
+ end
113
+
114
+ def dispatch_delete(data)
115
+ return if @handlers.delete.empty?
116
+ data['delete']['user_id'] = User.new(self, data['delete']['user_id'])
117
+ e = Delete.new(data)
118
+ e.load_all {
119
+ @handlers.delete.each{|h| h.call(e)}
120
+ }
121
+ end
122
+
123
+ def dispatch_reconnect
124
+ return if @handlers.reconnect.empty?
125
+ @handlers.reconnect.each{|h| h.call}
126
+ end
127
+
128
+ def connect
129
+ unless EM.reactor_running?
130
+ EM.run { connect }
131
+ else
132
+ http = EM::HttpRequest.new(@connect_url).get :head => {'authorization' => [@username, @password]}
133
+ http.errback { |e, err|
134
+ dispatch_reconnect
135
+ connect
136
+ }
137
+ http.stream { |chunk|
138
+ @data << chunk
139
+ begin
140
+ parsed_data = JSON.parse(@data)
141
+ @data = ''
142
+ if parsed_data['friends']
143
+ dispatch_friend(parsed_data)
144
+ elsif parsed_data['text']
145
+ dispatch_tweet(parsed_data)
146
+ elsif parsed_data['event']
147
+ case parsed_data['event']
148
+ when 'follow'
149
+ dispatch_follow(parsed_data)
150
+ when 'favorite'
151
+ dispatch_favorite(parsed_data)
152
+ when 'retweet'
153
+ dispatch_retweet(parsed_data)
154
+ else
155
+ puts "weird event"
156
+ pp parsed_data
157
+ end
158
+ elsif parsed_data['delete']
159
+ dispatch_delete(parsed_data)
160
+ else
161
+ puts "i didn't know what to do with this!"
162
+ pp parsed_data
163
+ end
164
+ rescue JSON::ParserError
165
+ #puts "need more"
166
+ end
167
+ }
168
+ end
169
+ end
170
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chirpstream
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Joshua Hull
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-22 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Eventmachine-based Chirpstream client
22
+ email: joshbuddy@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - Rakefile
31
+ - Readme.rdoc
32
+ - VERSION
33
+ - lib/chirpstream.rb
34
+ - lib/chirpstream/event.rb
35
+ - lib/chirpstream/event/delete.rb
36
+ - lib/chirpstream/event/favorite.rb
37
+ - lib/chirpstream/event/follow.rb
38
+ - lib/chirpstream/event/retweet.rb
39
+ - lib/chirpstream/loadable.rb
40
+ - lib/chirpstream/tweet.rb
41
+ - lib/chirpstream/user.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/joshbuddy/chirpstream
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.6
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Eventmachine-based Chirpstream client
72
+ test_files: []
73
+