gnip_api 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.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile.lock +6 -1
- data/README.md +43 -4
- data/gnip_api.gemspec +1 -0
- data/lib/gnip_api/adapter.rb +44 -22
- data/lib/gnip_api/adapters/base_adapter.rb +59 -0
- data/lib/gnip_api/adapters/httparty_adapter.rb +33 -1
- data/lib/gnip_api/apis/power_track/buffer.rb +4 -0
- data/lib/gnip_api/apis/power_track/rule.rb +31 -0
- data/lib/gnip_api/apis/power_track/rules.rb +69 -2
- data/lib/gnip_api/apis/power_track/stream.rb +41 -22
- data/lib/gnip_api/apis/search/count.rb +0 -0
- data/lib/gnip_api/apis/search/query.rb +36 -0
- data/lib/gnip_api/apis/search/result.rb +17 -0
- data/lib/gnip_api/apis/search/stream.rb +26 -0
- data/lib/gnip_api/configuration.rb +4 -1
- data/lib/gnip_api/endpoints.rb +15 -2
- data/lib/gnip_api/errors.rb +39 -0
- data/lib/gnip_api/gnip/activity.rb +72 -0
- data/lib/gnip_api/gnip/actor.rb +42 -11
- data/lib/gnip_api/gnip/gnip_data.rb +23 -0
- data/lib/gnip_api/gnip/message.rb +24 -51
- data/lib/gnip_api/gnip/system_message.rb +30 -0
- data/lib/gnip_api/gnip/url.rb +35 -0
- data/lib/gnip_api/limiters/rules.rb +56 -0
- data/lib/gnip_api/rate_limiter.rb +14 -0
- data/lib/gnip_api/request.rb +26 -0
- data/lib/gnip_api/response.rb +35 -0
- data/lib/gnip_api/version.rb +1 -1
- data/lib/gnip_api.rb +31 -0
- data/spec/fixtures/activities/full_activity.json +227 -0
- data/spec/fixtures/activities/nil_urls.json +1 -0
- data/spec/fixtures/activities/real_activity.json +127 -0
- data/spec/fixtures/activities/real_activity_long_rules.json +126 -0
- data/spec/fixtures/system_messages/error.json +1 -0
- data/spec/fixtures/system_messages/info.json +1 -0
- data/spec/fixtures/system_messages/warn.json +1 -0
- data/spec/fixtures/twitter_messages/quote.json +219 -0
- data/spec/fixtures/twitter_messages/retweet.json +418 -0
- data/spec/fixtures/twitter_messages/retweet_long_rules.json +417 -0
- data/spec/fixtures/twitter_messages/scrub_geo.json +11 -0
- data/spec/fixtures/twitter_messages/status_delete.json +11 -0
- data/spec/fixtures/twitter_messages/status_withheld.json +11 -0
- data/spec/fixtures/twitter_messages/tweet.json +233 -0
- data/spec/fixtures/twitter_messages/tweet_long_rules.json +232 -0
- data/spec/fixtures/twitter_messages/user_delete.json +7 -0
- data/spec/fixtures/twitter_messages/user_protect.json +7 -0
- data/spec/fixtures/twitter_messages/user_suspend.json +7 -0
- data/spec/fixtures/twitter_messages/user_undelete.json +7 -0
- data/spec/fixtures/twitter_messages/user_unprotect.json +7 -0
- data/spec/fixtures/twitter_messages/user_unsuspend.json +7 -0
- data/spec/fixtures/twitter_messages/user_withheld.json +10 -0
- data/spec/gnip_api/adapter_spec.rb +78 -0
- data/spec/gnip_api/adapters/base_adapter_spec.rb +0 -0
- data/spec/gnip_api/adapters/httparty_adapter_spec.rb +0 -0
- data/spec/gnip_api/apis/power_track/rule_spec.rb +62 -0
- data/spec/gnip_api/apis/power_track/rules_spec.rb +70 -0
- data/spec/gnip_api/apis/power_track/stream_spec.rb +50 -0
- data/spec/gnip_api/gnip/activity_spec.rb +123 -0
- data/spec/gnip_api/gnip/gnip_data_spec.rb +108 -0
- data/spec/gnip_api/gnip/message_spec.rb +48 -0
- data/spec/gnip_api/limiters/rules_spec.rb +74 -0
- data/spec/gnip_api/request_spec.rb +33 -0
- data/spec/gnip_api/response_spec.rb +32 -0
- data/spec/lib/test_adapter.rb +16 -0
- data/spec/spec_helper.rb +8 -0
- metadata +103 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74edd623bf1f6bb85470235633add59192a90448
|
4
|
+
data.tar.gz: 51786aa16a0f9df12bf3e44595441096e0e0db1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e49dafce62bb9f34c05127676b6099ee687c35667d849d609e241cf198c11196069b41f7ab979ee3a67a5f56d670bf4fd07cf7a1a5f1642aa367ff56724427f2
|
7
|
+
data.tar.gz: c88927e42d3da21e5b8ebd59ae391733d8f79a50e5d42c77c21498368a161827790329da94a80a100b66856a4f91b5c302407235d0c9ba72edce2434ee489aff
|
data/.gitignore
CHANGED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
gnip_api
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.1.0
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
gnip_api (0.0.
|
4
|
+
gnip_api (0.0.2)
|
5
5
|
activesupport
|
6
6
|
httparty
|
7
7
|
json
|
@@ -45,6 +45,7 @@ GEM
|
|
45
45
|
rspec-support (3.0.3)
|
46
46
|
slop (3.6.0)
|
47
47
|
thread_safe (0.3.5)
|
48
|
+
timecop (0.7.1)
|
48
49
|
tzinfo (1.2.2)
|
49
50
|
thread_safe (~> 0.1)
|
50
51
|
|
@@ -58,3 +59,7 @@ DEPENDENCIES
|
|
58
59
|
pry
|
59
60
|
rake (~> 10.0)
|
60
61
|
rspec
|
62
|
+
timecop
|
63
|
+
|
64
|
+
BUNDLED WITH
|
65
|
+
1.10.4
|
data/README.md
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
# GnipApi
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
Connect with different Gnip APIs and get data from streams.
|
4
|
+
|
5
|
+
## Notes
|
6
|
+
|
7
|
+
- Can't access Search API currently
|
8
|
+
- Rules endpoint are now rate limited.
|
9
|
+
- A simple rate limiter was implemented.
|
10
|
+
- You can configure the gem's mutex outside the gem if you plan to have concurrency. Very experimental for now.
|
6
11
|
|
7
12
|
## Installation
|
8
13
|
|
@@ -22,7 +27,39 @@ Or install it yourself as:
|
|
22
27
|
|
23
28
|
## Usage
|
24
29
|
|
25
|
-
|
30
|
+
### Configure the gem
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
GnipApi.configure |config|
|
34
|
+
config.user = 'someone' # Gnip Account Username
|
35
|
+
config.password = 'something' # Gnip Password
|
36
|
+
config.account = 'myGnipAccount' # Your accounts name
|
37
|
+
config.adapter_class = SomeAdapter # You can define your own adapter, more in the following section
|
38
|
+
config.logger = Logger.new('myLog.log') # You can also provide a custom logger
|
39
|
+
config.mutex = Mutex.new # Experimental thread safety, more below
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
Put the avobe code in a initializer if you're using Rails, or somewhere else if you aren't. After that you can interact with Gnip APIs.
|
44
|
+
|
45
|
+
Note that you'll need a source and a label. Source is the data source within Gnip, such as Twitter, and label is the identifier of your stream.
|
46
|
+
|
47
|
+
### Adapters
|
48
|
+
|
49
|
+
GnipApi is not dependent of a single adapter (there's a dependency with HTTParty, but shhh... it won't last too long). You can use one of the provided adapters, or you can make your own, using the BaseAdapter class. You only need to implement the desired connector POST, GET and DELETE methods. There's an extra stream_get method, but it's just a variant of GET.
|
50
|
+
|
51
|
+
The custom adapter does not require to live within the gem files, as long as GnipApi has access to your class, just put it in the config and you're ready to go. See the current adapters for reference.
|
52
|
+
|
53
|
+
### Mutex and Thread Safety
|
54
|
+
|
55
|
+
GnipApi has this feature in experimental stage, using a simple mutex to interact with the RateLimiter. The limiters are very simple, and should prevent your code executing more requests than it should. Depending where you are defining the mutex, you can elevate the coverage. GnipApi only requires an instance of Mutex, which you can place somewhere else for it to use.
|
56
|
+
|
57
|
+
## WIP State
|
58
|
+
|
59
|
+
GnipApi is still a WIP. Call it a beta, alpha, gem that has part of the features, whatever. Thing is, that it is currently usable. The custom adapter feature is there, and some of the APIs of Gnip were implemented. I'll be coding more things into this, such as other APIs, more limiters, request retries, error handling, different adapters for known connectors like RestClient or HTTP/net, etc.
|
60
|
+
|
61
|
+
In any case, you were warned about it. Feel free to fill my issues list on Github :)
|
62
|
+
|
26
63
|
|
27
64
|
## Contributing
|
28
65
|
|
@@ -31,3 +68,5 @@ TODO
|
|
31
68
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
32
69
|
4. Push to the branch (`git push origin my-new-feature`)
|
33
70
|
5. Create a new Pull Request
|
71
|
+
|
72
|
+
This library was constructed with the help of [Armando Andini](https://github.com/antico5) who provided the basis to connect with the Gnip APIs.
|
data/gnip_api.gemspec
CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_development_dependency "pry"
|
24
24
|
spec.add_development_dependency "awesome_print"
|
25
25
|
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "timecop"
|
26
27
|
|
27
28
|
spec.add_dependency "httparty"
|
28
29
|
spec.add_dependency "json"
|
data/lib/gnip_api/adapter.rb
CHANGED
@@ -1,40 +1,62 @@
|
|
1
1
|
module GnipApi
|
2
2
|
class Adapter
|
3
|
+
GET = 'GET'
|
4
|
+
POST = 'POST'
|
5
|
+
DELETE = 'DELETE'
|
6
|
+
|
3
7
|
attr_reader :adapter
|
4
8
|
|
5
9
|
def initialize
|
6
|
-
|
10
|
+
raise GnipApi::Errors::MissingCredentials unless GnipApi.credentials?
|
11
|
+
raise GnipApi::Errors::MissingAdapter unless GnipApi.adapter_class?
|
12
|
+
@adapter = GnipApi.config.adapter_class.new
|
13
|
+
@logger = GnipApi.config.logger
|
7
14
|
end
|
8
15
|
|
9
|
-
def get
|
10
|
-
|
16
|
+
def get request
|
17
|
+
log_request(request)
|
18
|
+
response = adapter.get(request)
|
19
|
+
check_response_for_errors(response)
|
20
|
+
return response.body unless response.body.empty?
|
21
|
+
return true
|
11
22
|
end
|
12
23
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
|
24
|
+
def post request
|
25
|
+
log_request(request)
|
26
|
+
response = adapter.post(request)
|
27
|
+
check_response_for_errors(response)
|
28
|
+
return response.body unless response.body.empty?
|
29
|
+
return true
|
17
30
|
end
|
18
|
-
end
|
19
31
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
32
|
+
def delete request
|
33
|
+
log_request(request)
|
34
|
+
response = adapter.delete(request)
|
35
|
+
check_response_for_errors(response)
|
36
|
+
return response.body unless response.body.empty?
|
37
|
+
return true
|
38
|
+
end
|
27
39
|
|
28
|
-
|
29
|
-
|
40
|
+
def stream_get request
|
41
|
+
log_request(request)
|
42
|
+
adapter.stream_get(request) do |data|
|
43
|
+
yield(data)
|
30
44
|
end
|
45
|
+
end
|
31
46
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
47
|
+
def check_response_for_errors response
|
48
|
+
if response.ok?
|
49
|
+
@logger.info "#{response.request_method} request to #{response.request_uri} returned with status #{response.status} OK"
|
50
|
+
else
|
51
|
+
error_message = response.error_message
|
52
|
+
@logger.error "#{response.request_method} request to #{response.request_uri} returned with status #{response.status} FAIL: #{error_message}"
|
53
|
+
raise GnipApi::Errors::Adapter::RequestError.new, error_message
|
37
54
|
end
|
38
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def log_request request
|
59
|
+
@logger.info "Starting #{request.request_method} request to #{request.uri}"
|
60
|
+
end
|
39
61
|
end
|
40
62
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# BaseAdapter should be used on any adapter for this gem. In order
|
2
|
+
# to create your own adapter you must inherit this class to
|
3
|
+
# let your adapter use the provided functionality of the gem. In
|
4
|
+
# other words, this just defines basic methods to provide the
|
5
|
+
# custom adapter with basic data.
|
6
|
+
#
|
7
|
+
# To create a custom adapter, create your class, and implement the
|
8
|
+
# following methods that GnipApi::Adapter will need.
|
9
|
+
#
|
10
|
+
# - #get
|
11
|
+
# - #post
|
12
|
+
# - #delete
|
13
|
+
# - #stream_get
|
14
|
+
#
|
15
|
+
# All single-request methods (stream_get not included), should
|
16
|
+
# return a GnipApi::Response object with:
|
17
|
+
#
|
18
|
+
# - status: integer value for status code (200, 403, etc)
|
19
|
+
# - body: raw body, no matter if it's json or xml, the implementation of the api will know this
|
20
|
+
# - headers: a hash with the response headers
|
21
|
+
#
|
22
|
+
# The response object is an effort to standarize the data and let Gnip::Adapter
|
23
|
+
# operate without the concern of the data format. The helper method to create
|
24
|
+
# this response is available in this class, and will be available to your class
|
25
|
+
# when you write your adapter.
|
26
|
+
#
|
27
|
+
# The process of parsing the headers to a hash, setting authorization headers or
|
28
|
+
# parsing response data to break it down to status, body and headers are responsabilities
|
29
|
+
# of your custom adapter class.
|
30
|
+
#
|
31
|
+
# Gnip::Adapter will pass your adapter a Gnip::Request object that contains:
|
32
|
+
#
|
33
|
+
# - uri: URI object with url, schema, etc
|
34
|
+
# - payload: a parsed text to send in the request's body
|
35
|
+
# - headers: a hash that may contain additional headers
|
36
|
+
#
|
37
|
+
# Your adapter should process this object and translate it into a relevant request for
|
38
|
+
# your desired connector. Note that payload and headers may be nil if not needed.
|
39
|
+
#
|
40
|
+
# Last thing to denote, GnipApi::Adapter will expect an instance of your adapter to use.
|
41
|
+
# What you do inside your adapter or how you implement a specific adapter is up to you.
|
42
|
+
|
43
|
+
module GnipApi
|
44
|
+
module Adapters
|
45
|
+
class BaseAdapter
|
46
|
+
def username
|
47
|
+
GnipApi.configuration.user
|
48
|
+
end
|
49
|
+
|
50
|
+
def password
|
51
|
+
GnipApi.configuration.password
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_response request, status, body, headers
|
55
|
+
GnipApi::Response.new request, status, body, headers
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,6 +1,38 @@
|
|
1
1
|
module GnipApi
|
2
2
|
module Adapters
|
3
|
-
class HTTPartyAdapter
|
3
|
+
class HTTPartyAdapter < GnipApi::Adapters::BaseAdapter
|
4
|
+
def post request
|
5
|
+
data = HTTParty.post request.uri, :basic_auth => auth, :body => request.payload
|
6
|
+
return response(request, data)
|
7
|
+
end
|
8
|
+
|
9
|
+
def delete request
|
10
|
+
data = HTTParty.delete request.uri, :basic_auth => auth, :body => request.payload
|
11
|
+
return response(request, data)
|
12
|
+
end
|
13
|
+
|
14
|
+
def get request
|
15
|
+
data = HTTParty.get request.uri, :basic_auth => auth
|
16
|
+
return response(request, data)
|
17
|
+
end
|
18
|
+
|
19
|
+
def stream_get request
|
20
|
+
HTTParty.get request.uri, :headers => request.headers, :basic_auth => auth do |data|
|
21
|
+
yield(data)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def auth
|
26
|
+
{
|
27
|
+
:username => username,
|
28
|
+
:password => password
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def response request, data
|
33
|
+
create_response request, data.code, data.body, data.headers
|
34
|
+
end
|
35
|
+
|
4
36
|
end
|
5
37
|
end
|
6
38
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module GnipApi
|
2
|
+
module Apis
|
3
|
+
module PowerTrack
|
4
|
+
class Rule
|
5
|
+
attr_accessor :value, :tag
|
6
|
+
|
7
|
+
def initialize params={}
|
8
|
+
@value = params[:value] || params['value']
|
9
|
+
@tag = params[:tag] || params['tag']
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_json
|
13
|
+
attributes.to_json
|
14
|
+
end
|
15
|
+
|
16
|
+
def attributes
|
17
|
+
attrs = {}
|
18
|
+
attrs[:value] = @value if @value
|
19
|
+
attrs[:tag] = @tag if @tag
|
20
|
+
attrs
|
21
|
+
end
|
22
|
+
|
23
|
+
def uid
|
24
|
+
rule = @value
|
25
|
+
rule += "tag:#{@tag}" if @tag
|
26
|
+
Digest::SHA2.hexdigest(rule)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,15 +1,82 @@
|
|
1
|
+
# Gnip PowerTrack Rules API
|
2
|
+
#
|
3
|
+
# Create, delete and list rules of a powetrack stream.
|
4
|
+
|
1
5
|
module GnipApi
|
2
6
|
module Apis
|
3
7
|
module PowerTrack
|
4
8
|
class Rules
|
5
9
|
attr_reader :adapter
|
6
10
|
|
7
|
-
|
11
|
+
# In order to do any operation, you need to specify:
|
12
|
+
# - label: the label of your stream
|
13
|
+
# - source: which data source to use (I think only twitter is available)
|
14
|
+
def initialize params={}
|
8
15
|
@adapter = GnipApi::Adapter.new
|
16
|
+
@label = params[:label]
|
17
|
+
@source = params[:source]
|
9
18
|
end
|
10
19
|
|
20
|
+
# Returns an array of defined rules
|
11
21
|
def list
|
12
|
-
|
22
|
+
request_allowed?
|
23
|
+
request = create_get_request
|
24
|
+
rules = adapter.get(request)
|
25
|
+
parse_rules(rules)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates the specified rule. Parameters:
|
29
|
+
# - rules: GnipApi::Apis::PowerTrack::Rule object
|
30
|
+
def create rules
|
31
|
+
raise GnipApi::Errors::PowerTrack::MissingRules.new if rules.nil? || rules.empty?
|
32
|
+
request_allowed?
|
33
|
+
request = create_post_request(construct_rules(rules))
|
34
|
+
adapter.post(request)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Deletes the specified rule. Parameters:
|
38
|
+
# - rules: GnipApi::Apis::PowerTrack::Rule object
|
39
|
+
def delete rules
|
40
|
+
raise GnipApi::Errors::PowerTrack::MissingRules.new if rules.nil? || rules.empty?
|
41
|
+
request_allowed?
|
42
|
+
request = create_delete_request(construct_rules(rules))
|
43
|
+
adapter.delete(request)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Parses an array of GnipApi::Apis::PowerTrack::Rule objects
|
47
|
+
# to the necesary JSON format for the endpoint
|
48
|
+
def construct_rules rules
|
49
|
+
parsed_rules = {:rules => []}
|
50
|
+
rules.each do |rule|
|
51
|
+
parsed_rules[:rules] << rule.attributes
|
52
|
+
end
|
53
|
+
parsed_rules.to_json
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_rules data
|
57
|
+
parsed_data = JSON.parse(data)
|
58
|
+
parsed_data['rules'].map{|rule| GnipApi::Apis::PowerTrack::Rule.new(:value => rule['value'], :tag => rule['tag'])}
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def endpoint
|
63
|
+
GnipApi::Endpoints.powertrack_rules(@source, @label)
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_get_request
|
67
|
+
GnipApi::Request.new_get(endpoint)
|
68
|
+
end
|
69
|
+
|
70
|
+
def create_post_request payload
|
71
|
+
GnipApi::Request.new_post(endpoint, payload)
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_delete_request payload
|
75
|
+
GnipApi::Request.new_delete(endpoint, payload)
|
76
|
+
end
|
77
|
+
|
78
|
+
def request_allowed?
|
79
|
+
raise 'RateLimited' unless GnipApi.config.rate_limiter.rules_request_allowed?
|
13
80
|
end
|
14
81
|
end
|
15
82
|
end
|
@@ -2,7 +2,7 @@ module GnipApi
|
|
2
2
|
module Apis
|
3
3
|
module PowerTrack
|
4
4
|
class Stream
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :adapter
|
6
6
|
|
7
7
|
def initialize params = {}
|
8
8
|
@stream = params[:stream]
|
@@ -15,15 +15,53 @@ module GnipApi
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def consume
|
18
|
-
|
18
|
+
request = create_request
|
19
|
+
adapter.stream_get request do |chunk|
|
19
20
|
@buffer.insert! chunk
|
20
|
-
|
21
|
+
begin
|
22
|
+
yield process_entries(@buffer.read!)
|
23
|
+
rescue Exception => e
|
24
|
+
puts e.class
|
25
|
+
puts e.message
|
26
|
+
puts e.backtrace[0..10].join("\n")
|
27
|
+
raise e
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def process_entries entries
|
33
|
+
entries.map!{|e| parse_json(e)}.compact!
|
34
|
+
entries.map!{|e| build_message(e)}
|
35
|
+
log_system_messages(entries)
|
36
|
+
entries
|
37
|
+
end
|
38
|
+
|
39
|
+
def log_system_messages entries
|
40
|
+
entries.select{|message| message.system_message? }.each do |system_message|
|
41
|
+
GnipApi.logger.send(system_message.log_method, system_message.message)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_message params
|
46
|
+
Gnip::Message.build(params)
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse_json json
|
50
|
+
begin
|
51
|
+
JSON.parse json
|
52
|
+
rescue JSON::ParserError
|
53
|
+
nil
|
21
54
|
end
|
22
55
|
end
|
23
56
|
|
24
57
|
private
|
58
|
+
def create_request
|
59
|
+
GnipApi::Request.new_get(endpoint, {'Accept-Encoding' => 'gzip'})
|
60
|
+
end
|
25
61
|
|
26
62
|
def set_config
|
63
|
+
raise 'MissingStream' if @stream.nil?
|
64
|
+
raise 'MissingSource' if @source.nil?
|
27
65
|
@user = GnipApi.configuration.user
|
28
66
|
@password = GnipApi.configuration.password
|
29
67
|
@account = GnipApi.configuration.account
|
@@ -31,29 +69,10 @@ module GnipApi
|
|
31
69
|
@buffer = GnipApi::Apis::PowerTrack::Buffer.new
|
32
70
|
end
|
33
71
|
|
34
|
-
def handle message
|
35
|
-
@system_messages << message if message.system_message?
|
36
|
-
yield message if message.activity?
|
37
|
-
end
|
38
|
-
|
39
72
|
def endpoint
|
40
73
|
GnipApi::Endpoints.powertrack_stream(@source, @stream)
|
41
74
|
end
|
42
75
|
|
43
|
-
def parse data
|
44
|
-
json_parse(extract_messages(data)).map { |hash| Message.build hash }
|
45
|
-
end
|
46
|
-
|
47
|
-
def json_parse messages
|
48
|
-
messages.map do |message|
|
49
|
-
begin
|
50
|
-
JSON.parse message
|
51
|
-
rescue JSON::ParserError
|
52
|
-
nil
|
53
|
-
end
|
54
|
-
end.compact
|
55
|
-
end
|
56
|
-
|
57
76
|
end
|
58
77
|
end
|
59
78
|
end
|
File without changes
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module GnipApi
|
2
|
+
module Apis
|
3
|
+
module Search
|
4
|
+
class Query
|
5
|
+
attr_accessor :rules, :from_date, :to_date, :max_results, :next, :publisher
|
6
|
+
|
7
|
+
def initialize params={}
|
8
|
+
@rules = params[:rules]
|
9
|
+
@from_date = params[:from_date]
|
10
|
+
@to_date = params[:to_date]
|
11
|
+
@max_results = params[:max_results]
|
12
|
+
@next = params[:next]
|
13
|
+
@publisher = params[:publisher]
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_json
|
17
|
+
hash = {}
|
18
|
+
hash['query'] = @rules
|
19
|
+
hash['publisher'] = @publisher
|
20
|
+
hash['fromDate'] = @from_date.to_time.utc.strftime('%Y%m%d%H%M') if @from_date
|
21
|
+
hash['toDate'] = @to_date.to_time.utc.strftime('%Y%m%d%H%M') if @to_date
|
22
|
+
hash['next'] = @next if @next
|
23
|
+
hash['maxResults'] = @max_results if @max_results
|
24
|
+
hash.to_json
|
25
|
+
end
|
26
|
+
|
27
|
+
def valid?
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def validate
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module GnipApi
|
2
|
+
module Apis
|
3
|
+
module Search
|
4
|
+
class Result
|
5
|
+
attr_reader :activities, :response
|
6
|
+
|
7
|
+
def initialize response
|
8
|
+
@response = response
|
9
|
+
end
|
10
|
+
|
11
|
+
def activities
|
12
|
+
@activities ||= response['results'].map { |activity| Activity.new(activity) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module GnipApi
|
2
|
+
module Apis
|
3
|
+
module Search
|
4
|
+
class Stream
|
5
|
+
attr_accessor :query, :label
|
6
|
+
|
7
|
+
def initialize options={}
|
8
|
+
@query = options[:query]
|
9
|
+
@label = options[:label]
|
10
|
+
@adapter = GnipApi::Adapter.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def perform
|
14
|
+
response = @adapter.post search_url, @query.to_json
|
15
|
+
Result.new response
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def search_url
|
21
|
+
GnipApi::Endpoints.search_stream(@label)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module GnipApi
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :user, :password, :adapter_class, :account, :logger
|
3
|
+
attr_accessor :user, :password, :adapter_class, :account, :logger, :mutex
|
4
|
+
attr_reader :rate_limiter
|
4
5
|
|
5
6
|
def initialize
|
6
7
|
@adapter_class = GnipApi::Adapters::HTTPartyAdapter
|
7
8
|
@logger = Logger.new('tmp/gnip_api.log')
|
9
|
+
@mutex = Mutex.new
|
10
|
+
@rate_limiter = GnipApi::RateLimiter.new
|
8
11
|
end
|
9
12
|
end
|
10
13
|
end
|
data/lib/gnip_api/endpoints.rb
CHANGED
@@ -2,11 +2,24 @@ module GnipApi
|
|
2
2
|
class Endpoints
|
3
3
|
class << self
|
4
4
|
def powertrack_rules source, label
|
5
|
-
URI("https://api.gnip.com:443/accounts/#{
|
5
|
+
URI("https://api.gnip.com:443/accounts/#{account}/publishers/#{source}/streams/track/#{label}/rules.json")
|
6
6
|
end
|
7
7
|
|
8
8
|
def powertrack_stream source, label
|
9
|
-
URI("https://stream.gnip.com:443/accounts/#{
|
9
|
+
URI("https://stream.gnip.com:443/accounts/#{account}/publishers/#{source}/streams/track/#{label}.json")
|
10
|
+
end
|
11
|
+
|
12
|
+
def search_stream label
|
13
|
+
URI("https://search.gnip.com/accounts/#{account}/search/#{label}.json")
|
14
|
+
end
|
15
|
+
|
16
|
+
def search_count
|
17
|
+
URI("https://search.gnip.com/accounts/#{ CONFIG['account'] }/search/#{label}.json/counts")
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def account
|
22
|
+
GnipApi.configuration.account
|
10
23
|
end
|
11
24
|
end
|
12
25
|
end
|