video_info 3.0.2 → 4.0.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 +49 -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 +41 -40
- 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 +34 -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 +27 -23
- data/video_info.gemspec +23 -25
- metadata +31 -20
- 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: a38718ee6a56eeea64af973e390986e80592369b3493f9e769316b72f7bd20c3
|
4
|
+
data.tar.gz: 5d1d36326e69350b53ddfdf9e2473f5538a93453fc5a85d5f1da30238fc1194f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91f46cde99f57f21766f648edf87a9b18b8d6ac134ada1fb2f6aa00eebf545e5dee585dbe15113c542c41bcab6f4d8a16dcb4620f3927fc1d1aee5c802601d69
|
7
|
+
data.tar.gz: 72dac7cb696e34e02c562ff7d58dc997adb574a48bee51071468ff81d8e0d777abc72e8847d24b58f1bdba78b31345c51f0d6f249288a0fab942d43301754f7e
|
@@ -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,30 @@
|
|
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
|
-
Usage
|
25
|
-
-----
|
27
|
+
## Usage
|
26
28
|
|
27
29
|
### Note for YouTube and Vimeo usage!
|
28
30
|
|
@@ -30,19 +32,20 @@ Youtube and Vimeo have recently updated their APIs to require API keys.
|
|
30
32
|
|
31
33
|
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
34
|
|
33
|
-
|
34
|
-
|
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)
|
35
|
+
**How to get these API keys**
|
36
36
|
|
37
|
-
To get a
|
37
|
+
- 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).
|
38
|
+
- To get a Vimeo API key, [follow the instructions here](https://developer.vimeo.com/api/start).
|
38
39
|
|
39
40
|
To set the API keys, do the following:
|
40
|
-
|
41
|
+
|
42
|
+
```ruby
|
41
43
|
VideoInfo.provider_api_keys = { youtube: 'YOUR_YOUTUBE_API_KEY', vimeo: 'YOUR_VIMEO_API_KEY' }
|
42
44
|
```
|
43
45
|
|
46
|
+
### Basic Usage
|
44
47
|
|
45
|
-
```
|
48
|
+
```ruby
|
46
49
|
video = VideoInfo.new('http://www.dailymotion.com/video/x7lni3')
|
47
50
|
# video.available? => true
|
48
51
|
# video.video_id => 'x7lni3'
|
@@ -56,6 +59,7 @@ video = VideoInfo.new('http://www.dailymotion.com/video/x7lni3')
|
|
56
59
|
# video.thumbnail_large => 'http://s2.dmcdn.net/BgWxI/x720-YcV.jpg'
|
57
60
|
# video.embed_url => 'http://www.dailymotion.com/embed/video/x7lni3'
|
58
61
|
# video.embed_code => "<iframe src='//www.dailymotion.com/embed/video/x7lni3' frameborder='0' allowfullscreen='allowfullscreen'></iframe>"
|
62
|
+
# video.stats => {"views_total"=>10342797, "likes_total"=>3850}
|
59
63
|
|
60
64
|
video = VideoInfo.new("http://vimeo.com/898029")
|
61
65
|
# video.available? => true
|
@@ -76,6 +80,7 @@ video = VideoInfo.new("http://vimeo.com/898029")
|
|
76
80
|
# video.thumbnail_large => 'http://b.vimeocdn.com/ts/343/731/34373130_640.jpg'
|
77
81
|
# video.embed_url => 'http://player.vimeo.com/video/898029'
|
78
82
|
# video.embed_code => "<iframe src='//player.vimeo.com/video/898029?title=0&byline=0&portrait=0&autoplay=0' frameborder='0'></iframe>"
|
83
|
+
# video.stats => {"plays"=>630, "likes"=>3, "comments"=>0}
|
79
84
|
|
80
85
|
video = VideoInfo.new("http://fast.wistia.com/embed/medias/pxonqr42is")
|
81
86
|
# video.available? => true
|
@@ -107,6 +112,7 @@ video = VideoInfo.new("http://www.youtube.com/watch?v=mZqGqE0D0n4")
|
|
107
112
|
# video.thumbnail_large => 'http://i.ytimg.com/vi/mZqGqE0D0n4/hqdefault.jpg'
|
108
113
|
# video.embed_url => 'http://www.youtube.com/embed/mZqGqE0D0n4'
|
109
114
|
# video.embed_code => "<iframe src='//www.youtube.com/embed/mZqGqE0D0n4' frameborder='0' allowfullscreen='allowfullscreen'></iframe>"
|
115
|
+
# video.stats => {"viewCount"=>"8297", "likeCount"=>"66", "favoriteCount"=>"0", "commentCount"=>"5"}
|
110
116
|
|
111
117
|
playlist = VideoInfo.new("http://www.youtube.com/playlist?p=PL9hW1uS6HUftLdHI6RIsaf-iXTm09qnEr")
|
112
118
|
# playlist.available? => true
|
@@ -124,29 +130,40 @@ playlist = VideoInfo.new("http://www.youtube.com/playlist?p=PL9hW1uS6HUftLdHI6RI
|
|
124
130
|
# playlist.videos => [VideoInfo.new('http://www.youtube.com/watch?v=_Bt3-WsHfB0'), VideoInfo.new('http://www.youtube.com/watch?v=9g2U12SsRns'), VideoInfo.new('http://www.youtube.com/watch?v=8b0aEoxqqC0'), VideoInfo.new('http://www.youtube.com/watch?v=6c3mHikRz0I'), VideoInfo.new('http://www.youtube.com/watch?v=OQVHWsTHcoc')]
|
125
131
|
```
|
126
132
|
|
127
|
-
|
128
|
-
|
133
|
+
You can also use the `valid_url?` helper to check if a given url is valid in some of the _enabled_ providers:
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
> VideoInfo.valid_url?('http://www.youtube.com/watch?v=AT_5xOGh6Ko')
|
137
|
+
=> true
|
138
|
+
> VideoInfo.valid_url?('http://vimeo.com/898029')
|
139
|
+
=> true
|
140
|
+
> VideoInfo.valid_url?('http://www.example.com/video/12345')
|
141
|
+
=> false
|
142
|
+
```
|
143
|
+
|
144
|
+
### Options
|
129
145
|
|
130
|
-
```
|
146
|
+
```ruby
|
131
147
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', 'User-Agent' => 'My YouTube Mashup Robot/1.0')
|
132
148
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', 'Referer' => 'http://my-youtube-mashup.com/')
|
133
149
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', 'Referer' => 'http://my-youtube-mashup.com/',
|
134
150
|
'User-Agent' => 'My YouTube Mashup Robot/1.0')
|
135
151
|
```
|
152
|
+
|
136
153
|
You can also use **symbols** instead of strings (any non-word (`/[^a-z]/i`) character would be converted to hyphen).
|
137
154
|
|
138
|
-
```
|
155
|
+
```ruby
|
139
156
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', referer: 'http://my-youtube-mashup.com/',
|
140
157
|
user_agent: 'My YouTube Mashup Robot/1.0')
|
141
158
|
```
|
142
159
|
|
143
160
|
User-Agent when empty defaults to "VideoInfo/VERSION" - where version is current VideoInfo version, e.g. **"VideoInfo/0.2.7"**.
|
144
161
|
|
145
|
-
It supports all
|
162
|
+
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).
|
146
163
|
|
147
164
|
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:
|
148
165
|
|
149
|
-
```
|
166
|
+
```ruby
|
150
167
|
VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4').embed_code(iframe_attributes: { width: 800, height: 600, 'data-key' => 'value' })
|
151
168
|
=> '<iframe src="//www.youtube.com/embed/mZqGqE0D0n4" frameborder="0" allowfullscreen="allowfullscreen" width="800" height="600" data-key="value"></iframe>'
|
152
169
|
|
@@ -156,29 +173,29 @@ VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4').embed_code(url_attri
|
|
156
173
|
|
157
174
|
If you would like to disable certain providers, you can do so by modifying the class variable `disable_providers`:
|
158
175
|
|
159
|
-
```
|
176
|
+
```ruby
|
160
177
|
VideoInfo.disable_providers = %w[YouTube] # disable YouTube
|
161
178
|
VideoInfo.disable_providers = %w[Vimeo YouTube] # disable Vimeo and Youtube
|
162
179
|
VideoInfo.disable_providers = [] # enable all providers
|
163
180
|
```
|
164
181
|
|
165
|
-
|
166
|
-
|
182
|
+
**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.
|
183
|
+
|
184
|
+
## Contributing
|
167
185
|
|
186
|
+
Please read [the contributing guidelines](CONTRIBUTING.md).
|
168
187
|
|
169
|
-
Author
|
170
|
-
------
|
188
|
+
### Author
|
171
189
|
|
172
190
|
[Thibaud Guillaume-Gentil](https://github.com/thibaudgg) ([@thibaudgg](https://twitter.com/thibaudgg))
|
173
191
|
|
174
|
-
Maintainers
|
175
|
-
-----------
|
192
|
+
### Maintainers
|
176
193
|
|
177
194
|
- [Thibaud Guillaume-Gentil](https://github.com/thibaudgg) ([@thibaudgg](https://twitter.com/thibaudgg))
|
178
|
-
- [Vincent Heuken](https://github.com/vheuken)
|
179
|
-
- [João Vieira](https://github.com/joaocv3)
|
195
|
+
- [Vincent Heuken](https://github.com/vheuken)
|
196
|
+
- [João Vieira](https://github.com/joaocv3)
|
197
|
+
- [Marc Anguera](https://github.com/markets)
|
180
198
|
|
181
|
-
Contributors
|
182
|
-
------------
|
199
|
+
### Contributors
|
183
200
|
|
184
201
|
[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?(/(vimeo\.com\/(?!album|hubnut\/album).*)/)
|
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
|