chirpstream 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/Rakefile +14 -0
- data/Readme.rdoc +19 -0
- data/VERSION +1 -0
- data/lib/chirpstream/event/delete.rb +4 -0
- data/lib/chirpstream/event/favorite.rb +4 -0
- data/lib/chirpstream/event/follow.rb +4 -0
- data/lib/chirpstream/event/retweet.rb +4 -0
- data/lib/chirpstream/event.rb +19 -0
- data/lib/chirpstream/loadable.rb +0 -0
- data/lib/chirpstream/tweet.rb +29 -0
- data/lib/chirpstream/user.rb +29 -0
- data/lib/chirpstream.rb +170 -0
- metadata +73 -0
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,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
|
data/lib/chirpstream.rb
ADDED
@@ -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
|
+
|