metonym 1.0.0 → 1.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +34 -4
- data/README.md +193 -142
- data/lib/metonym.rb +12 -2
- data/lib/metonym/lib/gnews.rb +49 -47
- data/lib/metonym/lib/news_api.rb +45 -56
- data/lib/metonym/lib/presenters/base_response_presenter.rb +18 -0
- data/lib/metonym/lib/presenters/gnews_response_presenter.rb +5 -0
- data/lib/metonym/lib/presenters/news_api_response_presenter.rb +3 -0
- data/lib/metonym/lib/repositories/base_repository.rb +9 -0
- data/lib/metonym/lib/repositories/gnews_repository.rb +31 -0
- data/lib/metonym/lib/repositories/news_api_repository.rb +31 -0
- data/lib/metonym/lib/validators/base_validator.rb +25 -0
- data/lib/metonym/lib/validators/gnews_query_validator.rb +55 -0
- data/lib/metonym/lib/validators/news_api_query_validator.rb +61 -0
- data/lib/metonym/version.rb +3 -1
- data/metonym.gemspec +24 -22
- metadata +39 -18
- data/lib/metonym/lib/validate.rb +0 -124
data/lib/metonym.rb
CHANGED
@@ -1,8 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'metonym/version'
|
2
4
|
require 'date'
|
3
5
|
require 'net/http'
|
4
6
|
require 'metonym/lib/gnews.rb'
|
5
|
-
require 'metonym/lib/
|
7
|
+
require 'metonym/lib/presenters/base_response_presenter.rb'
|
8
|
+
require 'metonym/lib/presenters/gnews_response_presenter.rb'
|
9
|
+
require 'metonym/lib/presenters/news_api_response_presenter.rb'
|
10
|
+
require 'metonym/lib/repositories/base_repository.rb'
|
11
|
+
require 'metonym/lib/repositories/gnews_repository.rb'
|
12
|
+
require 'metonym/lib/repositories/news_api_repository.rb'
|
13
|
+
require 'metonym/lib/validators/base_validator.rb'
|
14
|
+
require 'metonym/lib/validators/gnews_query_validator.rb'
|
15
|
+
require 'metonym/lib/validators/news_api_query_validator.rb'
|
6
16
|
require 'metonym/lib/news_api.rb'
|
7
17
|
require 'byebug'
|
8
18
|
require 'json'
|
data/lib/metonym/lib/gnews.rb
CHANGED
@@ -1,49 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gnews
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
4
|
+
class Query
|
5
|
+
attr_accessor :gnews_api_key
|
6
|
+
attr_accessor :uri
|
7
|
+
|
8
|
+
def initialize(key)
|
9
|
+
@gnews_api_key = key
|
10
|
+
@gnews = Gnews::GnewsRepository.new(key)
|
11
|
+
end
|
12
|
+
|
13
|
+
def search(args, **options)
|
14
|
+
request('search', args: args, format: define_response_format(options))
|
15
|
+
end
|
16
|
+
|
17
|
+
def top_news(args, **options)
|
18
|
+
request('top-news', args: args, format: define_response_format(options))
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def define_response_format(options)
|
24
|
+
options[:format] || 'json'
|
25
|
+
end
|
26
|
+
|
27
|
+
def request(resource, args:, format:)
|
28
|
+
validate_query_parameters(args, format)
|
29
|
+
|
30
|
+
case resource
|
31
|
+
when 'search'
|
32
|
+
response = @gnews.search(query: args)
|
33
|
+
when 'top-news'
|
34
|
+
response = @gnews.top_news(query: args)
|
35
|
+
when 'topics'
|
36
|
+
response = @gnews.topics(query: args)
|
37
|
+
end
|
38
|
+
rescue StandardError => e
|
39
|
+
response = { errors: e.to_s }
|
40
|
+
ensure
|
41
|
+
presenter = Gnews::GnewsResponsePresenter.new
|
42
|
+
return presenter.generate_formatted_response(response, format)
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_query_parameters(args, format)
|
46
|
+
v = Validate::GnewsQueryValidator.new(@gnews_api_key,
|
47
|
+
args: args, format: format)
|
48
|
+
raise v unless v
|
48
49
|
end
|
49
|
-
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/metonym/lib/news_api.rb
CHANGED
@@ -1,65 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module NewsApi
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
attr_accessor :uri
|
4
|
+
class Query
|
5
|
+
attr_accessor :news_api_key
|
6
|
+
attr_accessor :uri
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
8
|
+
def initialize(key)
|
9
|
+
@news_api_key = key
|
10
|
+
@news_api = NewsApi::NewsApiRepository.new(key)
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
13
|
+
def everything(args, **options)
|
14
|
+
request('everything', args: args, format: define_response_format(options))
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
17
|
+
def top_headlines(args, **options)
|
18
|
+
request('top-headlines', args: args, format: define_response_format(options))
|
19
|
+
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
21
|
+
def sources(args, **options)
|
22
|
+
request('sources', args: args, format: define_response_format(options))
|
23
|
+
end
|
27
24
|
|
28
|
-
|
29
|
-
def request(args, format, uri, endpoint)
|
30
|
-
begin
|
31
|
-
v = Validate::NewsApiValidator.new
|
32
|
-
raise "API Key is required" if v.is_key_present?(@news_api_key) == false
|
33
|
-
raise "Invalid parameter sequence" if v.is_query_valid?(args, endpoint) == false
|
34
|
-
raise "Invalid country sent" if v.is_country_valid?(args) == false
|
35
|
-
raise "Invalid language sent" if v.is_language_valid?(args) == false
|
36
|
-
raise "Invalid date or dates sent" if v.is_date_valid?(args) == false
|
37
|
-
raise "Invalid format sent" if v.is_format_valid?(format) == false
|
38
|
-
|
39
|
-
args = prepare_arguments(args)
|
25
|
+
private
|
40
26
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
27
|
+
def define_response_format(options)
|
28
|
+
options[:format] || 'json'
|
29
|
+
end
|
30
|
+
|
31
|
+
def request(resource, args:, format:)
|
32
|
+
validate_query_parameters(args, format, resource)
|
33
|
+
|
34
|
+
case resource
|
35
|
+
when 'top-headlines'
|
36
|
+
response = @news_api.top_headlines(query: args)
|
37
|
+
when 'everything'
|
38
|
+
response = @news_api.everything(query: args)
|
39
|
+
when 'sources'
|
40
|
+
response = @news_api.sources(query: args)
|
41
|
+
end
|
42
|
+
rescue StandardError => e
|
43
|
+
response = { errors: e.to_s }
|
44
|
+
ensure
|
45
|
+
presenter = NewsApi::NewsApiResponsePresenter.new
|
46
|
+
return presenter.generate_formatted_response(response, format)
|
47
|
+
end
|
57
48
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
args['to'] = args.has_key?('to') ? args['to'].strftime("%FT%T%:z") : nil
|
62
|
-
args
|
63
|
-
end
|
49
|
+
def validate_query_parameters(args, format, resource)
|
50
|
+
v = Validate::NewsApiQueryValidator.new(@news_api_key, args: args, format: format, endpoint: resource)
|
51
|
+
raise v unless v
|
64
52
|
end
|
65
|
-
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class BaseResponsePresenter
|
4
|
+
def generate_formatted_response(response, format)
|
5
|
+
return response if response.is_a?(Hash) && response.key?(:errors)
|
6
|
+
|
7
|
+
case format
|
8
|
+
when nil
|
9
|
+
response.body
|
10
|
+
when 'json'
|
11
|
+
response.body
|
12
|
+
when 'hash'
|
13
|
+
JSON.parse(response.body)
|
14
|
+
else
|
15
|
+
response.body
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gnews
|
4
|
+
class GnewsRepository < BaseRepository
|
5
|
+
def initialize(api_key)
|
6
|
+
@gnews_api_key = api_key
|
7
|
+
@uri = 'https://gnews.io/api/v3/'
|
8
|
+
end
|
9
|
+
|
10
|
+
def search(query:)
|
11
|
+
request(@uri, query: query, resource: 'search')
|
12
|
+
end
|
13
|
+
|
14
|
+
def top_news(query:)
|
15
|
+
request(@uri, query: query, resource: 'top-news')
|
16
|
+
end
|
17
|
+
|
18
|
+
def topic
|
19
|
+
request(@uri, query: query, resource: 'topic')
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def prepare_arguments(query)
|
25
|
+
query['mindate'] = query.key?(:mindate) ? query[:mindate].strftime('%y-%m-%d') : nil
|
26
|
+
query['maxdate'] = query.key?(:maxdate) ? query[:maxdate].strftime('%y-%m-%d') : nil
|
27
|
+
query['token'] = @gnews_api_key
|
28
|
+
query
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NewsApi
|
4
|
+
class NewsApiRepository < BaseRepository
|
5
|
+
def initialize(api_key)
|
6
|
+
@news_api_key = api_key
|
7
|
+
@uri = 'https://newsapi.org/v2/'
|
8
|
+
end
|
9
|
+
|
10
|
+
def everything(query:)
|
11
|
+
request(@uri, query: query, resource: 'everything')
|
12
|
+
end
|
13
|
+
|
14
|
+
def top_headlines(query:)
|
15
|
+
request(@uri, query: query, resource: 'top-headlines')
|
16
|
+
end
|
17
|
+
|
18
|
+
def sources(query:)
|
19
|
+
request(@uri, query: query, resource: 'sources')
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def prepare_arguments(query)
|
25
|
+
query['from'] = query.key?(:from) ? query[:from].strftime('%FT%T%:z') : nil
|
26
|
+
query['to'] = query.key?(:to) ? query[:to].strftime('%FT%T%:z') : nil
|
27
|
+
query['apiKey'] = @news_api_key
|
28
|
+
query
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Validate
|
4
|
+
class BaseValidator
|
5
|
+
protected
|
6
|
+
|
7
|
+
def key_present?(args)
|
8
|
+
!args.nil?
|
9
|
+
end
|
10
|
+
|
11
|
+
def language_valid?(args)
|
12
|
+
return true if args[:lang].nil?
|
13
|
+
|
14
|
+
[
|
15
|
+
'af', 'ak', 'sq', 'am', 'ar', 'hy', 'az', 'eu', 'be', 'bem', 'bn', 'bs', 'bh', 'br', 'bg', 'km', 'ca', 'chr', 'ny', 'zh-CN',
|
16
|
+
'zh-TW', 'co', 'hr', 'cs', 'da', 'nl', 'en', 'eo', 'et', 'ee', 'fo', 'tl', 'fi', 'fr', 'fy', 'gl', 'ka', 'de', 'el', 'gn', 'gu',
|
17
|
+
'ht', 'ha', 'haw', 'iw', 'hi', 'hu', 'is', 'ig', 'id', 'ia', 'ga', 'it', 'ja', 'jw', 'kn', 'kk', 'rw', 'rn', 'kg', 'ko', 'kri',
|
18
|
+
'ku', 'ckb', 'ky', 'lo', 'la', 'lv', 'ln', 'lt', 'loz', 'lg', 'ach', 'mk', 'mg', 'ms', 'ml', 'mt', 'mi', 'mr', 'mfe', 'mo', 'mn',
|
19
|
+
'sr-ME', 'ne', 'nso', 'no', 'nn', 'oc', 'or', 'om', 'ps', 'fa', 'pl', 'pt-BR', 'pt-PT', 'pa', 'qu', 'ro', 'rm', 'nyn', 'ru', 'gd',
|
20
|
+
'sr', 'sh', 'st', 'tn', 'crs', 'sn', 'sd', 'si', 'sk', 'sl', 'so', 'es', 'sp-419', 'su', 'sw', 'sv', 'tg', 'ta', 'tt', 'te', 'th', 'ti',
|
21
|
+
'to', 'lua', 'tum', 'tr', 'tk', 'tw', 'ug', 'uk', 'ur', 'uz', 'vi', 'cy', 'wo', 'xh', 'yi', 'yo', 'zu'
|
22
|
+
].include?(args[:lang].downcase)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Validate
|
4
|
+
class GnewsQueryValidator < BaseValidator
|
5
|
+
COUNTRIES = %w[
|
6
|
+
af al dz as ad ao ai aq ag ar am aw au at az bs bh bd bb by
|
7
|
+
be bz bj bm bt bo ba bw bv br io bn bg bf bi kh cm ca cv ky
|
8
|
+
cf td cl cn cx cc co km cg cd ck cr ci hr cu cy cz dk dj dm
|
9
|
+
do ec eg sv gq er ee et fk fo fj fi fr gf pf tf ga gm ge de
|
10
|
+
gh gi gr gl gd gp gu gt gn gw gy ht hm va hn hk hu is in id
|
11
|
+
ir iq ie il it jm jp jo kz ke ki kp kr kw kg la lv lb ls lr
|
12
|
+
ly li lt lu mo mk mg mw my mv ml mt mh mq mr mu yt mx fm md
|
13
|
+
mc mn ms ma mz mm na nr np nl an nc nz ni ne ng nu nf mp no
|
14
|
+
om pk pw ps pa pg py pe ph pn pl pt pr qa re ro ru rw sh kn
|
15
|
+
lc pm vc ws sm st sa sn cs sc sl sg sk si sb so za gs sp lk
|
16
|
+
sd sr sj sz se ch sy tw tj tz th tl tg tk to tt tn tr tm tc
|
17
|
+
tv ug ua ae uk us um uy uz vu ve vn vg vi wf eh ye zm zw
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
def initialize(api_key, args:, format:)
|
21
|
+
raise 'API Key is required' unless key_present?(api_key)
|
22
|
+
raise 'Invalid parameter sequence' unless query_valid?(args)
|
23
|
+
raise 'Invalid country sent' unless country_valid?(args)
|
24
|
+
raise 'Invalid language sent' unless language_valid?(args)
|
25
|
+
raise 'Invalid date or dates sent' unless date_valid?(args)
|
26
|
+
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def query_valid?(args)
|
33
|
+
search_template = %i[q max lang country mindate maxdate in]
|
34
|
+
top_news_template = %i[lang country max image]
|
35
|
+
template = search_template + top_news_template
|
36
|
+
(args.keys - template).empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
def country_valid?(args)
|
40
|
+
args[:country].nil? ? true : COUNTRIES.include?(args[:country].downcase)
|
41
|
+
end
|
42
|
+
|
43
|
+
def date_valid?(args)
|
44
|
+
if args[:mindate].nil? && args[:maxdate].nil?
|
45
|
+
true
|
46
|
+
elsif args[:mindate] && args[:maxdate]
|
47
|
+
(args[:mindate].respond_to?(:strftime) && args[:maxdate].respond_to?(:strftime))
|
48
|
+
elsif args[:mindate] && args[:maxdate].nil?
|
49
|
+
args[:mindate].respond_to?(:strftime)
|
50
|
+
elsif args[:mindate].nil? && args[:maxdate]
|
51
|
+
args[:maxdate].respond_to?(:strftime)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Validate
|
4
|
+
class NewsApiQueryValidator < BaseValidator
|
5
|
+
COUNTRIES = %w[ar au at be br bg ca cn co cu cz eg fr de gr hk hu in id ie il it jp lv lt my mx ma nl nz ng no ph pl pt ro ru sa rs sg sk si za kr se ch tw th tr ae ua gb us ve].freeze
|
6
|
+
CATEGORIES = %w[business entertainment general health science sports technology].freeze
|
7
|
+
|
8
|
+
def initialize(api_key, args:, format:, endpoint: nil)
|
9
|
+
raise 'API Key is required' unless key_present?(api_key)
|
10
|
+
raise 'Invalid parameter sequence' unless query_valid?(args, endpoint)
|
11
|
+
raise 'Invalid country sent' unless country_valid?(args)
|
12
|
+
raise 'Invalid language sent' unless language_valid?(args)
|
13
|
+
raise 'Invalid date or dates sent' unless date_valid?(args)
|
14
|
+
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def query_valid?(args, endpoint = 'top-headlines')
|
21
|
+
case endpoint
|
22
|
+
when 'top-headlines'
|
23
|
+
template = %i[q country category sources page_size page]
|
24
|
+
when 'everything'
|
25
|
+
template = %i[q sources domains excludeDomains
|
26
|
+
from to language sortBy pageSize page]
|
27
|
+
when 'sources'
|
28
|
+
template = %i[category language country]
|
29
|
+
end
|
30
|
+
|
31
|
+
if endpoint == 'top-headlines' && (args.include?(:sources) && (args.include?(:country) || args.include?(:category)))
|
32
|
+
false
|
33
|
+
elsif (endpoint == 'sources') && args.key?(:category) && (CATEGORIES.include?(args[:category]) == false)
|
34
|
+
false
|
35
|
+
else
|
36
|
+
(args.keys - template).empty?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def country_valid?(args)
|
41
|
+
args[:country].nil? ? true : COUNTRIES.include?(args[:country].downcase)
|
42
|
+
end
|
43
|
+
|
44
|
+
def category_valid?(args)
|
45
|
+
template = %w[business entertainment general health science sports technology]
|
46
|
+
template.include?(args[:country])
|
47
|
+
end
|
48
|
+
|
49
|
+
def date_valid?(args)
|
50
|
+
if args[:from].nil? && args[:to].nil?
|
51
|
+
true
|
52
|
+
elsif args[:from] && args[:to]
|
53
|
+
(args[:from].respond_to?(:strftime) && args['to'].respond_to?(:strftime))
|
54
|
+
elsif args[:from] && args['to'].nil?
|
55
|
+
args[:from].respond_to?(:strftime)
|
56
|
+
elsif args[:from].nil? && args['to']
|
57
|
+
args[:from].respond_to?(:strftime)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|