video_info 3.1.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +44 -0
- data/.gitignore +1 -1
- data/.rspec +1 -0
- data/CONTRIBUTING.md +6 -6
- data/Gemfile +1 -9
- data/README.md +44 -32
- data/Rakefile +3 -2
- data/lib/video_info/provider.rb +28 -22
- data/lib/video_info/providers/dailymotion.rb +25 -18
- data/lib/video_info/providers/vimeo.rb +12 -12
- data/lib/video_info/providers/vimeo_api.rb +19 -15
- data/lib/video_info/providers/vimeo_scraper.rb +43 -42
- data/lib/video_info/providers/wistia.rb +7 -7
- data/lib/video_info/providers/youtube.rb +8 -9
- data/lib/video_info/providers/youtube_api.rb +26 -26
- data/lib/video_info/providers/youtube_scraper.rb +38 -29
- data/lib/video_info/providers/youtubeplaylist.rb +6 -7
- data/lib/video_info/providers/youtubeplaylist_api.rb +12 -12
- data/lib/video_info/providers/youtubeplaylist_scraper.rb +10 -12
- data/lib/video_info/version.rb +1 -1
- data/lib/video_info.rb +17 -23
- data/video_info.gemspec +23 -25
- metadata +42 -31
- data/.github/workflows/unit_test.yml +0 -42
- data/.hound.yml +0 -3
- data/.rubocop.yml +0 -243
- data/Guardfile +0 -8
- data/tmp/rspec_guard_result +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b389a80be182106eeba217bf53d64801d78c9e95110e39c136d53af11dd813fe
|
4
|
+
data.tar.gz: 6dc99daeaafd264ef991232c85fa5bc6b4c3713d8ef83895e48bc6f27a461d61
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91095899474824019cc2fa55f128fd20c3fe288aa558de950abc2ea39f2546cdfb68597992e1abad1f6294ea9deb49c190ce8676bcb036cbb2d82ee6177082d6
|
7
|
+
data.tar.gz: d0a09d7f75591250157f8d4c2e9996a7072db3f41bf1fed92adf8235066c535147f7c1d4f0b5451aec16673c33635577e2bfb0d5c29cf5a901bcabb51b0abcd7
|
@@ -0,0 +1,44 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [master]
|
6
|
+
pull_request:
|
7
|
+
branches: [master]
|
8
|
+
|
9
|
+
permissions:
|
10
|
+
checks: write
|
11
|
+
contents: read
|
12
|
+
|
13
|
+
env:
|
14
|
+
YOUTUBE_API_KEY: ${{ secrets.YOUTUBE_API_KEY }}
|
15
|
+
VIMEO_ACCESS_TOKEN: ${{ secrets.VIMEO_ACCESS_TOKEN }}
|
16
|
+
|
17
|
+
jobs:
|
18
|
+
specs:
|
19
|
+
runs-on: ubuntu-latest
|
20
|
+
strategy:
|
21
|
+
fail-fast: false
|
22
|
+
matrix:
|
23
|
+
ruby: ['2.7', '3.0', '3.1', '3.2', 'head']
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v3
|
26
|
+
- uses: ruby/setup-ruby@v1
|
27
|
+
with:
|
28
|
+
ruby-version: ${{ matrix.ruby }}
|
29
|
+
bundler-cache: true
|
30
|
+
- name: Run tests
|
31
|
+
run: bundle exec rspec
|
32
|
+
- name: Publish code coverage
|
33
|
+
uses: paambaati/codeclimate-action@v3.2.0
|
34
|
+
env:
|
35
|
+
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
|
36
|
+
with:
|
37
|
+
coverageLocations: ${{ github.workspace }}/coverage/coverage.json:simplecov
|
38
|
+
linter:
|
39
|
+
runs-on: ubuntu-latest
|
40
|
+
steps:
|
41
|
+
- name: StandardRB Linter
|
42
|
+
uses: amoeba/standardrb-action@v4
|
43
|
+
env:
|
44
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/CONTRIBUTING.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
Contributing
|
2
|
-
--------
|
1
|
+
# Contributing
|
3
2
|
|
4
3
|
The guidelines for contributions are as follows:
|
5
|
-
|
6
|
-
* Make sure
|
7
|
-
* Make sure
|
4
|
+
|
5
|
+
* Make sure you include comprehensive specs for new features and bug-fixes.
|
6
|
+
* Make sure all of the specs pass by running `bundle exec rspec` in the root project directory. Pull requests with failing tests will not be merged.
|
7
|
+
* Make sure there are no code style issues by running `bundle exec standardrb` in the root project directory. Pull requests with style issues will not be merged.
|
8
8
|
* Optimally, you should create a separate branch to make rebasing with `master` simpler if other work gets merged in before your patch does.
|
9
|
-
* In bug reports, post the outputs of `VideoInfo::VERSION` and `ruby --version
|
9
|
+
* In bug reports, post the outputs of `VideoInfo::VERSION` and `ruby --version`.
|
10
10
|
* In bug reports, provide detailed and clear reproduction steps. Optimally, provide some sample code.
|
11
11
|
* In bug reports, try to test against the `master` branch. If the bug does not exist in `master`, it is most likely known and a fix will be in the next release.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,28 +1,36 @@
|
|
1
1
|
# VideoInfo
|
2
2
|
|
3
|
-
[![Gem Version](https://badge.fury.io/rb/video_info.svg)](http://badge.fury.io/rb/video_info)
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/video_info.svg)](http://badge.fury.io/rb/video_info)
|
4
|
+
[![CI](https://github.com/thibaudgg/video_info/actions/workflows/ci.yml/badge.svg)](https://github.com/thibaudgg/video_info/actions/workflows/ci.yml)
|
5
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/1f03474bdb81e735002c/maintainability)](https://codeclimate.com/github/thibaudgg/video_info/maintainability)
|
6
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/1f03474bdb81e735002c/test_coverage)](https://codeclimate.com/github/thibaudgg/video_info/test_coverage)
|
7
|
+
[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
|
4
8
|
|
5
9
|
Simple Ruby Gem to get video info from Dailymotion, Vimeo, Wistia and YouTube (with playlist).
|
6
10
|
|
7
|
-
Tested against Ruby 2.
|
11
|
+
Tested against Ruby 2.7, 3.0, 3.1 and 3.2.
|
12
|
+
|
13
|
+
## Features
|
8
14
|
|
9
|
-
Features
|
10
|
-
--------
|
11
15
|
* Simple, single-function API that returns a simple data structure
|
12
16
|
* Has a mere three gem dependencies
|
13
17
|
* Automatic fallback to scrapers when required API keys aren't provided
|
14
18
|
* Fetches metadata on the video, including title, duration, upload date, description, keywords, thumbnail, and dimensions
|
15
19
|
* Fetches metadata on the author, including name, thumbnail, and channel/profile URL
|
16
20
|
|
17
|
-
Install
|
18
|
-
--------
|
21
|
+
## Install
|
19
22
|
|
20
|
-
```
|
23
|
+
```bash
|
21
24
|
gem install video_info
|
22
25
|
```
|
23
26
|
|
24
|
-
|
25
|
-
|
27
|
+
Or add to the Gemfile:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
gem 'video_info'
|
31
|
+
```
|
32
|
+
|
33
|
+
## Usage
|
26
34
|
|
27
35
|
### Note for YouTube and Vimeo usage!
|
28
36
|
|
@@ -30,19 +38,20 @@ Youtube and Vimeo have recently updated their APIs to require API keys.
|
|
30
38
|
|
31
39
|
Scrapers has been implemented for both Youtube and Vimeo. However, the Youtube scraper can only get the date the video was posted, while the API is able to get the date and the exact time the video was posted. You may also wish to use the API to protect against potential HTML changes that could break the scrapers.
|
32
40
|
|
33
|
-
|
41
|
+
**How to get these API keys**
|
34
42
|
|
35
|
-
After generating a Youtube API key it is necessary to enable the YouTube Data API for the project which your API key was generated [enable Youtube Data API here](https://console.developers.google.com/apis/library/youtube.googleapis.com)
|
36
|
-
|
37
|
-
To get a Vimeo API key, [follow the instructions here](https://developer.vimeo.com/api/start)
|
43
|
+
- To get a Youtube API key, [follow the instructions here](https://developers.google.com/youtube/registering_an_application). After generating a Youtube API key it is necessary to enable the YouTube Data API for the project which your API key was generated [enable Youtube Data API here](https://console.developers.google.com/apis/library/youtube.googleapis.com).
|
44
|
+
- To get a Vimeo API key, [follow the instructions here](https://developer.vimeo.com/api/start).
|
38
45
|
|
39
46
|
To set the API keys, do the following:
|
40
|
-
|
47
|
+
|
48
|
+
```ruby
|
41
49
|
VideoInfo.provider_api_keys = { youtube: 'YOUR_YOUTUBE_API_KEY', vimeo: 'YOUR_VIMEO_API_KEY' }
|
42
50
|
```
|
43
51
|
|
52
|
+
### Basic Usage
|
44
53
|
|
45
|
-
```
|
54
|
+
```ruby
|
46
55
|
video = VideoInfo.new('http://www.dailymotion.com/video/x7lni3')
|
47
56
|
# video.available? => true
|
48
57
|
# video.video_id => 'x7lni3'
|
@@ -56,6 +65,7 @@ video = VideoInfo.new('http://www.dailymotion.com/video/x7lni3')
|
|
56
65
|
# video.thumbnail_large => 'http://s2.dmcdn.net/BgWxI/x720-YcV.jpg'
|
57
66
|
# video.embed_url => 'http://www.dailymotion.com/embed/video/x7lni3'
|
58
67
|
# video.embed_code => "<iframe src='//www.dailymotion.com/embed/video/x7lni3' frameborder='0' allowfullscreen='allowfullscreen'></iframe>"
|
68
|
+
# video.stats => {"views_total"=>10342797, "likes_total"=>3850}
|
59
69
|
|
60
70
|
video = VideoInfo.new("http://vimeo.com/898029")
|
61
71
|
# video.available? => true
|
@@ -76,6 +86,7 @@ video = VideoInfo.new("http://vimeo.com/898029")
|
|
76
86
|
# video.thumbnail_large => 'http://b.vimeocdn.com/ts/343/731/34373130_640.jpg'
|
77
87
|
# video.embed_url => 'http://player.vimeo.com/video/898029'
|
78
88
|
# video.embed_code => "<iframe src='//player.vimeo.com/video/898029?title=0&byline=0&portrait=0&autoplay=0' frameborder='0'></iframe>"
|
89
|
+
# video.stats => {"plays"=>630, "likes"=>3, "comments"=>0}
|
79
90
|
|
80
91
|
video = VideoInfo.new("http://fast.wistia.com/embed/medias/pxonqr42is")
|
81
92
|
# video.available? => true
|
@@ -107,6 +118,7 @@ video = VideoInfo.new("http://www.youtube.com/watch?v=mZqGqE0D0n4")
|
|
107
118
|
# video.thumbnail_large => 'http://i.ytimg.com/vi/mZqGqE0D0n4/hqdefault.jpg'
|
108
119
|
# video.embed_url => 'http://www.youtube.com/embed/mZqGqE0D0n4'
|
109
120
|
# video.embed_code => "<iframe src='//www.youtube.com/embed/mZqGqE0D0n4' frameborder='0' allowfullscreen='allowfullscreen'></iframe>"
|
121
|
+
# video.stats => {"viewCount"=>"8297", "likeCount"=>"66", "favoriteCount"=>"0", "commentCount"=>"5"}
|
110
122
|
|
111
123
|
playlist = VideoInfo.new("http://www.youtube.com/playlist?p=PL9hW1uS6HUftLdHI6RIsaf-iXTm09qnEr")
|
112
124
|
# playlist.available? => true
|
@@ -135,29 +147,29 @@ You can also use the `valid_url?` helper to check if a given url is valid in som
|
|
135
147
|
=> false
|
136
148
|
```
|
137
149
|
|
138
|
-
Options
|
139
|
-
-------
|
150
|
+
### Options
|
140
151
|
|
141
|
-
```
|
152
|
+
```ruby
|
142
153
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', 'User-Agent' => 'My YouTube Mashup Robot/1.0')
|
143
154
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', 'Referer' => 'http://my-youtube-mashup.com/')
|
144
155
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', 'Referer' => 'http://my-youtube-mashup.com/',
|
145
156
|
'User-Agent' => 'My YouTube Mashup Robot/1.0')
|
146
157
|
```
|
158
|
+
|
147
159
|
You can also use **symbols** instead of strings (any non-word (`/[^a-z]/i`) character would be converted to hyphen).
|
148
160
|
|
149
|
-
```
|
161
|
+
```ruby
|
150
162
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', referer: 'http://my-youtube-mashup.com/',
|
151
163
|
user_agent: 'My YouTube Mashup Robot/1.0')
|
152
164
|
```
|
153
165
|
|
154
166
|
User-Agent when empty defaults to "VideoInfo/VERSION" - where version is current VideoInfo version, e.g. **"VideoInfo/0.2.7"**.
|
155
167
|
|
156
|
-
It supports all
|
168
|
+
It supports all `OpenURI` header fields (options), for more information see: [OpenURI docs](https://ruby-doc.org/3.2.0/stdlibs/open-uri/OpenURI.html).
|
157
169
|
|
158
170
|
You can also include an `iframe_attributes` or `url_attributes` hash to the `embed_code` method to include arbitrary attributes in the iframe embed code or as additional URL params:
|
159
171
|
|
160
|
-
```
|
172
|
+
```ruby
|
161
173
|
VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4').embed_code(iframe_attributes: { width: 800, height: 600, 'data-key' => 'value' })
|
162
174
|
=> '<iframe src="//www.youtube.com/embed/mZqGqE0D0n4" frameborder="0" allowfullscreen="allowfullscreen" width="800" height="600" data-key="value"></iframe>'
|
163
175
|
|
@@ -167,29 +179,29 @@ VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4').embed_code(url_attri
|
|
167
179
|
|
168
180
|
If you would like to disable certain providers, you can do so by modifying the class variable `disable_providers`:
|
169
181
|
|
170
|
-
```
|
182
|
+
```ruby
|
171
183
|
VideoInfo.disable_providers = %w[YouTube] # disable YouTube
|
172
184
|
VideoInfo.disable_providers = %w[Vimeo YouTube] # disable Vimeo and Youtube
|
173
185
|
VideoInfo.disable_providers = [] # enable all providers
|
174
186
|
```
|
175
187
|
|
176
|
-
|
177
|
-
|
188
|
+
**NOTE:** `disable_providers` is case-insensitive. Attempting to use a disabled provider will raise a UrlError, just like attempting to use a non-video URL.
|
189
|
+
|
190
|
+
## Contributing
|
178
191
|
|
192
|
+
Please read [the contributing guidelines](CONTRIBUTING.md).
|
179
193
|
|
180
|
-
Author
|
181
|
-
------
|
194
|
+
### Author
|
182
195
|
|
183
196
|
[Thibaud Guillaume-Gentil](https://github.com/thibaudgg) ([@thibaudgg](https://twitter.com/thibaudgg))
|
184
197
|
|
185
|
-
Maintainers
|
186
|
-
-----------
|
198
|
+
### Maintainers
|
187
199
|
|
188
200
|
- [Thibaud Guillaume-Gentil](https://github.com/thibaudgg) ([@thibaudgg](https://twitter.com/thibaudgg))
|
189
|
-
- [Vincent Heuken](https://github.com/vheuken)
|
190
|
-
- [João Vieira](https://github.com/joaocv3)
|
201
|
+
- [Vincent Heuken](https://github.com/vheuken)
|
202
|
+
- [João Vieira](https://github.com/joaocv3)
|
203
|
+
- [Marc Anguera](https://github.com/markets)
|
191
204
|
|
192
|
-
Contributors
|
193
|
-
------------
|
205
|
+
### Contributors
|
194
206
|
|
195
207
|
[https://github.com/thibaudgg/video_info/graphs/contributors](https://github.com/thibaudgg/video_info/graphs/contributors)
|
data/Rakefile
CHANGED
data/lib/video_info/provider.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "open-uri"
|
2
|
+
require "json"
|
3
|
+
require "uri"
|
4
|
+
require "net/http"
|
5
|
+
require "openssl"
|
4
6
|
|
5
7
|
class VideoInfo
|
6
8
|
class Provider
|
7
|
-
attr_accessor :url, :options, :
|
9
|
+
attr_accessor :url, :options, :video_id
|
8
10
|
attr_writer :data
|
9
11
|
|
10
12
|
def initialize(url, options = {})
|
@@ -15,7 +17,7 @@ class VideoInfo
|
|
15
17
|
|
16
18
|
def self.usable?(_url)
|
17
19
|
raise NotImplementedError.new(
|
18
|
-
|
20
|
+
"Provider class must implement .usable? public method"
|
19
21
|
)
|
20
22
|
end
|
21
23
|
|
@@ -26,7 +28,7 @@ class VideoInfo
|
|
26
28
|
_default_iframe_attributes.merge(iframe_attributes)
|
27
29
|
)
|
28
30
|
|
29
|
-
"<iframe #{iframe_attrs.reject(&:empty?).join(
|
31
|
+
"<iframe #{iframe_attrs.reject(&:empty?).join(" ")}></iframe>"
|
30
32
|
end
|
31
33
|
|
32
34
|
def data
|
@@ -34,7 +36,7 @@ class VideoInfo
|
|
34
36
|
end
|
35
37
|
|
36
38
|
def available?
|
37
|
-
!%w[403 404 400].include?(_response_code)
|
39
|
+
!%w[403 404 400 451 401].include?(_response_code)
|
38
40
|
end
|
39
41
|
|
40
42
|
def thumbnail
|
@@ -51,13 +53,17 @@ class VideoInfo
|
|
51
53
|
nil
|
52
54
|
end
|
53
55
|
|
56
|
+
def stats
|
57
|
+
{}
|
58
|
+
end
|
59
|
+
|
54
60
|
private
|
55
61
|
|
56
62
|
def _response_code
|
57
63
|
uri = URI.parse(_api_url)
|
58
64
|
http = Net::HTTP.new(uri.host, uri.port)
|
59
65
|
|
60
|
-
if uri.scheme ==
|
66
|
+
if uri.scheme == "https"
|
61
67
|
_https_response_code(http)
|
62
68
|
else
|
63
69
|
_http_response_code(http)
|
@@ -78,7 +84,7 @@ class VideoInfo
|
|
78
84
|
|
79
85
|
def _clean_options(options)
|
80
86
|
options =
|
81
|
-
{
|
87
|
+
{"User-Agent" => "VideoInfo/#{VideoInfo::VERSION}"}.merge(options)
|
82
88
|
options.dup.each do |key, value|
|
83
89
|
if _not_openuri_option_symbol?(key)
|
84
90
|
options[_http_header_field(key)] = value
|
@@ -92,16 +98,16 @@ class VideoInfo
|
|
92
98
|
_set_data_from_api_impl(api_url)
|
93
99
|
rescue OpenURI::HTTPError, *NetHttpTimeoutErrors.all => e
|
94
100
|
if e.instance_of?(OpenURI::HTTPError) &&
|
95
|
-
|
96
|
-
|
101
|
+
e.respond_to?(:io) &&
|
102
|
+
e.io.respond_to?(:status)
|
97
103
|
response_code = e.io.status[0]
|
98
|
-
if response_code ==
|
99
|
-
log_warn(
|
104
|
+
if response_code == "400"
|
105
|
+
log_warn("Your API key is probably invalid. Please verify it.")
|
100
106
|
end
|
101
107
|
end
|
102
108
|
|
103
|
-
msg =
|
104
|
-
|
109
|
+
msg = "Unexpected network error while fetching information about the video"
|
110
|
+
msg << " (response code: #{response_code})" if defined?(response_code)
|
105
111
|
raise VideoInfo::HttpError.new(msg)
|
106
112
|
end
|
107
113
|
|
@@ -110,16 +116,16 @@ class VideoInfo
|
|
110
116
|
end
|
111
117
|
|
112
118
|
def _set_data_from_api_impl(api_url)
|
113
|
-
uri = URI.
|
114
|
-
JSON.
|
119
|
+
uri = URI.parse(api_url)
|
120
|
+
JSON.parse(uri.read(options))
|
115
121
|
end
|
116
122
|
|
117
123
|
def _not_openuri_option_symbol?(key)
|
118
|
-
key.is_a?(Symbol) && !OpenURI::Options.
|
124
|
+
key.is_a?(Symbol) && !OpenURI::Options.key?(key)
|
119
125
|
end
|
120
126
|
|
121
127
|
def _http_header_field(key)
|
122
|
-
key.to_s.split(/[^a-z]/i).map(&:capitalize).join(
|
128
|
+
key.to_s.split(/[^a-z]/i).map(&:capitalize).join("-")
|
123
129
|
end
|
124
130
|
|
125
131
|
def _set_video_id_from_url
|
@@ -135,13 +141,13 @@ class VideoInfo
|
|
135
141
|
|
136
142
|
def _url_regex
|
137
143
|
raise NotImplementedError.new(
|
138
|
-
|
144
|
+
"Provider class must implement #_url_regex private method"
|
139
145
|
)
|
140
146
|
end
|
141
147
|
|
142
148
|
def _api_url
|
143
149
|
raise NotImplementedError.new(
|
144
|
-
|
150
|
+
"Provider class must implement #_api_url private method"
|
145
151
|
)
|
146
152
|
end
|
147
153
|
|
@@ -156,7 +162,7 @@ class VideoInfo
|
|
156
162
|
|
157
163
|
def _hash_to_attributes(hash)
|
158
164
|
return unless hash.is_a?(Hash)
|
159
|
-
hash.map { |k, v| "#{k}=\"#{v}\"" }.join(
|
165
|
+
hash.map { |k, v| "#{k}=\"#{v}\"" }.join(" ")
|
160
166
|
end
|
161
167
|
|
162
168
|
def _hash_to_params(hash)
|
@@ -2,11 +2,11 @@ class VideoInfo
|
|
2
2
|
module Providers
|
3
3
|
class Dailymotion < Provider
|
4
4
|
def self.usable?(url)
|
5
|
-
url
|
5
|
+
url.match?(/(dai(?:\.ly|lymotion\.com))/)
|
6
6
|
end
|
7
7
|
|
8
8
|
def provider
|
9
|
-
|
9
|
+
"Dailymotion"
|
10
10
|
end
|
11
11
|
|
12
12
|
%w[title description duration].each do |method|
|
@@ -18,19 +18,19 @@ class VideoInfo
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def author
|
21
|
-
data[
|
21
|
+
data["owner.screenname"]
|
22
22
|
end
|
23
23
|
|
24
24
|
def author_url
|
25
|
-
data[
|
25
|
+
data["owner.url"]
|
26
26
|
end
|
27
27
|
|
28
28
|
def author_thumbnail
|
29
|
-
data[
|
29
|
+
data["owner.avatar_60_url"]
|
30
30
|
end
|
31
31
|
|
32
32
|
def keywords
|
33
|
-
data[
|
33
|
+
data["tags"]
|
34
34
|
end
|
35
35
|
|
36
36
|
def embed_url
|
@@ -38,23 +38,30 @@ class VideoInfo
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def date
|
41
|
-
Time.at(data[
|
41
|
+
Time.at(data["created_time"]).utc
|
42
42
|
end
|
43
43
|
|
44
44
|
def thumbnail_small
|
45
|
-
data[
|
45
|
+
data["thumbnail_60_url"]
|
46
46
|
end
|
47
47
|
|
48
48
|
def thumbnail_medium
|
49
|
-
data[
|
49
|
+
data["thumbnail_240_url"]
|
50
50
|
end
|
51
51
|
|
52
52
|
def thumbnail_large
|
53
|
-
data[
|
53
|
+
data["thumbnail_720_url"]
|
54
54
|
end
|
55
55
|
|
56
56
|
def view_count
|
57
|
-
data[
|
57
|
+
data["views_total"].to_i
|
58
|
+
end
|
59
|
+
|
60
|
+
def stats
|
61
|
+
{
|
62
|
+
"views_total" => view_count,
|
63
|
+
"likes_total" => data["likes_total"].to_i
|
64
|
+
}
|
58
65
|
end
|
59
66
|
|
60
67
|
private
|
@@ -68,11 +75,11 @@ class VideoInfo
|
|
68
75
|
end
|
69
76
|
|
70
77
|
def _url_regex
|
71
|
-
%r{dai(?:\.ly|lymotion\.com
|
78
|
+
%r{dai(?:\.ly|lymotion\.com/(?:embed/)?video)/([a-zA-Z0-9]*)}
|
72
79
|
end
|
73
80
|
|
74
81
|
def _api_base
|
75
|
-
|
82
|
+
"api.dailymotion.com"
|
76
83
|
end
|
77
84
|
|
78
85
|
def _api_path
|
@@ -81,10 +88,10 @@ class VideoInfo
|
|
81
88
|
|
82
89
|
def _api_url
|
83
90
|
"https://#{_api_base}#{_api_path}?" \
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
91
|
+
"fields=id,title,description,duration,created_time," \
|
92
|
+
"url,views_total,tags,thumbnail_url,thumbnail_720_url," \
|
93
|
+
"owner.url,owner.screenname,owner.avatar_60_url," \
|
94
|
+
"thumbnail_240_url,thumbnail_60_url,likes_total"
|
88
95
|
end
|
89
96
|
|
90
97
|
def _default_iframe_attributes
|
@@ -92,7 +99,7 @@ class VideoInfo
|
|
92
99
|
end
|
93
100
|
|
94
101
|
def _default_url_attributes
|
95
|
-
{
|
102
|
+
{autoplay: 0}
|
96
103
|
end
|
97
104
|
end
|
98
105
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require_relative
|
2
|
-
require_relative
|
1
|
+
require_relative "vimeo_api"
|
2
|
+
require_relative "vimeo_scraper"
|
3
3
|
|
4
4
|
class VideoInfo
|
5
5
|
module Providers
|
@@ -15,11 +15,11 @@ class VideoInfo
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.usable?(url)
|
18
|
-
url
|
18
|
+
url.match?(%r{(vimeo\.com/(?!album|hubnut/album|user\d+/?\z).*)})
|
19
19
|
end
|
20
20
|
|
21
21
|
def provider
|
22
|
-
|
22
|
+
"Vimeo"
|
23
23
|
end
|
24
24
|
|
25
25
|
def embed_url
|
@@ -30,10 +30,10 @@ class VideoInfo
|
|
30
30
|
|
31
31
|
def _url_regex
|
32
32
|
%r{.*\.com&&
|
33
|
-
|
34
|
-
|(?:ondemand|channels)(?:(
|
35
|
-
|(?:user[0-9]
|
36
|
-
|(
|
33
|
+
|/(?:(?:groups/[^/]+/videos/)
|
34
|
+
|(?:ondemand|channels)(?:(?:/less/)
|
35
|
+
|(?:user[0-9]+/review/)?([0-9]+).*
|
36
|
+
|(?:/\w*/))|(?:video/))?([0-9]+).*$
|
37
37
|
}x
|
38
38
|
end
|
39
39
|
|
@@ -42,10 +42,10 @@ class VideoInfo
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def _default_url_attributes
|
45
|
-
{
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
{title: 0,
|
46
|
+
byline: 0,
|
47
|
+
portrait: 0,
|
48
|
+
autoplay: 0}
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|