twingly-search 5.2.0 → 5.3.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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -15
- data/CHANGELOG.md +7 -0
- data/README.md +13 -4
- data/examples/find_all_posts_mentioning_github.rb +8 -2
- data/lib/twingly/livefeed.rb +2 -0
- data/lib/twingly/livefeed/client.rb +5 -3
- data/lib/twingly/livefeed/error.rb +6 -1
- data/lib/twingly/livefeed/parser.rb +6 -3
- data/lib/twingly/livefeed/post.rb +8 -4
- data/lib/twingly/livefeed/result.rb +13 -9
- data/lib/twingly/livefeed/version.rb +3 -1
- data/lib/twingly/search.rb +2 -0
- data/lib/twingly/search/client.rb +4 -2
- data/lib/twingly/search/error.rb +12 -2
- data/lib/twingly/search/parser.rb +6 -3
- data/lib/twingly/search/post.rb +8 -4
- data/lib/twingly/search/query.rb +9 -2
- data/lib/twingly/search/result.rb +11 -5
- data/lib/twingly/search/version.rb +3 -1
- data/profiler/fixtures/vcr_cassettes/blog_livefeed_100.yml +43 -0
- data/profiler/fixtures/vcr_cassettes/blog_search_100.yml +43 -0
- data/profiler/profile_helper.rb +18 -0
- data/profiler/profile_livefeed.rb +21 -0
- data/profiler/profile_search.rb +23 -0
- data/spec/client_spec.rb +3 -3
- data/spec/error_spec.rb +4 -0
- data/spec/fixtures/unauthenticated_api_key_result.xml +3 -0
- data/spec/fixtures/unauthorized_api_key_result.xml +3 -3
- data/spec/livefeed/client_spec.rb +2 -2
- data/spec/livefeed/error_spec.rb +1 -0
- data/spec/livefeed/parser_spec.rb +3 -3
- data/spec/livefeed/result_spec.rb +22 -8
- data/spec/parser_spec.rb +11 -3
- data/spec/result_spec.rb +20 -6
- data/twingly-search-api-ruby.gemspec +3 -1
- metadata +39 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 816d2bcb38d40a6f83dd9c815f3eded749735d06c16e66910c9d19eccda14a56
|
4
|
+
data.tar.gz: 3d70d46edfa3c201e06fc36292498a3669ad63c9bbf0a6b509b758efa2d23138
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf6d1617263939de594f571031ee98fb0ed592838e0d53a5a221850511f7e948992af2e59c3630c8311fec0f53cf6d29f9a1a3594bc17d324817b6c284acd56c
|
7
|
+
data.tar.gz: 67c9e8cd2b7180fbe34401b16cab2d6a0f79ed5764d356843bce1b520f7473e787a8d3d47dcb88a34b94c7c2e92ce2af285974e82c5558e6d734ee80132b6f94
|
data/.travis.yml
CHANGED
@@ -4,20 +4,9 @@ before_install:
|
|
4
4
|
- gem update bundler
|
5
5
|
cache: bundler
|
6
6
|
rvm:
|
7
|
-
- 2.
|
8
|
-
- 2.
|
9
|
-
- 2.
|
10
|
-
- 2.
|
11
|
-
- 2.5.0
|
12
|
-
- jruby-9.0.5.0
|
13
|
-
- jruby-9.1.15.0
|
7
|
+
- 2.4.6
|
8
|
+
- 2.5.5
|
9
|
+
- 2.6.2
|
10
|
+
- jruby-9.2.6.0
|
14
11
|
notifications:
|
15
12
|
email: false
|
16
|
-
hipchat:
|
17
|
-
on_success: never
|
18
|
-
on_failure: change
|
19
|
-
template:
|
20
|
-
- '%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message} (<a href="%{build_url}">Details</a>/<a href="%{compare_url}">Change view</a>)'
|
21
|
-
format: html
|
22
|
-
rooms:
|
23
|
-
secure: KU2mE9mcqvBczfiCTgTsgMmJPyW02AH/0Rzcli7oj3HVbiHGw8t5JlBQWYROF5TPht0kFhGkiwVPl6HUt/VAGxOIBsOp+/8MXR6aK5FkdIw6g8DMKlDjm9a2QijOT9rvat5bZ3l6hm3snojgkI3s9pLKmLq9l+KalAsPcevwKAQ=
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [v5.2.0](https://github.com/twingly/twingly-search-api-ruby/tree/v5.2.0) (2018-05-17)
|
4
|
+
[Full Changelog](https://github.com/twingly/twingly-search-api-ruby/compare/v5.1.4...v5.2.0)
|
5
|
+
|
6
|
+
**Merged pull requests:**
|
7
|
+
|
8
|
+
- Add Post\#to\_h for both LiveFeed and Search [\#77](https://github.com/twingly/twingly-search-api-ruby/pull/77) ([dentarg](https://github.com/dentarg))
|
9
|
+
|
3
10
|
## [v5.1.4](https://github.com/twingly/twingly-search-api-ruby/tree/v5.1.4) (2018-02-23)
|
4
11
|
[Full Changelog](https://github.com/twingly/twingly-search-api-ruby/compare/v5.1.3...v5.1.4)
|
5
12
|
|
data/README.md
CHANGED
@@ -46,7 +46,7 @@ query = client.query do |query|
|
|
46
46
|
end
|
47
47
|
|
48
48
|
result = query.execute
|
49
|
-
=> #<Twingly::Search::Result:
|
49
|
+
=> #<Twingly::Search::Result:0x3fca8ad3aa60 posts, number_of_matches_returned=10, number_of_matches_total=281, incomplete_result=false, seconds_elapsed=0.239, all_results_returned?=false, incomplete?=false>
|
50
50
|
result.posts # will include all returned posts
|
51
51
|
```
|
52
52
|
|
@@ -64,7 +64,7 @@ end
|
|
64
64
|
|
65
65
|
# get the next chunk of posts
|
66
66
|
result = client.next_result
|
67
|
-
=> #<Twingly::LiveFeed::Result:
|
67
|
+
=> #<Twingly::LiveFeed::Result:0x3fca8ad4e81c posts, ts=2019-03-27 12:52:54 UTC, from=2019-03-27 11:52:53 UTC, number_of_posts=709, max_number_of_posts=1000, first_post=2019-03-27 11:53:02 UTC, last_post=2019-03-27 12:52:42 UTC, next_timestamp=2019-03-27 12:52:42 UTC>
|
68
68
|
|
69
69
|
result.posts # will include all returned posts
|
70
70
|
```
|
@@ -73,8 +73,8 @@ result.posts # will include all returned posts
|
|
73
73
|
|
74
74
|
* API key, [sign up](https://www.twingly.com/try-for-free) via [twingly.com](https://www.twingly.com/) to get one
|
75
75
|
* Ruby
|
76
|
-
* Ruby
|
77
|
-
* JRuby
|
76
|
+
* Ruby >= 2.4
|
77
|
+
* JRuby >= 9.2
|
78
78
|
|
79
79
|
## Development
|
80
80
|
|
@@ -88,6 +88,15 @@ Run the tests
|
|
88
88
|
|
89
89
|
bundle exec rake
|
90
90
|
|
91
|
+
### Profiling
|
92
|
+
|
93
|
+
It's possible to profile memory and object allocation:
|
94
|
+
|
95
|
+
bundle exec ruby profiler/profile_livefeed.rb
|
96
|
+
bundle exec ruby profiler/profile_search.rb
|
97
|
+
|
98
|
+
Currently using [memory_profiler](https://github.com/SamSaffron/memory_profiler) for reports and [VCR](https://github.com/vcr/vcr) for saving requests (to make runs comparable).
|
99
|
+
|
91
100
|
### Release
|
92
101
|
|
93
102
|
1. Make a commit bumping the version in `lib/twingly/search/version.rb`, follow [Semantic Versioning 2.0.0](http://semver.org/). No need to push as this will be taken care of automatically in the next step.
|
@@ -8,8 +8,14 @@ class SearchPostStream
|
|
8
8
|
end
|
9
9
|
|
10
10
|
@query = client.query do |query|
|
11
|
-
|
12
|
-
|
11
|
+
query_parts = [
|
12
|
+
"sort-order:asc",
|
13
|
+
"sort:published",
|
14
|
+
keyword,
|
15
|
+
]
|
16
|
+
query_parts << "lang:#{language}" if language
|
17
|
+
|
18
|
+
query.search_query = query_parts.join(" ")
|
13
19
|
end
|
14
20
|
end
|
15
21
|
|
data/lib/twingly/livefeed.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "faraday"
|
2
4
|
require "time"
|
3
5
|
|
@@ -30,7 +32,7 @@ module Twingly
|
|
30
32
|
# @option options [String] :max_posts the maximum number of posts that can
|
31
33
|
# be returned for each request
|
32
34
|
# @option options [String] :timestamp the timestamp to start the client at
|
33
|
-
# @raise [
|
35
|
+
# @raise [AuthenticationError] if an API key is not set
|
34
36
|
def initialize(api_key = nil, options = {})
|
35
37
|
@api_key = api_key
|
36
38
|
@user_agent = options.fetch(:user_agent) { DEFAULT_USER_AGENT }
|
@@ -49,7 +51,7 @@ module Twingly
|
|
49
51
|
# then returns the result.
|
50
52
|
#
|
51
53
|
# @raise [QueryError] if the timestamp is invalid.
|
52
|
-
# @raise [
|
54
|
+
# @raise [AuthenticationError] if the API couldn't authenticate you. Make sure your API key is correct.
|
53
55
|
# @raise [ServerError] if the query could not be executed due to a server error.
|
54
56
|
# @return [Result] the result for this request.
|
55
57
|
def next_result
|
@@ -110,7 +112,7 @@ module Twingly
|
|
110
112
|
end
|
111
113
|
|
112
114
|
def api_key_missing
|
113
|
-
fail
|
115
|
+
fail AuthenticationError, "No API key has been provided."
|
114
116
|
end
|
115
117
|
|
116
118
|
def assert_valid_time(time)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Twingly
|
2
4
|
module LiveFeed
|
3
5
|
class Error < StandardError
|
@@ -7,7 +9,7 @@ module Twingly
|
|
7
9
|
when /^400/, /^404/
|
8
10
|
QueryError
|
9
11
|
when /^401/
|
10
|
-
|
12
|
+
AuthenticationError
|
11
13
|
else
|
12
14
|
ServerError
|
13
15
|
end
|
@@ -19,6 +21,9 @@ module Twingly
|
|
19
21
|
class AuthError < Error
|
20
22
|
end
|
21
23
|
|
24
|
+
class AuthenticationError < AuthError
|
25
|
+
end
|
26
|
+
|
22
27
|
class ServerError < Error
|
23
28
|
end
|
24
29
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'nokogiri'
|
2
4
|
|
3
5
|
module Twingly
|
@@ -45,9 +47,10 @@ module Twingly
|
|
45
47
|
def parse_post(element)
|
46
48
|
post_params = {}
|
47
49
|
element.element_children.each do |child|
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
name = child.name.freeze
|
51
|
+
post_params[name] =
|
52
|
+
case name
|
53
|
+
when "tags", "links", "images"
|
51
54
|
parse_array(child)
|
52
55
|
when "coordinates"
|
53
56
|
parse_coordinates(child)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Twingly
|
4
5
|
module LiveFeed
|
@@ -36,6 +37,9 @@ module Twingly
|
|
36
37
|
:published_at, :reindexed_at, :inlinks_count, :blog_id, :blog_name,
|
37
38
|
:blog_url, :blog_rank, :authority
|
38
39
|
|
40
|
+
EMPTY_ARRAY = [].freeze
|
41
|
+
EMPTY_HASH = {}.freeze
|
42
|
+
|
39
43
|
# Sets all instance variables for the {Post}, given a Hash.
|
40
44
|
#
|
41
45
|
# @param [Hash] params containing blog post data.
|
@@ -47,10 +51,10 @@ module Twingly
|
|
47
51
|
@text = params.fetch('text')
|
48
52
|
@language_code = params.fetch('languageCode')
|
49
53
|
@location_code = params.fetch('locationCode')
|
50
|
-
@coordinates = params.fetch('coordinates'
|
51
|
-
@links = params.fetch('links'
|
52
|
-
@tags = params.fetch('tags'
|
53
|
-
@images = params.fetch('images'
|
54
|
+
@coordinates = params.fetch('coordinates') { EMPTY_HASH }
|
55
|
+
@links = params.fetch('links') { EMPTY_ARRAY }
|
56
|
+
@tags = params.fetch('tags') { EMPTY_ARRAY }
|
57
|
+
@images = params.fetch('images') { EMPTY_ARRAY }
|
54
58
|
@indexed_at = Time.parse(params.fetch('indexedAt'))
|
55
59
|
@published_at = Time.parse(params.fetch('publishedAt'))
|
56
60
|
@reindexed_at = Time.parse(params.fetch('reindexedAt'))
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Twingly
|
2
4
|
module LiveFeed
|
3
5
|
# Represents a result from a request to the LiveFeed API
|
@@ -23,16 +25,18 @@ module Twingly
|
|
23
25
|
end
|
24
26
|
|
25
27
|
def inspect
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
instance_methods = [
|
29
|
+
"posts",
|
30
|
+
"ts=#{self.ts}",
|
31
|
+
"from=#{self.from}",
|
32
|
+
"number_of_posts=#{self.number_of_posts}",
|
33
|
+
"max_number_of_posts=#{self.max_number_of_posts}",
|
34
|
+
"first_post=#{self.first_post}",
|
35
|
+
"last_post=#{self.last_post}",
|
36
|
+
"next_timestamp=#{self.next_timestamp}",
|
37
|
+
].join(", ")
|
34
38
|
|
35
|
-
sprintf("#<%s:0x%x %s>", self.class.name, __id__,
|
39
|
+
sprintf("#<%s:0x%x %s>", self.class.name, __id__, instance_methods)
|
36
40
|
end
|
37
41
|
end
|
38
42
|
end
|
data/lib/twingly/search.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "faraday"
|
2
4
|
|
3
5
|
module Twingly
|
@@ -19,7 +21,7 @@ module Twingly
|
|
19
21
|
# @param options [Hash]
|
20
22
|
# @option options [String] :user_agent the user agent to be used
|
21
23
|
# for all requests
|
22
|
-
# @raise [
|
24
|
+
# @raise [AuthenticationError] if an API key is not set.
|
23
25
|
def initialize(api_key = nil, options = {})
|
24
26
|
@api_key = api_key
|
25
27
|
@user_agent = options.fetch(:user_agent) { DEFAULT_USER_AGENT }
|
@@ -70,7 +72,7 @@ module Twingly
|
|
70
72
|
end
|
71
73
|
|
72
74
|
def api_key_missing
|
73
|
-
fail
|
75
|
+
fail AuthenticationError, "No API key has been provided."
|
74
76
|
end
|
75
77
|
end
|
76
78
|
end
|
data/lib/twingly/search/error.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Twingly
|
2
4
|
module Search
|
3
5
|
class Error < StandardError
|
@@ -6,8 +8,10 @@ module Twingly
|
|
6
8
|
case code.to_s
|
7
9
|
when /^400/, /^404/
|
8
10
|
QueryError
|
9
|
-
when /^401
|
10
|
-
|
11
|
+
when /^401/ # E.g. API key not enabled
|
12
|
+
AuthenticationError
|
13
|
+
when /^402/ # E.g. language access denied
|
14
|
+
AuthorizationError
|
11
15
|
else
|
12
16
|
ServerError
|
13
17
|
end
|
@@ -19,6 +23,12 @@ module Twingly
|
|
19
23
|
class AuthError < Error
|
20
24
|
end
|
21
25
|
|
26
|
+
class AuthenticationError < AuthError
|
27
|
+
end
|
28
|
+
|
29
|
+
class AuthorizationError < AuthError
|
30
|
+
end
|
31
|
+
|
22
32
|
class ServerError < Error
|
23
33
|
end
|
24
34
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'nokogiri'
|
2
4
|
|
3
5
|
module Twingly
|
@@ -43,9 +45,10 @@ module Twingly
|
|
43
45
|
def parse_post(element)
|
44
46
|
post_params = {}
|
45
47
|
element.element_children.each do |child|
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
name = child.name.freeze
|
49
|
+
post_params[name] =
|
50
|
+
case name
|
51
|
+
when "tags", "links", "images"
|
49
52
|
parse_array(child)
|
50
53
|
when "coordinates"
|
51
54
|
parse_coordinates(child)
|
data/lib/twingly/search/post.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module Twingly
|
4
5
|
module Search
|
@@ -35,6 +36,9 @@ module Twingly
|
|
35
36
|
:published_at, :reindexed_at, :inlinks_count, :blog_id, :blog_name,
|
36
37
|
:blog_url, :blog_rank, :authority
|
37
38
|
|
39
|
+
EMPTY_ARRAY = [].freeze
|
40
|
+
EMPTY_HASH = {}.freeze
|
41
|
+
|
38
42
|
# Sets all instance variables for the {Post}, given a Hash.
|
39
43
|
#
|
40
44
|
# @param [Hash] params containing blog post data.
|
@@ -46,10 +50,10 @@ module Twingly
|
|
46
50
|
@text = params.fetch('text')
|
47
51
|
@language_code = params.fetch('languageCode')
|
48
52
|
@location_code = params.fetch('locationCode')
|
49
|
-
@coordinates = params.fetch('coordinates'
|
50
|
-
@links = params.fetch('links'
|
51
|
-
@tags = params.fetch('tags'
|
52
|
-
@images = params.fetch('images'
|
53
|
+
@coordinates = params.fetch('coordinates') { EMPTY_HASH }
|
54
|
+
@links = params.fetch('links') { EMPTY_ARRAY }
|
55
|
+
@tags = params.fetch('tags') { EMPTY_ARRAY }
|
56
|
+
@images = params.fetch('images') { EMPTY_ARRAY }
|
53
57
|
@indexed_at = Time.parse(params.fetch('indexedAt'))
|
54
58
|
@published_at = Time.parse(params.fetch('publishedAt'))
|
55
59
|
@reindexed_at = Time.parse(params.fetch('reindexedAt'))
|
data/lib/twingly/search/query.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "faraday"
|
2
4
|
require "time"
|
3
5
|
|
@@ -48,7 +50,11 @@ module Twingly
|
|
48
50
|
#
|
49
51
|
# @param client [Client] the client that this query should be connected to.
|
50
52
|
def initialize(client)
|
51
|
-
@client
|
53
|
+
@client = client
|
54
|
+
@start_time = nil
|
55
|
+
@end_time = nil
|
56
|
+
@language = nil
|
57
|
+
|
52
58
|
yield self if block_given?
|
53
59
|
end
|
54
60
|
|
@@ -60,7 +66,8 @@ module Twingly
|
|
60
66
|
# Executes the query and returns the result.
|
61
67
|
#
|
62
68
|
# @raise [QueryError] if {#search_query} is empty.
|
63
|
-
# @raise [
|
69
|
+
# @raise [AuthenticationError] if the API couldn't authenticate you. Make sure your API key is correct.
|
70
|
+
# @raise [AuthorizationError] if you don't have access to something.
|
64
71
|
# @raise [ServerError] if the query could not be executed due to a server error.
|
65
72
|
# @return [Result] the result for this query.
|
66
73
|
def execute
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Twingly
|
2
4
|
module Search
|
3
5
|
# Represents a result from a {Query} to the Search API
|
@@ -35,12 +37,16 @@ module Twingly
|
|
35
37
|
end
|
36
38
|
|
37
39
|
def inspect
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
instance_methods = [
|
41
|
+
"posts",
|
42
|
+
"number_of_matches_returned=#{self.number_of_matches_returned}",
|
43
|
+
"number_of_matches_total=#{self.number_of_matches_total}",
|
44
|
+
"seconds_elapsed=#{self.seconds_elapsed}",
|
45
|
+
"all_results_returned?=#{self.all_results_returned?}",
|
46
|
+
"incomplete?=#{self.incomplete?}",
|
47
|
+
].join(", ")
|
42
48
|
|
43
|
-
sprintf("#<%s:0x%x %s>", self.class.name, __id__,
|
49
|
+
sprintf("#<%s:0x%x %s>", self.class.name, __id__, instance_methods)
|
44
50
|
end
|
45
51
|
end
|
46
52
|
end
|