yourub 2.0.3 → 3.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 76023fb4d89509d08902ab1ed6810758b260a070
4
- data.tar.gz: 964ad582fc7d3463da47e2e8220154e92d4177cb
2
+ SHA256:
3
+ metadata.gz: 8d722c005745a329557fad47e8b494e1fd42e18f2e7f2df397a6b467bee9a599
4
+ data.tar.gz: 5e0c6ffc16c546c32b3d21f0354cb19976756b0436e71260e9dcf937aa2af7e2
5
5
  SHA512:
6
- metadata.gz: 7bacc97831647d25a6f8288b2258c0a100aac9aa5f9ac092e30940228f9790815d7866f9fe431ccda70764461b13b984d1ff058bd381fdcd55b9643451c37964
7
- data.tar.gz: aa97fb23ddb4bc1f2a1cebb2d7cd1fdb6e4845c4b4489a82a34afdf3b6af8d91571d227acc2d2ef261773f03e62df98f1fccad76308b1c5e315f1524f9b9ef86
6
+ metadata.gz: 90b6010eeb9cd2f0311ef0217b152ab800ed038d7ac18557d983b877d8e4653e890f5046490f490c18130a7a871a60919255823cda38920295626391ec7f8241
7
+ data.tar.gz: 58beed04c2d831215d74129c9c41e9029d7daaa671b68c711be1df41076b0b9819f1fb8854a5d922f4bf7aa68633a5f1646853415577e9cf170a8fa936e1eea5
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ lib/yourub/DEVELOPER_KEY
15
15
  lib/yourub/cli.rb
16
16
  pkg
17
17
  rdoc
18
+ test.rb
data/.travis.yml CHANGED
@@ -1,13 +1,9 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 1.9.3
5
4
  - 2.0.0
6
5
  - 2.1
7
6
  - 2.2
8
- - jruby-19mode
9
- - jruby-head
10
- - rbx-2
11
7
  - ruby-head
12
8
 
13
9
  sudo: false
data/Gemfile CHANGED
@@ -9,9 +9,9 @@ end
9
9
 
10
10
  group :test do
11
11
  gem 'coveralls'
12
- gem 'rspec', '>= 3.00'
13
- gem 'rubocop', '>= 0.27'
14
- gem 'simplecov', '>= 0.9'
12
+ gem 'rspec'
13
+ gem 'rubocop'
14
+ gem 'simplecov'
15
15
  gem 'webmock'
16
16
  end
17
17
 
data/README.md CHANGED
@@ -1,10 +1,8 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/yourub.svg)](http://badge.fury.io/rb/yourub)
2
- [![Dependency Status](https://gemnasium.com/edap/yourub.svg)](https://gemnasium.com/edap/yourub)
3
- [![Build Status](https://travis-ci.org/edap/yourub.svg?branch=master)](https://travis-ci.org/edap/yourub)
4
- [![Code Climate](https://codeclimate.com/github/edap/yourub.png)](https://codeclimate.com/github/edap/yourub)
2
+
5
3
 
6
4
  # Yourub
7
- Yourub is a gem that search videos on youtebe using the YouTube API v3.
5
+ Yourub is a gem for searching YouTube videos using the YouTube Data API v3.
8
6
 
9
7
  ## Installation
10
8
 
@@ -28,10 +26,8 @@ rails app, create a app/config/yourub.yml file as follow:
28
26
  ```
29
27
  yourub_defaults: &yourub_defaults
30
28
  developer_key: 'YoUrDevEl0PerKey'
31
- youtube_api_service_name: 'youtube'
32
- youtube_api_version: 'v3'
33
29
  application_name: "yourub"
34
- application_version: "0.1"
30
+ application_version: "0.2"
35
31
  log_level: WARN
36
32
 
37
33
  development:
@@ -45,7 +41,8 @@ test:
45
41
  ```
46
42
 
47
43
  If you want to use it from the console, or in another program, you can simply
48
- pass an hash containing the needed options
44
+ pass an hash containing the needed options. Change 'yourub' with the name of your application.
45
+
49
46
  ```ruby
50
47
  options = { developer_key: 'mySecretKey',
51
48
  application_name: 'yourub',
@@ -58,18 +55,21 @@ client = Yourub::Client.new(options)
58
55
 
59
56
  ### Examples
60
57
 
61
- For example, to find the most recent videos in the category "sports" in Germany
58
+ **`search`** always requires a non-empty `:query` (YouTube `search.list` uses the `q` parameter). Optional filters narrow results.
59
+
60
+ Recent sports-related videos in Germany (category is matched by **name**, see below):
61
+
62
62
  ```ruby
63
- client = Yourub::Client.new
64
- client.search(country: "DE", category: "sports", order: 'date') do |v|
63
+ client = Yourub::Client.new(developer_key: "…", application_name: "yourub", application_version: "1.0")
64
+ client.search(query: "highlights", country: "DE", category: "sports", order: "date") do |v|
65
65
  puts v
66
66
  end
67
67
  ```
68
68
 
69
- To find video for a specific thema, use the parameter query
69
+ Search by text only (optional `country` sets `regionCode` on the API request):
70
70
 
71
71
  ```ruby
72
- client = Yourub::Client.new
72
+ client = Yourub::Client.new(developer_key: "…", application_name: "yourub", application_version: "1.0")
73
73
  client.search(query: "aliens") do |v|
74
74
  puts v
75
75
  end
@@ -79,59 +79,65 @@ that is the content of the response:
79
79
  [{"kind"=>"youtube#video", "etag"=>"\"N5Eg36Gl054SUNiWWc-Su3t5O-k/U6AzLXvcnZt2WFqpnq9_dksV7DA\"", "id"=>"NisCkxU544c", "snippet"=>{"publishedAt"=>"2009-04-05T05:20:10.000Z", "channelId"=>"UCCHcEUksSVKsRDH86j77Ntg", "title"=>"Like A Boss (ft. Seth Rogen) - Uncensored Version", "description"=>"http://www.itunes.com/thelonelyisland\r\n\r\nThe new single from The Lonely Island's debut album \"INCREDIBAD\" In stores now!\r\n\r\nFeaturing Seth Rogen.\r\n\r\nThe Lonely Island is Andy Samberg, Akiva Schaffer & Jorma Taccone.", "thumbnails"=>{"default"=>{"url"=>"https://i1.ytimg.com/vi/NisCkxU544c/default.jpg", "width"=>120, "height"=>90}, "medium"=>{"url"=>"https://i1.ytimg.com/vi/NisCkxU544c/mqdefault.jpg", "width"=>320, "height"=>180}, "high"=>{"url"=>"https://i1.ytimg.com/vi/NisCkxU544c/hqdefault.jpg", "width"=>480, "height"=>360}, "standard"=>{"url"=>"https://i1.ytimg.com/vi/NisCkxU544c/sddefault.jpg", "width"=>640, "height"=>480}, "maxres"=>{"url"=>"https://i1.ytimg.com/vi/NisCkxU544c/maxresdefault.jpg", "width"=>1280, "height"=>720}}, "channelTitle"=>"thelonelyisland", "categoryId"=>"23", "liveBroadcastContent"=>"none"}, "statistics"=>{"viewCount"=>"120176425", "likeCount"=>"594592", "dislikeCount"=>"15121", "favoriteCount"=>"0", "commentCount"=>"208109"}}]
80
80
  ```
81
81
  ### Available parameters
82
- `:query` String, example `aliens`
83
82
 
84
- `:country` String, one or more alpha-2 country codes [ISO 3166-1](http://www.iso.org/iso/country_codes/iso_3166_code_lists/country_names_and_code_elements.htm), example `US` or `IT, DE`. The default one is `US`
83
+ `:query` **Required.** Non-empty string (after stripping whitespace). Sent as YouTube **`q`**.
85
84
 
86
- `:category` String, example `comedy`. It accept the wildcard `all`, that retrieves videos for all the category for the given nation, or the default one (US) if no one is given
85
+ `:country` Optional. One or more [ISO 3166-1 alpha-2](https://www.iso.org/iso-3166-country-codes.html) codes, e.g. `"US"` or `"IT,DE"`. Each code is applied as **`regionCode`** on `search.list`. Codes are validated against `Yourub::CountryCodes::ISO_3166_1_ALPHA2` (also exposed as `Yourub::Validator::COUNTRIES` / `client.countries`).
87
86
 
88
- `:count_filter` Hash, example `{views: ">= 100"}` or `{views: "== 600"}`
87
+ `:category` — Optional. If the name of a category is set, Yourub resolves a category_id from the name: it calls `list_video_categories`, cached on the client), finds the first item whose title contains your string (case-insensitive). Omit `category` entirely when you do not want a category filter. If the name does not match any category, `ArgumentError` lists `id: title` lines of the available categories.
89
88
 
90
- `:max_results` Integer, between 1 and 50
89
+ `:count_filter` — Optional hash, e.g. `{ views: ">= 100" }` or `{ views: "== 600" }` (applied after fetching full video resources).
91
90
 
92
- `:order` String, one of these: 'date', 'rating', 'relevance', 'title', 'videocount', 'viewcount'. The default one is `'relevance'`
91
+ `:max_results` Optional integer from 1 to 50.
93
92
 
94
- It's necessary at least one of this parameters to start a search: `:country`, `:category`, `:query`
93
+ `:order` Optional. One of: `date`, `rating`, `relevance`, `title`, `videoCount`, `viewCount`. Default `relevance`.
95
94
 
96
95
  ### Methods
97
- * `search`, search youtube videos for the given parameters
96
+ * `search` — Runs a YouTube search and yields each video hash that passes optional filters. Requires `:query` and typically a block.
97
+
98
98
  ```ruby
99
- client = Yourub::Client.new
100
- client.search(query: "space missions")
99
+ client = Yourub::Client.new(developer_key: "…", application_name: "yourub", application_version: "1.0")
100
+ client.search(query: "space missions") { |v| puts v["id"] }
101
101
  ```
102
102
 
103
- * `get_views`
104
- it return the number of views for the given video id
103
+ * `get` — Fetches one video’s metadata (`snippet` + `statistics`).
104
+
105
105
  ```ruby
106
- client = Yourub::Client.new
107
- client.get_views("G2b0OIkTraI")
106
+ client = Yourub::Client.new(developer_key: "…", application_name: "yourub", application_version: "1.0")
107
+ client.get("G2b0OIkTraI")
108
108
  ```
109
- * `get`
110
- retrieves all the metatags available for one
109
+
110
+ * `list_video_categories`
111
+
112
+ Calls YouTube [`videoCategories.list`](https://developers.google.com/youtube/v3/docs/videoCategories/list) using only **`regionCode`** (via `region_code:`). The API does not use category IDs in this helper; you pass an [ISO 3166-1 alpha-2](https://www.iso.org/iso-3166-country-codes.html) region when you want that country’s category list.
113
+
114
+ **`region_code`:** Optional. If omitted or blank, the request is sent without `regionCode`, which matches the documented default catalog (United States).
115
+
116
+ **`hl`:** Optional. Sets the `hl` query parameter so snippet titles in the response use the requested locale (e.g. Spanish labels for Spain).
117
+
118
+ **Caching:** Responses are cached per client instance, keyed by `region_code` and `hl`, because category metadata changes rarely. Repeat calls with the same arguments return the same in-memory result without another HTTP request.
119
+
120
+ **Return value:** A `Google::Apis::YoutubeV3::VideoCategoryListResponse` (from `google-apis-youtube_v3`). Use `#items` to iterate categories (each has `#id` and `#snippet`).
121
+
111
122
  ```ruby
112
- client = Yourub::Client.new
113
- client.get("G2b0OIkTraI")
123
+ client = Yourub::Client.new(options)
124
+
125
+ # Default catalog (documented as US when region is not specified)
126
+ us_like = client.list_video_categories
127
+
128
+ # Explicit region
129
+ de_categories = client.list_video_categories(region_code: "DE")
130
+
131
+ # Region + localized labels
132
+ es_labels = client.list_video_categories(region_code: "ES", hl: "es")
114
133
  ```
115
134
 
116
- ## Supported Ruby Versions
117
- This gem [supports](https://travis-ci.org/edap/yourub) the following Ruby versions:
118
-
119
- * Ruby 1.9.3
120
- * Ruby 2.0.0
121
- * Ruby 2.1
122
- * Ruby 2.2
123
- * JRuby 1.7 (in Ruby 1.9 mode)
124
-
125
- ##TODO
126
- Here there is a [list](https://developers.google.com/youtube/v3/docs/) of the available methods.
127
- Currently, this gem implements: [videos.list](https://developers.google.com/youtube/v3/docs/videos/list), [search.list](https://developers.google.com/youtube/v3/docs/search/list) and [videoCategories.list](https://developers.google.com/youtube/v3/docs/videoCategories/list).
128
- The next methods that will be implemented are [playlist.list](https://developers.google.com/youtube/v3/docs/playlists/list) and [channelis.list](https://developers.google.com/youtube/v3/docs/channels/list)
129
- ## Contributing
130
-
131
- 1. Fork it
132
- 2. Create your feature branch (`git checkout -b my-new-feature`)
133
- 3. Commit your changes (`git commit -am 'Add some feature'`)
134
- 4. Run the test, run the spec/yourub/integration.rb file with a valid developer
135
- key
136
- 5. Push to the branch (`git push origin my-new-feature`)
137
- 4. Create new Pull Request
135
+ * `flush_video_categories_cache!`
136
+
137
+ Clears all cached `list_video_categories` results for this client. Call this if you need to force a fresh fetch (e.g. after a long-lived process or for tests).
138
+
139
+ ```ruby
140
+ client.flush_video_categories_cache!
141
+ ```
142
+
143
+
data/config/yourub.yml CHANGED
@@ -1,7 +1,5 @@
1
1
  yourub_defaults: &yourub_defaults
2
2
  developer_key: 'YourDeveloperKey'
3
- youtube_api_service_name: 'youtube'
4
- youtube_api_version: 'v3'
5
3
  application_name: "yourub"
6
4
  application_version: "0.1"
7
5
  log_level: WARN
data/lib/yourub/client.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require 'yourub/meta_search'
2
- require 'google/api_client'
2
+ require 'google/apis/youtube_v3'
3
3
 
4
4
  module Yourub
5
- class Client < Google::APIClient
5
+ class Client
6
6
  include Yourub::MetaSearch
7
7
 
8
8
  attr_reader :videos
@@ -34,30 +34,106 @@ module Yourub
34
34
  Yourub::Config.override_config_file(options)
35
35
  end
36
36
 
37
- args = {
38
- :key => config.developer_key,
39
- :application_name => config.application_name,
40
- :application_version => config.application_version,
41
- :authorization => nil
42
- }
43
- super(args)
37
+ @service = Google::Apis::YoutubeV3::YouTubeService.new
38
+ @service.key = config.developer_key
39
+ @service.client_options.application_name = config.application_name
40
+ @service.client_options.application_version = config.application_version
41
+ @video_categories_cache = {}
44
42
  end
45
43
 
46
- # @return countries [Array] contain a list of the available alpha-2 country codes ISO 3166-1
47
44
  def countries
48
45
  Yourub::Validator.available_countries
49
46
  end
50
47
 
51
- # it returns the youtube service object
52
- # @see http://www.rubydoc.info/github/google/google-api-ruby-client/Google/APIClient#discovered_api-instance_method
53
- def youtube_api
54
- @youtube_api ||= self.discovered_api(
55
- config.youtube_api_service_name, config.youtube_api_version
56
- )
48
+ def list_video_categories(region_code: nil, hl: nil)
49
+ key = video_categories_cache_key(region_code, hl)
50
+ return @video_categories_cache[key] if @video_categories_cache.key?(key)
51
+
52
+ part = "snippet"
53
+ kwargs = {}
54
+ unless region_code.nil? || region_code.to_s.strip.empty?
55
+ kwargs[:region_code] = region_code.to_s.strip.upcase
56
+ end
57
+ kwargs[:hl] = hl.to_s.strip if hl && !hl.to_s.strip.empty?
58
+
59
+ @video_categories_cache[key] = @service.list_video_categories(part, **kwargs)
60
+ end
61
+
62
+ def flush_video_categories_cache!
63
+ @video_categories_cache.clear
64
+ end
65
+
66
+ # Compatibility shim used by Yourub::REST::Request
67
+ def execute!(api_method:, parameters:)
68
+ case api_method
69
+ when :search_list
70
+ part = parameters.delete(:part) || parameters.delete('part') || 'snippet'
71
+ opts = normalize_search_params(parameters)
72
+ data = @service.list_searches(part, **opts)
73
+ OpenStruct.new(data: data, status: 200)
74
+ when :videos_list
75
+ part = parameters.delete(:part) || parameters.delete('part') || 'snippet'
76
+ opts = normalize_videos_params(parameters)
77
+ data = @service.list_videos(part, **opts)
78
+ OpenStruct.new(data: data, status: 200)
79
+ when :video_categories_list
80
+ part = parameters.delete(:part) || parameters.delete('part') || 'snippet'
81
+ opts = normalize_categories_params(parameters)
82
+ data = @service.list_video_categories(part, **opts)
83
+ OpenStruct.new(data: data, status: 200)
84
+ else
85
+ raise ArgumentError, "Unsupported api_method #{api_method.inspect}"
86
+ end
57
87
  end
58
88
 
59
89
  def config
60
90
  Yourub::Config
61
91
  end
92
+
93
+ private
94
+
95
+ def video_categories_cache_key(region_code, hl)
96
+ region = if region_code.nil? || region_code.to_s.strip.empty?
97
+ "_default"
98
+ else
99
+ region_code.to_s.strip.upcase
100
+ end
101
+ hl_part = (hl.nil? || hl.to_s.strip.empty?) ? "" : hl.to_s.strip
102
+ "#{region}\0#{hl_part}"
103
+ end
104
+
105
+ def normalize_search_params(params)
106
+ query = params[:q] || params['q'] || ""
107
+
108
+ transform_common_params(params).merge(
109
+ {
110
+ q: query,
111
+ type: params[:type] || params['type'],
112
+ order: params[:order] || params['order'],
113
+ safe_search: params[:safeSearch] || params['safeSearch']
114
+ }.compact
115
+ )
116
+ end
117
+
118
+ def normalize_videos_params(params)
119
+ transform_common_params(params).merge(
120
+ {
121
+ id: params[:id] || params['id'],
122
+ fields: params[:fields] || params['fields']
123
+ }.compact
124
+ )
125
+ end
126
+
127
+ def normalize_categories_params(params)
128
+ transform_common_params(params)
129
+ end
130
+
131
+ def transform_common_params(params)
132
+ {
133
+ max_results: params[:maxResults] || params['maxResults'],
134
+ region_code: params[:regionCode] || params['regionCode'],
135
+ video_category_id: params[:videoCategoryId] || params['videoCategoryId']
136
+ }.compact
137
+ end
62
138
  end
63
139
  end
data/lib/yourub/config.rb CHANGED
@@ -9,17 +9,18 @@ module Yourub
9
9
  extend Forwardable
10
10
  attr_accessor :config
11
11
 
12
- def_delegators :@config, :developer_key,:youtube_api_service_name, :log_level,
13
- :youtube_api_version, :application_name, :application_version
12
+ def_delegators :@config, :developer_key, :log_level,
13
+ :application_name, :application_version
14
14
 
15
15
  MANDATORY_KEYS = [:developer_key, :application_name, :application_version, :log_level]
16
16
 
17
- # It loads the configuration file
18
- # this method is used in the railtie.rb and in the default.rb files
19
- # @example
20
- # Yourub::Config.load!(File.join("config", "yourub.yml"), 'yourub_defaults')
17
+ # Only these keys are read from YAML or from +Client.new(opts)+. The API is always
18
+ # YouTube Data API v3 via google-apis-youtube_v3 (+YouTubeService+).
19
+ USER_CONFIG_KEYS = %i[developer_key application_name application_version log_level].freeze
20
+
21
21
  def load!(file_path, environment)
22
- @config = OpenStruct.new YAML.load_file(file_path)[environment]
22
+ raw = YAML.load_file(file_path)[environment]
23
+ @config = OpenStruct.new(prune_config_hash(raw))
23
24
  end
24
25
 
25
26
  def override_config_file(hash)
@@ -29,8 +30,15 @@ module Yourub
29
30
 
30
31
  private
31
32
 
33
+ def prune_config_hash(h)
34
+ return {} unless h.is_a?(Hash)
35
+
36
+ h.transform_keys { |k| k.to_sym }.slice(*USER_CONFIG_KEYS)
37
+ end
38
+
32
39
  def valid_options(hash)
33
- opt = default_options.merge(hash)
40
+ normalized = hash.transform_keys { |k| k.to_sym }
41
+ opt = default_options.merge(normalized.slice(*USER_CONFIG_KEYS))
34
42
  raise ArgumentError.new(
35
43
  "please provide an hash containing at least a valid developer_key"
36
44
  ) if opt[:developer_key].empty?
@@ -40,8 +48,6 @@ private
40
48
  def default_options
41
49
  {
42
50
  developer_key: "",
43
- youtube_api_service_name: "youtube",
44
- youtube_api_version: "v3",
45
51
  application_name: "yourub",
46
52
  application_version: Yourub::VERSION,
47
53
  log_level: "WARN"
@@ -0,0 +1,28 @@
1
+ module Yourub
2
+ # ISO 3166-1 alpha-2 codes used for YouTube +regionCode+ style parameters.
3
+ #
4
+ # Derived from the +slim-2.csv+ dataset:
5
+ # https://github.com/lukes/ISO-3166-Countries-with-Regional-Codes (249 entries).
6
+ module CountryCodes
7
+ ISO_3166_1_ALPHA2 = %w[
8
+ AD AE AF AG AI AL AM AO AQ AR AS AT AU AW
9
+ AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN
10
+ BO BQ BR BS BT BV BW BY BZ CA CC CD CF CG
11
+ CH CI CK CL CM CN CO CR CU CV CW CX CY CZ
12
+ DE DJ DK DM DO DZ EC EE EG EH ER ES ET FI
13
+ FJ FK FM FO FR GA GB GD GE GF GG GH GI GL
14
+ GM GN GP GQ GR GS GT GU GW GY HK HM HN HR
15
+ HT HU ID IE IL IM IN IO IQ IR IS IT JE JM
16
+ JO JP KE KG KH KI KM KN KP KR KW KY KZ LA
17
+ LB LC LI LK LR LS LT LU LV LY MA MC MD ME
18
+ MF MG MH MK ML MM MN MO MP MQ MR MS MT MU
19
+ MV MW MX MY MZ NA NC NE NF NG NI NL NO NP
20
+ NR NU NZ OM PA PE PF PG PH PK PL PM PN PR
21
+ PS PT PW PY QA RE RO RS RU RW SA SB SC SD
22
+ SE SG SH SI SJ SK SL SM SN SO SR SS ST SV
23
+ SX SY SZ TC TD TF TG TH TJ TK TL TM TN TO
24
+ TR TT TV TW TZ UA UG UM US UY UZ VA VC VE
25
+ VG VI VN VU WF WS YE YT ZA ZM ZW
26
+ ].freeze
27
+ end
28
+ end
@@ -11,35 +11,31 @@ module Yourub
11
11
  # client.search(country: "DE", category: "sports", order: 'date')
12
12
  def search(criteria)
13
13
  begin
14
+ Yourub::CountFilter.filter = nil
15
+
14
16
  @api_options= {
15
17
  :part => 'snippet',
16
18
  :type => 'video',
17
19
  :order => 'relevance',
18
20
  :safeSearch => 'none',
19
- }
21
+ :q => nil
22
+ }
23
+
20
24
  @categories = []
21
25
  @count_filter = {}
26
+
27
+ @api_options[:q] = criteria[:query] if criteria[:query]
28
+
22
29
  @criteria = Yourub::Validator.confirm(criteria)
23
30
  search_by_criteria do |result|
24
31
  yield result
25
32
  end
26
33
  rescue ArgumentError => e
27
34
  Yourub.logger.error "#{e}"
35
+ raise
28
36
  end
29
37
  end
30
38
 
31
- # return the number of times a video was watched
32
- # @param video_id[Integer]
33
- # @example
34
- # client = Yourub::Client.new
35
- # client.get_views("G2b0OIkTraI")
36
- def get_views(video_id)
37
- params = { :id => video_id, :part => 'statistics' }
38
- request = Yourub::REST::Videos.list(self,params)
39
- v = Yourub::Result.format(request).first
40
- v ? Yourub::CountFilter.get_views_count(v) : nil
41
- end
42
-
43
39
  # return an hash containing the metadata for the given video
44
40
  # @param video_id[Integer]
45
41
  # @example
@@ -61,62 +57,84 @@ private
61
57
  end
62
58
  end
63
59
 
64
- def merge_criteria_with_api_options
65
- mappings = {query: :q, max_results: :maxResults, country: :regionCode}
66
- @api_options.merge! @criteria
67
- @api_options.keys.each do |k|
68
- @api_options[ mappings[k] ] = @api_options.delete(k) if mappings[k]
69
- end
70
- end
71
60
 
72
- def retrieve_categories
73
- if @criteria.has_key? :category
74
- @categories = Yourub::REST::Categories.for_country(self,@criteria[:country])
75
- @categories = Yourub::Validator.valid_category(@categories, @criteria[:category])
76
- end
77
- end
78
-
79
- def retrieve_videos
80
- consume_criteria do |criteria|
81
- begin
82
- req = Yourub::REST::Search.list(self, criteria)
83
- get_details_for_each_video(req) do |v|
84
- yield v
85
- end
86
- rescue StandardError => e
87
- Yourub.logger.error "Error #{e} retrieving videos for the criteria: #{criteria.to_s}"
88
- end
89
- end
61
+ def merge_criteria_with_api_options
62
+ @api_options[:q] = @criteria[:query] if @criteria[:query]
63
+ @api_options[:maxResults] = @criteria[:max_results] if @criteria[:max_results]
64
+ @api_options[:order] = @criteria[:order] if @criteria[:order]
90
65
  end
91
66
 
92
67
  def consume_criteria
93
- to_consume = @api_options
94
68
  if @criteria[:country]
95
69
  @criteria[:country].each do |country|
70
+ to_consume = @api_options.dup
96
71
  to_consume[:regionCode] = country
97
72
  consume_categories(to_consume) do |cat|
98
73
  yield cat
99
74
  end
100
75
  end
101
76
  else
102
- yield to_consume
77
+ consume_categories(@api_options.dup) do |cat|
78
+ yield cat
79
+ end
103
80
  end
104
81
  end
105
82
 
106
83
  def consume_categories(to_consume)
107
84
  if @categories.size > 0
108
85
  @categories.each do |cat|
109
- to_consume[:videoCategoryId] = cat.keys[0].to_i
110
- yield to_consume
86
+ current_params = to_consume.dup
87
+ current_params[:videoCategoryId] = cat.keys[0].to_i
88
+ yield current_params
111
89
  end
112
90
  else
113
91
  yield to_consume
114
92
  end
115
93
  end
116
94
 
95
+ def retrieve_categories
96
+ return unless @criteria.key?(:category)
97
+
98
+ term = @criteria[:category].to_s.strip
99
+ if term.empty?
100
+ @categories = []
101
+ return
102
+ end
103
+
104
+ if term.casecmp("all").zero?
105
+ raise ArgumentError,
106
+ 'category "all" is not supported; omit :category to search without a video category filter.'
107
+ end
108
+
109
+ region_code = region_code_for_category_catalog
110
+ list = list_video_categories(region_code: region_code)
111
+ items = video_category_list_items(list)
112
+ match = find_category_item_by_partial_name(items, term)
113
+ if match.nil?
114
+ raise ArgumentError, category_not_found_message(term, items)
115
+ end
116
+
117
+ cid = video_category_item_id(match)
118
+ @categories = [{ cid.to_s => term }]
119
+ end
120
+
121
+ def retrieve_videos
122
+ consume_criteria do |criteria|
123
+ begin
124
+ req = Yourub::REST::Search.list(self, criteria)
125
+ get_details_for_each_video(req) do |v|
126
+ yield v
127
+ end
128
+ rescue StandardError => e
129
+ Yourub.logger.error "Error #{e} retrieving videos for the criteria: #{criteria.to_s}"
130
+ end
131
+ end
132
+ end
133
+
134
+
117
135
  def get_details_for_each_video(video_list)
118
136
  video_list.data.items.each do |video_item|
119
- v = Yourub::REST::Videos.single_video(self, video_item.id.videoId)
137
+ v = Yourub::REST::Videos.single_video(self, video_item.id.video_id)
120
138
  v = Yourub::Result.format(v)
121
139
  if v && Yourub::CountFilter.accept?(v.first)
122
140
  yield v.first
@@ -130,5 +148,60 @@ private
130
148
  end
131
149
  end
132
150
 
151
+ def region_code_for_category_catalog
152
+ return nil unless @criteria[:country].is_a?(Array) && @criteria[:country].any?
153
+
154
+ @criteria[:country].first
155
+ end
156
+
157
+ def video_category_list_items(list)
158
+ raw =
159
+ if list.respond_to?(:items)
160
+ list.items
161
+ elsif list.is_a?(Hash)
162
+ list["items"]
163
+ end
164
+ Array(raw)
165
+ end
166
+
167
+ def find_category_item_by_partial_name(items, search_term)
168
+ needle = search_term.to_s.strip.downcase
169
+ return nil if needle.empty?
170
+
171
+ items.find do |item|
172
+ title = video_category_item_title(item).to_s.downcase
173
+ title.include?(needle)
174
+ end
175
+ end
176
+
177
+ def video_category_item_title(item)
178
+ if item.respond_to?(:snippet) && item.snippet.respond_to?(:title)
179
+ item.snippet.title
180
+ elsif item.is_a?(Hash)
181
+ item.dig("snippet", "title")
182
+ else
183
+ ""
184
+ end
185
+ end
186
+
187
+ def video_category_item_id(item)
188
+ if item.respond_to?(:id)
189
+ id = item.id
190
+ id.is_a?(Hash) ? id["videoId"] || id[:videoId] : id
191
+ elsif item.is_a?(Hash)
192
+ item["id"]
193
+ end
194
+ end
195
+
196
+ def category_not_found_message(term, items)
197
+ lines = items.map do |it|
198
+ "#{video_category_item_id(it)}: #{video_category_item_title(it)}"
199
+ end
200
+ <<~MSG.chomp
201
+ category not found, this is the list of the available categories:
202
+ #{lines.join("\n")}
203
+ MSG
204
+ end
205
+
133
206
  end
134
207
  end