video_info 3.0.2 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  class VideoInfo
2
2
  module Providers
3
3
  module VimeoAPI
4
- THUMBNAIL_LINK_REGEX = /.*\/(\d+\-[^_]+)/
4
+ THUMBNAIL_LINK_REGEX = /.*\/(\d+-[^_]+)/
5
5
 
6
6
  def api_key
7
7
  VideoInfo.provider_api_keys[:vimeo]
@@ -16,24 +16,24 @@ class VideoInfo
16
16
  end
17
17
 
18
18
  def title
19
- _video['name']
19
+ _video["name"]
20
20
  end
21
21
 
22
22
  def author
23
- _video['user']['name']
23
+ _video["user"]["name"]
24
24
  end
25
25
 
26
26
  def author_thumbnail_id
27
- author_uri = _video['user']['pictures']['uri']
27
+ author_uri = _video["user"]["pictures"]["uri"]
28
28
  @author_thumbnail_id ||= parse_picture_id_from_user(author_uri)
29
29
  end
30
30
 
31
31
  def author_url
32
- _video['user']['link']
32
+ _video["user"]["link"]
33
33
  end
34
34
 
35
35
  def author_thumbnail(width = 75)
36
- 'https://i.vimeocdn.com/portrait/' \
36
+ "https://i.vimeocdn.com/portrait/" \
37
37
  "#{author_thumbnail_id}_#{width}x#{width}.jpg"
38
38
  end
39
39
 
@@ -58,15 +58,19 @@ class VideoInfo
58
58
  end
59
59
 
60
60
  def keywords_array
61
- _video['tags'].map { |t| t['tag'] }
61
+ _video["tags"].map { |t| t["tag"] }
62
62
  end
63
63
 
64
64
  def date
65
- Time.parse(_video['created_time'], Time.now.utc).utc
65
+ Time.parse(_video["created_time"], Time.now.utc).utc
66
66
  end
67
67
 
68
68
  def view_count
69
- _video['stats']['plays'].to_i
69
+ stats["plays"].to_i
70
+ end
71
+
72
+ def stats
73
+ _video["stats"]
70
74
  end
71
75
 
72
76
  private
@@ -86,15 +90,15 @@ class VideoInfo
86
90
  end
87
91
 
88
92
  def _api_version
89
- '3.2'
93
+ "3.2"
90
94
  end
91
95
 
92
96
  def _authorization_headers
93
- { 'Authorization' => "bearer #{api_key}" }
97
+ {"Authorization" => "bearer #{api_key}"}
94
98
  end
95
99
 
96
100
  def _api_version_headers
97
- { 'Accept' => "application/vnd.vimeo.*+json;version=#{_api_version}" }
101
+ {"Accept" => "application/vnd.vimeo.*+json;version=#{_api_version}"}
98
102
  end
99
103
 
100
104
  def _video
@@ -102,7 +106,7 @@ class VideoInfo
102
106
  end
103
107
 
104
108
  def _api_base
105
- 'api.vimeo.com'
109
+ "api.vimeo.com"
106
110
  end
107
111
 
108
112
  def _api_path
@@ -113,8 +117,8 @@ class VideoInfo
113
117
  "https://#{_api_base}#{_api_path}"
114
118
  end
115
119
 
116
- def parse_picture_id_from_user (uri)
117
- %r{\/pictures\/(\d+)}.match(uri)[1]
120
+ def parse_picture_id_from_user(uri)
121
+ %r{/pictures/(\d+)}.match(uri)[1]
118
122
  end
119
123
 
120
124
  def parse_picture_id(uri)
@@ -1,15 +1,12 @@
1
- require 'oga'
2
- require 'open-uri'
3
- require 'json'
4
- require 'openssl'
5
- require 'cgi'
1
+ require "oga"
2
+ require "cgi"
6
3
 
7
4
  class VideoInfo
8
5
  module Providers
9
6
  module VimeoScraper
10
7
  def author
11
8
  if available?
12
- json_info['author']['name']
9
+ json_info["author"]["name"]
13
10
  end
14
11
  end
15
12
 
@@ -18,8 +15,8 @@ class VideoInfo
18
15
  return nil
19
16
  end
20
17
 
21
- split_point = 'window.vimeo.clip_page_config ='
22
- script_tags = data.css('script')
18
+ split_point = "window.vimeo.clip_page_config ="
19
+ script_tags = data.css("script")
23
20
 
24
21
  script_index = script_tags.find_index do |x|
25
22
  x.text.include?(split_point)
@@ -31,12 +28,12 @@ class VideoInfo
31
28
 
32
29
  parsed_data = JSON.parse(split_script_text.split(";\n")[0])
33
30
 
34
- parsed_data['owner']['portrait']['src']
31
+ parsed_data["owner"]["portrait"]["src"]
35
32
  end
36
33
 
37
34
  def author_url
38
35
  if available?
39
- json_info['author']['url']
36
+ json_info["author"]["url"]
40
37
  end
41
38
  end
42
39
 
@@ -46,7 +43,7 @@ class VideoInfo
46
43
  if data.nil?
47
44
  is_available = false
48
45
  elsif is_available
49
- password_elements = data.css('.exception_title--password')
46
+ password_elements = data.css(".exception_title--password")
50
47
 
51
48
  unless password_elements.empty?
52
49
  is_available = false
@@ -57,23 +54,23 @@ class VideoInfo
57
54
  end
58
55
 
59
56
  def title
60
- meta_node_value('og:title')
57
+ meta_node_value("og:title")
61
58
  end
62
59
 
63
60
  def description
64
- meta_node_value('og:description')
61
+ meta_node_value("og:description")
65
62
  end
66
63
 
67
64
  def date
68
65
  if available?
69
- upload_date = json_info['uploadDate']
66
+ upload_date = json_info["uploadDate"]
70
67
  ISO8601::DateTime.new(upload_date).to_time
71
68
  end
72
69
  end
73
70
 
74
71
  def duration
75
72
  if available?
76
- duration = json_info['duration']
73
+ duration = json_info["duration"]
77
74
  ISO8601::Duration.new(duration).to_seconds.to_i
78
75
  end
79
76
  end
@@ -83,55 +80,60 @@ class VideoInfo
83
80
  return nil
84
81
  end
85
82
 
86
- if json_info['keywords']
87
- json_info['keywords']
88
- else
89
- []
90
- end
83
+ json_info["keywords"] || []
91
84
  end
92
85
 
93
86
  def height
94
87
  if available?
95
- json_info['height']
88
+ json_info["height"]
96
89
  end
97
90
  end
98
91
 
99
92
  def width
100
93
  if available?
101
- json_info['width']
94
+ json_info["width"]
102
95
  end
103
96
  end
104
97
 
105
98
  def thumbnail_small
106
99
  if available?
107
- thumbnail_url.split('_')[0] + '_100x75.jpg'
100
+ thumbnail_url.split("_")[0] + "_100x75.jpg"
108
101
  end
109
102
  end
110
103
 
111
104
  def thumbnail_medium
112
105
  if available?
113
- thumbnail_url.split('_')[0] + '_200x150.jpg'
106
+ thumbnail_url.split("_")[0] + "_200x150.jpg"
114
107
  end
115
108
  end
116
109
 
117
110
  def thumbnail_large
118
111
  if available?
119
- thumbnail_url.split('_')[0] + '_640.jpg'
112
+ thumbnail_url.split("_")[0] + "_640.jpg"
120
113
  end
121
114
  end
122
115
 
123
116
  def view_count
124
117
  if available?
125
- user_interaction_count(interaction_type: "http://schema.org/WatchAction")
118
+ user_interaction_count(interaction_type: "WatchAction")
126
119
  end
127
120
  end
128
121
 
122
+ def stats
123
+ return {} unless available?
124
+ {
125
+ "plays" => view_count,
126
+ "likes" => user_interaction_count(interaction_type: "LikeAction"),
127
+ "comments" => user_interaction_count(interaction_type: "CommentAction")
128
+ }
129
+ end
130
+
129
131
  private
130
132
 
131
133
  def user_interaction_count(interaction_type:)
132
- interaction_statistic.find do |stat|
133
- stat["interactionType"] == interaction_type
134
- end["userInteractionCount"]
134
+ interaction_statistic&.find do |stat|
135
+ stat["interactionType"] == "http://schema.org/#{interaction_type}"
136
+ end&.public_send(:[], "userInteractionCount")
135
137
  end
136
138
 
137
139
  def interaction_statistic
@@ -139,39 +141,39 @@ class VideoInfo
139
141
  end
140
142
 
141
143
  def json_info
142
- @json_info ||= JSON.parse(data.css('script').detect do |n|
143
- type = n.attr('type')
144
+ @json_info ||= JSON.parse(data.css("script").detect do |n|
145
+ type = n.attr("type")
144
146
 
145
147
  if type.nil?
146
148
  false
147
149
  else
148
- type.value == 'application/ld+json'
150
+ type.value == "application/ld+json"
149
151
  end
150
152
  end.text)[0]
151
153
  end
152
154
 
153
155
  def thumbnail_url
154
- @thumbnail_url ||= remove_overlay(meta_node_value('og:image'))
156
+ @thumbnail_url ||= remove_overlay(meta_node_value("og:image"))
155
157
  end
156
158
 
157
159
  def remove_overlay(url)
158
160
  uri = URI.parse(url)
159
-
160
- if uri.path == '/filter/overlay'
161
- CGI::parse(uri.query)['src0'][0]
161
+
162
+ if uri.path == "/filter/overlay"
163
+ CGI.parse(uri.query)["src0"][0]
162
164
  else
163
165
  url
164
166
  end
165
167
  end
166
168
 
167
169
  def meta_nodes
168
- @meta_nodes ||= data.css('meta')
170
+ @meta_nodes ||= data.css("meta")
169
171
  end
170
172
 
171
173
  def meta_node_value(name)
172
174
  if available?
173
175
  node = meta_nodes.detect do |n|
174
- property = n.attr('property')
176
+ property = n.attr("property")
175
177
 
176
178
  if property.nil?
177
179
  false
@@ -180,20 +182,19 @@ class VideoInfo
180
182
  end
181
183
  end
182
184
 
183
- node.attr('content').value
185
+ node.attr("content").value
184
186
  end
185
187
  end
186
188
 
187
189
  def _set_data_from_api_impl(api_url)
188
- Oga.parse_html(URI.open(api_url.to_s).read)
189
-
190
+ Oga.parse_html(URI.parse(api_url.to_s).read)
190
191
  rescue OpenURI::HTTPError
191
192
  nil
192
193
  end
193
194
 
194
195
  def _api_url
195
196
  uri = URI.parse(@url)
196
- uri.scheme = 'https'
197
+ uri.scheme = "https"
197
198
  uri.to_s
198
199
  end
199
200
 
@@ -2,11 +2,11 @@ class VideoInfo
2
2
  module Providers
3
3
  class Wistia < Provider
4
4
  def self.usable?(url)
5
- url =~ /(.*)(wistia.com|wistia.net|wi.st)/
5
+ url.match?(/(.*)(wistia.com|wistia.net|wi.st)/)
6
6
  end
7
7
 
8
8
  def provider
9
- 'Wistia'
9
+ "Wistia"
10
10
  end
11
11
 
12
12
  %w[title duration width height].each do |method|
@@ -22,26 +22,26 @@ class VideoInfo
22
22
  end
23
23
 
24
24
  def thumbnail_small
25
- data['thumbnail_url']
25
+ data["thumbnail_url"]
26
26
  end
27
27
 
28
28
  def thumbnail_medium
29
- data['thumbnail_url']
29
+ data["thumbnail_url"]
30
30
  end
31
31
 
32
32
  def thumbnail_large
33
- data['thumbnail_url']
33
+ data["thumbnail_url"]
34
34
  end
35
35
 
36
36
  private
37
37
 
38
38
  def _url_regex
39
39
  %r{(?:.*)(?:wistia.com|wi.st|wistia.net)
40
- \/(?:embed\/)?(?:medias\/)?(?:iframe\/)?(.+)}x
40
+ /(?:embed/)?(?:medias/)?(?:iframe/)?(.+)}x
41
41
  end
42
42
 
43
43
  def _api_base
44
- 'fast.wistia.com'
44
+ "fast.wistia.com"
45
45
  end
46
46
 
47
47
  def _api_path
@@ -1,6 +1,6 @@
1
- require 'iso8601'
2
- require_relative 'youtube_api'
3
- require_relative 'youtube_scraper'
1
+ require "iso8601"
2
+ require_relative "youtube_api"
3
+ require_relative "youtube_scraper"
4
4
 
5
5
  class VideoInfo
6
6
  module Providers
@@ -16,12 +16,11 @@ class VideoInfo
16
16
  end
17
17
 
18
18
  def self.usable?(url)
19
- url =~ %r{(youtube\.com\/(?!playlist|embed\/videoseries).*)|
20
- (youtu\.be)}x
19
+ url.match?(/(youtube\.com\/(?!playlist|embed\/videoseries).*)|(youtu\.be)/)
21
20
  end
22
21
 
23
22
  def provider
24
- 'YouTube'
23
+ "YouTube"
25
24
  end
26
25
 
27
26
  %w[width height].each do |method|
@@ -55,12 +54,12 @@ class VideoInfo
55
54
  private
56
55
 
57
56
  def _url_regex
58
- %r{(?:youtube(?:-nocookie)?\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|
59
- .*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})}x
57
+ %r{(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?|live|shorts)/|
58
+ .*[?&]v=)|youtu\.be/)([^"&?/ ]{11})}x
60
59
  end
61
60
 
62
61
  def _default_iframe_attributes
63
- { allowfullscreen: 'allowfullscreen' }
62
+ {allowfullscreen: "allowfullscreen"}
64
63
  end
65
64
 
66
65
  def _default_url_attributes
@@ -2,9 +2,9 @@ class VideoInfo
2
2
  module Providers
3
3
  module YoutubeAPI
4
4
  def available?
5
- if !data['items'].empty?
6
- upload_status = data['items'][0]['status']['uploadStatus']
7
- 'rejected' != upload_status
5
+ if !data["items"].empty?
6
+ upload_status = data["items"][0]["status"]["uploadStatus"]
7
+ upload_status != "rejected"
8
8
  else
9
9
  false
10
10
  end
@@ -17,53 +17,58 @@ class VideoInfo
17
17
  end
18
18
 
19
19
  def author
20
- _video_snippet['channelTitle']
20
+ _video_snippet["channelTitle"]
21
21
  end
22
22
 
23
23
  def author_thumbnail
24
- _channel_snippet['thumbnails']['default']['url']
24
+ _channel_snippet["thumbnails"]["default"]["url"]
25
25
  end
26
26
 
27
27
  def author_url
28
- channel_id = _channel_info['items'][0]['id']
29
- 'https://www.youtube.com/channel/' + channel_id
28
+ channel_id = _channel_info["items"][0]["id"]
29
+ "https://www.youtube.com/channel/" + channel_id
30
30
  end
31
31
 
32
32
  def title
33
- _video_snippet['title']
33
+ _video_snippet["title"]
34
34
  end
35
35
 
36
36
  def description
37
- _video_snippet['description']
37
+ _video_snippet["description"]
38
38
  end
39
39
 
40
40
  def keywords
41
- _video_snippet['tags']
41
+ _video_snippet["tags"]
42
42
  end
43
43
 
44
44
  def duration
45
- video_duration = _video_content_details['duration'] || 0
45
+ video_duration = _video_content_details["duration"] || 0
46
46
  ISO8601::Duration.new(video_duration).to_seconds.to_i
47
47
  end
48
48
 
49
49
  def date
50
- return unless published_at = _video_snippet['publishedAt']
50
+ return unless (published_at = _video_snippet["publishedAt"])
51
51
  Time.parse(published_at, Time.now.utc)
52
52
  end
53
53
 
54
54
  def view_count
55
- _video_statistics['viewCount'].to_i
55
+ stats["viewCount"].to_i
56
+ end
57
+
58
+ def stats
59
+ return {} unless available?
60
+ data["items"][0]["statistics"]
56
61
  end
57
62
 
58
63
  private
59
64
 
60
65
  def _api_base
61
- 'www.googleapis.com'
66
+ "www.googleapis.com"
62
67
  end
63
68
 
64
69
  def _api_path
65
70
  "/youtube/v3/videos?id=#{video_id}" \
66
- '&part=snippet,statistics,status,contentDetails&fields=' \
71
+ "&part=snippet,statistics,status,contentDetails&fields=" \
67
72
  "items(id,snippet,statistics,status,contentDetails)&key=#{api_key}"
68
73
  end
69
74
 
@@ -73,7 +78,7 @@ class VideoInfo
73
78
 
74
79
  def _video_snippet
75
80
  return {} unless available?
76
- data['items'][0]['snippet']
81
+ data["items"][0]["snippet"]
77
82
  end
78
83
 
79
84
  def _channel_api_url(channel_id)
@@ -82,26 +87,21 @@ class VideoInfo
82
87
  end
83
88
 
84
89
  def _channel_info
85
- channel_url = _channel_api_url(_video_snippet['channelId'])
86
- @_channel_info ||= JSON.load(URI.open(channel_url).read)
90
+ channel_url = _channel_api_url(_video_snippet["channelId"])
91
+ @_channel_info ||= JSON.parse(URI.parse(channel_url).read)
87
92
  end
88
93
 
89
94
  def _channel_snippet
90
- _channel_info['items'][0]['snippet']
95
+ _channel_info["items"][0]["snippet"]
91
96
  end
92
97
 
93
98
  def _video_content_details
94
99
  return {} unless available?
95
- data['items'][0]['contentDetails']
96
- end
97
-
98
- def _video_statistics
99
- return {} unless available?
100
- data['items'][0]['statistics']
100
+ data["items"][0]["contentDetails"]
101
101
  end
102
102
 
103
103
  def _video_thumbnail(id)
104
- _video_entry['media$group']['media$thumbnail'][id]['url']
104
+ _video_entry["media$group"]["media$thumbnail"][id]["url"]
105
105
  end
106
106
  end
107
107
  end