jls-tweetstream 2.5.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.
- data/.yardopts +6 -0
- data/CHANGELOG.md +76 -0
- data/CONTRIBUTING.md +9 -0
- data/LICENSE.md +20 -0
- data/README.md +392 -0
- data/Rakefile +11 -0
- data/lib/tweetstream.rb +36 -0
- data/lib/tweetstream/client.rb +582 -0
- data/lib/tweetstream/configuration.rb +92 -0
- data/lib/tweetstream/daemon.rb +52 -0
- data/lib/tweetstream/site_stream_client.rb +122 -0
- data/lib/tweetstream/version.rb +3 -0
- data/spec/fixtures/delete.json +8 -0
- data/spec/fixtures/direct_messages.json +1 -0
- data/spec/fixtures/favorite.json +150 -0
- data/spec/fixtures/ids.json +30 -0
- data/spec/fixtures/info.json +18 -0
- data/spec/fixtures/limit.json +5 -0
- data/spec/fixtures/scrub_geo.json +8 -0
- data/spec/fixtures/stall_warning.json +7 -0
- data/spec/fixtures/status_withheld.json +7 -0
- data/spec/fixtures/statuses.json +1 -0
- data/spec/fixtures/user_withheld.json +6 -0
- data/spec/helper.rb +58 -0
- data/spec/tweetstream/client_authentication_spec.rb +83 -0
- data/spec/tweetstream/client_site_stream_spec.rb +145 -0
- data/spec/tweetstream/client_spec.rb +391 -0
- data/spec/tweetstream/client_userstream_spec.rb +74 -0
- data/spec/tweetstream/daemon_spec.rb +29 -0
- data/spec/tweetstream/site_stream_client_spec.rb +233 -0
- data/spec/tweetstream_spec.rb +129 -0
- data/tweetstream.gemspec +29 -0
- metadata +179 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'tweetstream/version'
|
2
|
+
|
3
|
+
module TweetStream
|
4
|
+
# Defines constants and methods related to configuration
|
5
|
+
module Configuration
|
6
|
+
# An array of valid keys in the options hash when configuring TweetStream.
|
7
|
+
VALID_OPTIONS_KEYS = [
|
8
|
+
:parser,
|
9
|
+
:username,
|
10
|
+
:password,
|
11
|
+
:user_agent,
|
12
|
+
:auth_method,
|
13
|
+
:proxy,
|
14
|
+
:consumer_key,
|
15
|
+
:consumer_secret,
|
16
|
+
:oauth_token,
|
17
|
+
:oauth_token_secret].freeze
|
18
|
+
|
19
|
+
OAUTH_OPTIONS_KEYS = [
|
20
|
+
:consumer_key,
|
21
|
+
:consumer_secret,
|
22
|
+
:oauth_token,
|
23
|
+
:oauth_token_secret].freeze
|
24
|
+
|
25
|
+
# By default, don't set a username
|
26
|
+
DEFAULT_USERNAME = nil
|
27
|
+
|
28
|
+
# By default, don't set a password
|
29
|
+
DEFAULT_PASSWORD = nil
|
30
|
+
|
31
|
+
# The user agent that will be sent to the API endpoint if none is set
|
32
|
+
DEFAULT_USER_AGENT = "TweetStream Ruby Gem #{TweetStream::VERSION}".freeze
|
33
|
+
|
34
|
+
# The default authentication method
|
35
|
+
DEFAULT_AUTH_METHOD = :oauth
|
36
|
+
|
37
|
+
DEFAULT_PROXY = nil
|
38
|
+
|
39
|
+
VALID_FORMATS = [
|
40
|
+
:basic,
|
41
|
+
:oauth].freeze
|
42
|
+
|
43
|
+
# By default, don't set an application key
|
44
|
+
DEFAULT_CONSUMER_KEY = nil
|
45
|
+
|
46
|
+
# By default, don't set an application secret
|
47
|
+
DEFAULT_CONSUMER_SECRET = nil
|
48
|
+
|
49
|
+
# By default, don't set a user oauth token
|
50
|
+
DEFAULT_OAUTH_TOKEN = nil
|
51
|
+
|
52
|
+
# By default, don't set a user oauth secret
|
53
|
+
DEFAULT_OAUTH_TOKEN_SECRET = nil
|
54
|
+
|
55
|
+
# @private
|
56
|
+
attr_accessor *VALID_OPTIONS_KEYS
|
57
|
+
|
58
|
+
# When this module is extended, set all configuration options to their default values
|
59
|
+
def self.extended(base)
|
60
|
+
base.reset
|
61
|
+
end
|
62
|
+
|
63
|
+
# Convenience method to allow configuration options to be set in a block
|
64
|
+
def configure
|
65
|
+
yield self
|
66
|
+
end
|
67
|
+
|
68
|
+
# Create a hash of options and their values
|
69
|
+
def options
|
70
|
+
Hash[*VALID_OPTIONS_KEYS.map {|key| [key, send(key)] }.flatten]
|
71
|
+
end
|
72
|
+
|
73
|
+
# Create a hash of options and their values
|
74
|
+
def oauth_options
|
75
|
+
Hash[*OAUTH_OPTIONS_KEYS.map {|key| [key, send(key)] }.flatten]
|
76
|
+
end
|
77
|
+
|
78
|
+
# Reset all configuration options to defaults
|
79
|
+
def reset
|
80
|
+
self.username = DEFAULT_USERNAME
|
81
|
+
self.password = DEFAULT_PASSWORD
|
82
|
+
self.user_agent = DEFAULT_USER_AGENT
|
83
|
+
self.auth_method = DEFAULT_AUTH_METHOD
|
84
|
+
self.proxy = DEFAULT_PROXY
|
85
|
+
self.consumer_key = DEFAULT_CONSUMER_KEY
|
86
|
+
self.consumer_secret = DEFAULT_CONSUMER_SECRET
|
87
|
+
self.oauth_token = DEFAULT_OAUTH_TOKEN
|
88
|
+
self.oauth_token_secret = DEFAULT_OAUTH_TOKEN_SECRET
|
89
|
+
self
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'daemons'
|
2
|
+
|
3
|
+
# A daemonized TweetStream client that will allow you to
|
4
|
+
# create backgroundable scripts for application specific
|
5
|
+
# processes. For instance, if you create a script called
|
6
|
+
# <tt>tracker.rb</tt> and fill it with this:
|
7
|
+
#
|
8
|
+
# require 'rubygems'
|
9
|
+
# require 'tweetstream'
|
10
|
+
#
|
11
|
+
# TweetStream.configure do |config|
|
12
|
+
# config.consumer_key = 'abcdefghijklmnopqrstuvwxyz'
|
13
|
+
# config.consumer_secret = '0123456789'
|
14
|
+
# config.oauth_token = 'abcdefghijklmnopqrstuvwxyz'
|
15
|
+
# config.oauth_token_secret = '0123456789'
|
16
|
+
# config.auth_method = :oauth
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# TweetStream::Daemon.new('tracker').track('intridea') do |status|
|
20
|
+
# # do something here
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# And then you call this from the shell:
|
24
|
+
#
|
25
|
+
# ruby tracker.rb start
|
26
|
+
#
|
27
|
+
# A daemon process will spawn that will automatically
|
28
|
+
# run the code in the passed block whenever a new tweet
|
29
|
+
# matching your search term ('intridea' in this case)
|
30
|
+
# is posted.
|
31
|
+
#
|
32
|
+
class TweetStream::Daemon < TweetStream::Client
|
33
|
+
|
34
|
+
DEFAULT_NAME = 'tweetstream'.freeze
|
35
|
+
DEFAULT_OPTIONS = { :multiple => true }
|
36
|
+
|
37
|
+
attr_accessor :app_name, :daemon_options
|
38
|
+
|
39
|
+
# The daemon has an optional process name for use when querying
|
40
|
+
# running processes. You can also pass daemon options.
|
41
|
+
def initialize(name = DEFAULT_NAME, options = DEFAULT_OPTIONS)
|
42
|
+
@app_name = name
|
43
|
+
@daemon_options = options
|
44
|
+
super({})
|
45
|
+
end
|
46
|
+
|
47
|
+
def start(path, query_parameters = {}, &block) #:nodoc:
|
48
|
+
Daemons.run_proc(@app_name, @daemon_options) do
|
49
|
+
super(path, query_parameters, &block)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'em-http'
|
2
|
+
require 'em-http/middleware/oauth'
|
3
|
+
require 'em-http/middleware/json_response'
|
4
|
+
|
5
|
+
module TweetStream
|
6
|
+
class SiteStreamClient
|
7
|
+
|
8
|
+
attr_accessor *Configuration::OAUTH_OPTIONS_KEYS
|
9
|
+
|
10
|
+
def initialize(config_uri, oauth = {})
|
11
|
+
@config_uri = config_uri
|
12
|
+
|
13
|
+
options = TweetStream.oauth_options.merge(oauth)
|
14
|
+
Configuration::OAUTH_OPTIONS_KEYS.each do |key|
|
15
|
+
send("#{key}=", options[key])
|
16
|
+
end
|
17
|
+
|
18
|
+
EventMachine::HttpRequest.use EventMachine::Middleware::JSONResponse
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_error(&block)
|
22
|
+
if block_given?
|
23
|
+
@on_error = block
|
24
|
+
self
|
25
|
+
else
|
26
|
+
@on_error
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def info(&block)
|
31
|
+
options = { :error_msg => 'Failed to retrieve SiteStream info.' }
|
32
|
+
request(:get, info_path, options, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_user(user_id, &block)
|
36
|
+
options = {
|
37
|
+
:error_msg => 'Failed to add user to SiteStream',
|
38
|
+
:body => { 'user_id' => normalized_user_ids(user_id) }
|
39
|
+
}
|
40
|
+
|
41
|
+
request(:post, add_user_path, options, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
def remove_user(user_id, &block)
|
45
|
+
options = {
|
46
|
+
:error_msg => 'Failed to remove user from SiteStream.',
|
47
|
+
:body => { 'user_id' => normalized_user_ids(user_id) }
|
48
|
+
}
|
49
|
+
|
50
|
+
request(:post, remove_user_path, options, &block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def friends_ids(user_id, &block)
|
54
|
+
options = { :error_msg => 'Failed to retrieve SiteStream friends ids.',
|
55
|
+
:body => { 'user_id' => user_id }
|
56
|
+
}
|
57
|
+
request(:post, friends_ids_path, options, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def connection
|
63
|
+
return @conn if defined?(@conn)
|
64
|
+
|
65
|
+
@conn = EventMachine::HttpRequest.new('https://sitestream.twitter.com/')
|
66
|
+
@conn.use EventMachine::Middleware::OAuth, oauth_configuration
|
67
|
+
@conn
|
68
|
+
end
|
69
|
+
|
70
|
+
def oauth_configuration
|
71
|
+
{
|
72
|
+
:consumer_key => consumer_key,
|
73
|
+
:consumer_secret => consumer_secret,
|
74
|
+
:access_token => oauth_token,
|
75
|
+
:access_token_secret => oauth_token_secret
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def info_path
|
80
|
+
@config_uri + '/info.json'
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_user_path
|
84
|
+
@config_uri + '/add_user.json'
|
85
|
+
end
|
86
|
+
|
87
|
+
def remove_user_path
|
88
|
+
@config_uri + '/remove_user.json'
|
89
|
+
end
|
90
|
+
|
91
|
+
def friends_ids_path
|
92
|
+
@config_uri + '/friends/ids.json'
|
93
|
+
end
|
94
|
+
|
95
|
+
def request(method, path, options, &block)
|
96
|
+
error_msg = options.delete(:error_msg)
|
97
|
+
|
98
|
+
http = connection.send(method, options.merge(:path => path))
|
99
|
+
http.callback do
|
100
|
+
if http.response_header.status == 200
|
101
|
+
if block && block.kind_of?(Proc)
|
102
|
+
if block.arity == 1
|
103
|
+
block.call http.response
|
104
|
+
else
|
105
|
+
block.call
|
106
|
+
end
|
107
|
+
end
|
108
|
+
else
|
109
|
+
@on_error.call(error_msg) if @on_error && @on_error.kind_of?(Proc)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
http.errback do
|
113
|
+
@on_error.call(error_msg) if @on_error && @on_error.kind_of?(Proc)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def normalized_user_ids(user_id)
|
118
|
+
user_id.join(',') if user_id.kind_of?(Array)
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"direct_message":{"created_at":"Sat Sep 24 18:59:38 +0000 2011", "id_str":"4227325281", "sender_screen_name":"coreyhaines", "sender":{"name":"Corey Haines", "profile_sidebar_fill_color":"DAECF4", "profile_sidebar_border_color":"C6E2EE", "profile_background_tile":false, "profile_image_url":"http://a0.twimg.com/profile_images/1508969901/Photo_on_2011-08-22_at_19.15__3_normal.jpg", "created_at":"Sun Dec 23 18:11:29 +0000 2007", "location":"Chicago, IL", "follow_request_sent":false, "id_str":"11458102", "is_translator":false, "profile_link_color":"1F98C7", "default_profile":false, "favourites_count":122, "contributors_enabled":false, "url":"http://www.coreyhaines.com", "id":11458102, "profile_image_url_https":"https://si0.twimg.com/profile_images/1508969901/Photo_on_2011-08-22_at_19.15__3_normal.jpg", "utc_offset":-21600, "profile_use_background_image":true, "listed_count":593, "lang":"en", "followers_count":5764, "protected":false, "profile_text_color":"663B12", "notifications":false, "description":"Software Journeyman, Coderetreat Facilitator, Cofounder of MercuryApp.com, Awesome....\r\nI make magic!", "verified":false, "profile_background_color":"C6E2EE", "geo_enabled":false, "profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme2/bg.gif", "time_zone":"Central Time (US & Canada)", "profile_background_image_url":"http://a1.twimg.com/images/themes/theme2/bg.gif", "default_profile_image":false, "friends_count":423, "statuses_count":35950, "following":false, "screen_name":"coreyhaines", "show_all_inline_media":false}, "recipient_screen_name":"coreyhainestest", "text":"waddup gain", "id":4227325281, "recipient":{"name":"Corey's Test Account", "profile_sidebar_fill_color":"DDEEF6", "profile_sidebar_border_color":"C0DEED", "profile_background_tile":false, "profile_image_url":"http://a2.twimg.com/sticky/default_profile_images/default_profile_3_normal.png", "created_at":"Sat Sep 24 13:04:56 +0000 2011", "location":null, "follow_request_sent":false, "id_str":"379145826", "is_translator":false, "profile_link_color":"0084B4", "default_profile":true, "favourites_count":0, "contributors_enabled":false, "url":null, "id":379145826, "profile_image_url_https":"https://si0.twimg.com/sticky/default_profile_images/default_profile_3_normal.png", "utc_offset":null, "profile_use_background_image":true, "listed_count":0, "lang":"en", "followers_count":1, "protected":false, "profile_text_color":"333333", "notifications":false, "description":null, "verified":false, "profile_background_color":"C0DEED", "geo_enabled":false, "profile_background_image_url_https":"https://si0.twimg.com/images/themes/theme1/bg.png", "time_zone":null, "profile_background_image_url":"http://a0.twimg.com/images/themes/theme1/bg.png", "default_profile_image":true, "friends_count":1, "statuses_count":21, "following":true, "screen_name":"coreyhainestest", "show_all_inline_media":false}, "recipient_id":379145826, "sender_id":11458102}}
|
@@ -0,0 +1,150 @@
|
|
1
|
+
{"target":
|
2
|
+
{"id": 598914668,
|
3
|
+
"verified": false,
|
4
|
+
"id_str": "598914668",
|
5
|
+
"profile_background_tile": false,
|
6
|
+
"location": "",
|
7
|
+
"profile_sidebar_fill_color": "DDEEF6",
|
8
|
+
"contributors_enabled": false,
|
9
|
+
"notifications": false,
|
10
|
+
"geo_enabled": false,
|
11
|
+
"profile_image_url_https": "https://si0.twimg.com/profile_images/2276724218/raf46pju0mijc6ixm6ke_normal.jpeg",
|
12
|
+
"utc_offset": null,
|
13
|
+
"default_profile": true,
|
14
|
+
"statuses_count": 151,
|
15
|
+
"name": "dev4sns",
|
16
|
+
"profile_background_color": "C0DEED",
|
17
|
+
"friends_count": 15,
|
18
|
+
"show_all_inline_media": false,
|
19
|
+
"protected": false,
|
20
|
+
"follow_request_sent": false,
|
21
|
+
"screen_name": "dev4sns",
|
22
|
+
"listed_count": 0,
|
23
|
+
"profile_background_image_url": "http://a0.twimg.com/images/themes/theme1/bg.png",
|
24
|
+
"lang": "ko",
|
25
|
+
"profile_link_color": "0084B4",
|
26
|
+
"time_zone": null,
|
27
|
+
"description": "Dev 계정입니다.",
|
28
|
+
"is_translator": false,
|
29
|
+
"profile_use_background_image": true,
|
30
|
+
"url": null,
|
31
|
+
"profile_text_color": "333333",
|
32
|
+
"created_at": "Mon Jun 04 04:07:27 +0000 2012",
|
33
|
+
"default_profile_image": false,
|
34
|
+
"profile_background_image_url_https":
|
35
|
+
"https://si0.twimg.com/images/themes/theme1/bg.png",
|
36
|
+
"favourites_count": 0,
|
37
|
+
"profile_sidebar_border_color": "C0DEED",
|
38
|
+
"profile_image_url":
|
39
|
+
"http://a0.twimg.com/profile_images/2276724218/raf46pju0mijc6ixm6ke_normal.jpeg",
|
40
|
+
"following": true,
|
41
|
+
"followers_count": 5},
|
42
|
+
"target_object":
|
43
|
+
{"id_str": "228029422597443584",
|
44
|
+
"in_reply_to_user_id": null,
|
45
|
+
"truncated": false,
|
46
|
+
"contributors": null,
|
47
|
+
"retweet_count": 0,
|
48
|
+
"possibly_sensitive_editable": true,
|
49
|
+
"favorited": false,
|
50
|
+
"coordinates": null,
|
51
|
+
"geo": null,
|
52
|
+
"possibly_sensitive": false,
|
53
|
+
"user":
|
54
|
+
{"id": 598914668,
|
55
|
+
"verified": false,
|
56
|
+
"id_str": "598914668",
|
57
|
+
"profile_background_tile": false,
|
58
|
+
"location": "",
|
59
|
+
"profile_sidebar_fill_color": "DDEEF6",
|
60
|
+
"contributors_enabled": false,
|
61
|
+
"notifications": false,
|
62
|
+
"geo_enabled": false,
|
63
|
+
"profile_image_url_https":
|
64
|
+
"https://si0.twimg.com/profile_images/2276724218/raf46pju0mijc6ixm6ke_normal.jpeg",
|
65
|
+
"utc_offset": null,
|
66
|
+
"default_profile": true,
|
67
|
+
"statuses_count": 151,
|
68
|
+
"name": "dev4sns",
|
69
|
+
"profile_background_color": "C0DEED",
|
70
|
+
"friends_count": 15,
|
71
|
+
"show_all_inline_media": false,
|
72
|
+
"protected": false,
|
73
|
+
"follow_request_sent": false,
|
74
|
+
"screen_name": "dev4sns",
|
75
|
+
"listed_count": 0,
|
76
|
+
"profile_background_image_url":
|
77
|
+
"http://a0.twimg.com/images/themes/theme1/bg.png",
|
78
|
+
"lang": "ko",
|
79
|
+
"profile_link_color": "0084B4",
|
80
|
+
"time_zone": null,
|
81
|
+
"description": "Dev 계정입니다.",
|
82
|
+
"is_translator": false,
|
83
|
+
"profile_use_background_image": true,
|
84
|
+
"url": null,
|
85
|
+
"profile_text_color": "333333",
|
86
|
+
"created_at": "Mon Jun 04 04:07:27 +0000 2012",
|
87
|
+
"default_profile_image": false,
|
88
|
+
"profile_background_image_url_https":
|
89
|
+
"https://si0.twimg.com/images/themes/theme1/bg.png",
|
90
|
+
"favourites_count": 0,
|
91
|
+
"profile_sidebar_border_color": "C0DEED",
|
92
|
+
"profile_image_url":
|
93
|
+
"http://a0.twimg.com/profile_images/2276724218/raf46pju0mijc6ixm6ke_normal.jpeg",
|
94
|
+
"following": true,
|
95
|
+
"followers_count": 5},
|
96
|
+
"in_reply_to_status_id_str": null,
|
97
|
+
"in_reply_to_screen_name": null,
|
98
|
+
"source": "<a href=\"http://www.a2m.co.kr\" rel=\"nofollow\">Dev Acct</a>",
|
99
|
+
"in_reply_to_user_id_str": null,
|
100
|
+
"retweeted": false,
|
101
|
+
"in_reply_to_status_id": null,
|
102
|
+
"id": 228029422597443584,
|
103
|
+
"place": null,
|
104
|
+
"text": "asdf http://t.co/CRX3fCRa",
|
105
|
+
"created_at": "Wed Jul 25 07:30:25 +0000 2012"},
|
106
|
+
"source":
|
107
|
+
{"id": 459909498,
|
108
|
+
"verified": false,
|
109
|
+
"id_str": "459909498",
|
110
|
+
"profile_background_tile": false,
|
111
|
+
"location": "",
|
112
|
+
"profile_sidebar_fill_color": "DDEEF6",
|
113
|
+
"contributors_enabled": false,
|
114
|
+
"notifications": false,
|
115
|
+
"geo_enabled": false,
|
116
|
+
"profile_image_url_https":
|
117
|
+
"https://si0.twimg.com/sticky/default_profile_images/default_profile_6_normal.png",
|
118
|
+
"utc_offset": null,
|
119
|
+
"default_profile": true,
|
120
|
+
"statuses_count": 124,
|
121
|
+
"name": "Brian Park",
|
122
|
+
"profile_background_color": "C0DEED",
|
123
|
+
"friends_count": 3,
|
124
|
+
"show_all_inline_media": false,
|
125
|
+
"protected": false,
|
126
|
+
"follow_request_sent": false,
|
127
|
+
"screen_name": "bdares",
|
128
|
+
"listed_count": 0,
|
129
|
+
"profile_background_image_url":
|
130
|
+
"http://a0.twimg.com/images/themes/theme1/bg.png",
|
131
|
+
"lang": "en",
|
132
|
+
"profile_link_color": "0084B4",
|
133
|
+
"time_zone": null,
|
134
|
+
"description": "",
|
135
|
+
"is_translator": false,
|
136
|
+
"profile_use_background_image": true,
|
137
|
+
"url": null,
|
138
|
+
"profile_text_color": "333333",
|
139
|
+
"created_at": "Tue Jan 10 05:33:52 +0000 2012",
|
140
|
+
"default_profile_image": true,
|
141
|
+
"profile_background_image_url_https":
|
142
|
+
"https://si0.twimg.com/images/themes/theme1/bg.png",
|
143
|
+
"favourites_count": 14,
|
144
|
+
"profile_sidebar_border_color": "C0DEED",
|
145
|
+
"profile_image_url":
|
146
|
+
"http://a0.twimg.com/sticky/default_profile_images/default_profile_6_normal.png",
|
147
|
+
"following": false,
|
148
|
+
"followers_count": 1},
|
149
|
+
"event": "favorite",
|
150
|
+
"created_at": "Mon Aug 06 02:24:16 +0000 2012"}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
{
|
2
|
+
"follow":
|
3
|
+
{
|
4
|
+
"user":
|
5
|
+
{
|
6
|
+
"id":119476949,
|
7
|
+
"name":"oauth_dancer",
|
8
|
+
"dm":false
|
9
|
+
},
|
10
|
+
"friends":
|
11
|
+
[
|
12
|
+
795649,
|
13
|
+
819797,
|
14
|
+
1401881,
|
15
|
+
3191321,
|
16
|
+
6253282,
|
17
|
+
8285392,
|
18
|
+
9160152,
|
19
|
+
13058772,
|
20
|
+
15147442,
|
21
|
+
15266205,
|
22
|
+
15822993,
|
23
|
+
27831060,
|
24
|
+
101058399,
|
25
|
+
289788076
|
26
|
+
],
|
27
|
+
"previous_cursor":0,
|
28
|
+
"next_cursor":0
|
29
|
+
}
|
30
|
+
}
|