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.
- 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 +3 -8
- data/README.md +60 -34
- 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 +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: c8147a3698a183d13edcbf0a4bb084741c99b6c64f69d562ce441f7e116a8d8d
|
4
|
+
data.tar.gz: 2b52569e7059929c4c64816f5f204bdd74fd669b775558dc76a8ef8dca693bb1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bda11c5fc3854079bfe460e3a161dbba6cdd47219004b9a03f05a60448633f81e8712480e933d3812294e52dee5eedb89c44376b2872663853eea8764e9bfda4
|
7
|
+
data.tar.gz: 274803d8d83b50659cdae0b6b7f59abf7c20595d07ddedc3627298a8f7b01b0a45bd72f5bfbc7d3b58d25831c9fea408d1eccc5ce7ba0d726badf30ddbcfc1d8
|
@@ -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', '3.3', '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
@@ -1,11 +1,6 @@
|
|
1
|
-
source
|
1
|
+
source "http://rubygems.org"
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in video_info.gemspec
|
4
3
|
gemspec
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
group :tool do
|
9
|
-
gem 'ruby_gntp'
|
10
|
-
gem 'guard-rspec'
|
11
|
-
end
|
5
|
+
# Temporal Ruby 3.4 support, see more: https://github.com/vcr/vcr/pull/1003
|
6
|
+
gem 'base64'
|
data/README.md
CHANGED
@@ -1,28 +1,39 @@
|
|
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
|
-
Simple Ruby Gem to get video
|
9
|
+
Simple Ruby Gem to get video information from different providers. Supported providers:
|
6
10
|
|
7
|
-
|
11
|
+
- YouTube (with playlists)
|
12
|
+
- Vimeo
|
13
|
+
- Dailymotion
|
14
|
+
- Wistia
|
15
|
+
|
16
|
+
## Features
|
8
17
|
|
9
|
-
Features
|
10
|
-
--------
|
11
18
|
* Simple, single-function API that returns a simple data structure
|
12
19
|
* Has a mere three gem dependencies
|
13
20
|
* Automatic fallback to scrapers when required API keys aren't provided
|
14
21
|
* Fetches metadata on the video, including title, duration, upload date, description, keywords, thumbnail, and dimensions
|
15
22
|
* Fetches metadata on the author, including name, thumbnail, and channel/profile URL
|
16
23
|
|
17
|
-
Install
|
18
|
-
--------
|
24
|
+
## Install
|
19
25
|
|
20
|
-
```
|
26
|
+
```bash
|
21
27
|
gem install video_info
|
22
28
|
```
|
23
29
|
|
24
|
-
|
25
|
-
|
30
|
+
Or add to the Gemfile:
|
31
|
+
|
32
|
+
```bash
|
33
|
+
gem 'video_info'
|
34
|
+
```
|
35
|
+
|
36
|
+
## Usage
|
26
37
|
|
27
38
|
### Note for YouTube and Vimeo usage!
|
28
39
|
|
@@ -30,19 +41,20 @@ Youtube and Vimeo have recently updated their APIs to require API keys.
|
|
30
41
|
|
31
42
|
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
43
|
|
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)
|
44
|
+
**How to get these API keys**
|
36
45
|
|
37
|
-
To get a
|
46
|
+
- 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).
|
47
|
+
- To get a Vimeo API key, [follow the instructions here](https://developer.vimeo.com/api/start).
|
38
48
|
|
39
49
|
To set the API keys, do the following:
|
40
|
-
|
50
|
+
|
51
|
+
```ruby
|
41
52
|
VideoInfo.provider_api_keys = { youtube: 'YOUR_YOUTUBE_API_KEY', vimeo: 'YOUR_VIMEO_API_KEY' }
|
42
53
|
```
|
43
54
|
|
55
|
+
### Basic Usage
|
44
56
|
|
45
|
-
```
|
57
|
+
```ruby
|
46
58
|
video = VideoInfo.new('http://www.dailymotion.com/video/x7lni3')
|
47
59
|
# video.available? => true
|
48
60
|
# video.video_id => 'x7lni3'
|
@@ -56,6 +68,7 @@ video = VideoInfo.new('http://www.dailymotion.com/video/x7lni3')
|
|
56
68
|
# video.thumbnail_large => 'http://s2.dmcdn.net/BgWxI/x720-YcV.jpg'
|
57
69
|
# video.embed_url => 'http://www.dailymotion.com/embed/video/x7lni3'
|
58
70
|
# video.embed_code => "<iframe src='//www.dailymotion.com/embed/video/x7lni3' frameborder='0' allowfullscreen='allowfullscreen'></iframe>"
|
71
|
+
# video.stats => {"views_total"=>10342797, "likes_total"=>3850}
|
59
72
|
|
60
73
|
video = VideoInfo.new("http://vimeo.com/898029")
|
61
74
|
# video.available? => true
|
@@ -76,6 +89,7 @@ video = VideoInfo.new("http://vimeo.com/898029")
|
|
76
89
|
# video.thumbnail_large => 'http://b.vimeocdn.com/ts/343/731/34373130_640.jpg'
|
77
90
|
# video.embed_url => 'http://player.vimeo.com/video/898029'
|
78
91
|
# video.embed_code => "<iframe src='//player.vimeo.com/video/898029?title=0&byline=0&portrait=0&autoplay=0' frameborder='0'></iframe>"
|
92
|
+
# video.stats => {"plays"=>630, "likes"=>3, "comments"=>0}
|
79
93
|
|
80
94
|
video = VideoInfo.new("http://fast.wistia.com/embed/medias/pxonqr42is")
|
81
95
|
# video.available? => true
|
@@ -107,6 +121,7 @@ video = VideoInfo.new("http://www.youtube.com/watch?v=mZqGqE0D0n4")
|
|
107
121
|
# video.thumbnail_large => 'http://i.ytimg.com/vi/mZqGqE0D0n4/hqdefault.jpg'
|
108
122
|
# video.embed_url => 'http://www.youtube.com/embed/mZqGqE0D0n4'
|
109
123
|
# video.embed_code => "<iframe src='//www.youtube.com/embed/mZqGqE0D0n4' frameborder='0' allowfullscreen='allowfullscreen'></iframe>"
|
124
|
+
# video.stats => {"viewCount"=>"8297", "likeCount"=>"66", "favoriteCount"=>"0", "commentCount"=>"5"}
|
110
125
|
|
111
126
|
playlist = VideoInfo.new("http://www.youtube.com/playlist?p=PL9hW1uS6HUftLdHI6RIsaf-iXTm09qnEr")
|
112
127
|
# playlist.available? => true
|
@@ -124,29 +139,40 @@ playlist = VideoInfo.new("http://www.youtube.com/playlist?p=PL9hW1uS6HUftLdHI6RI
|
|
124
139
|
# 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
140
|
```
|
126
141
|
|
127
|
-
|
128
|
-
-------
|
142
|
+
You can also use the `valid_url?` helper to check if a given url is valid in some of the _enabled_ providers:
|
129
143
|
|
130
|
-
```
|
144
|
+
```ruby
|
145
|
+
> VideoInfo.valid_url?('http://www.youtube.com/watch?v=AT_5xOGh6Ko')
|
146
|
+
=> true
|
147
|
+
> VideoInfo.valid_url?('http://vimeo.com/898029')
|
148
|
+
=> true
|
149
|
+
> VideoInfo.valid_url?('http://www.example.com/video/12345')
|
150
|
+
=> false
|
151
|
+
```
|
152
|
+
|
153
|
+
### Options
|
154
|
+
|
155
|
+
```ruby
|
131
156
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', 'User-Agent' => 'My YouTube Mashup Robot/1.0')
|
132
157
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', 'Referer' => 'http://my-youtube-mashup.com/')
|
133
158
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', 'Referer' => 'http://my-youtube-mashup.com/',
|
134
159
|
'User-Agent' => 'My YouTube Mashup Robot/1.0')
|
135
160
|
```
|
161
|
+
|
136
162
|
You can also use **symbols** instead of strings (any non-word (`/[^a-z]/i`) character would be converted to hyphen).
|
137
163
|
|
138
|
-
```
|
164
|
+
```ruby
|
139
165
|
video = VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4', referer: 'http://my-youtube-mashup.com/',
|
140
166
|
user_agent: 'My YouTube Mashup Robot/1.0')
|
141
167
|
```
|
142
168
|
|
143
169
|
User-Agent when empty defaults to "VideoInfo/VERSION" - where version is current VideoInfo version, e.g. **"VideoInfo/0.2.7"**.
|
144
170
|
|
145
|
-
It supports all
|
171
|
+
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
172
|
|
147
173
|
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
174
|
|
149
|
-
```
|
175
|
+
```ruby
|
150
176
|
VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4').embed_code(iframe_attributes: { width: 800, height: 600, 'data-key' => 'value' })
|
151
177
|
=> '<iframe src="//www.youtube.com/embed/mZqGqE0D0n4" frameborder="0" allowfullscreen="allowfullscreen" width="800" height="600" data-key="value"></iframe>'
|
152
178
|
|
@@ -156,29 +182,29 @@ VideoInfo.new('http://www.youtube.com/watch?v=mZqGqE0D0n4').embed_code(url_attri
|
|
156
182
|
|
157
183
|
If you would like to disable certain providers, you can do so by modifying the class variable `disable_providers`:
|
158
184
|
|
159
|
-
```
|
185
|
+
```ruby
|
160
186
|
VideoInfo.disable_providers = %w[YouTube] # disable YouTube
|
161
187
|
VideoInfo.disable_providers = %w[Vimeo YouTube] # disable Vimeo and Youtube
|
162
188
|
VideoInfo.disable_providers = [] # enable all providers
|
163
189
|
```
|
164
190
|
|
165
|
-
|
166
|
-
|
191
|
+
**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.
|
192
|
+
|
193
|
+
## Contributing
|
167
194
|
|
195
|
+
Please read [the contributing guidelines](CONTRIBUTING.md).
|
168
196
|
|
169
|
-
Author
|
170
|
-
------
|
197
|
+
### Author
|
171
198
|
|
172
199
|
[Thibaud Guillaume-Gentil](https://github.com/thibaudgg) ([@thibaudgg](https://twitter.com/thibaudgg))
|
173
200
|
|
174
|
-
Maintainers
|
175
|
-
-----------
|
201
|
+
### Maintainers
|
176
202
|
|
177
203
|
- [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)
|
204
|
+
- [Vincent Heuken](https://github.com/vheuken)
|
205
|
+
- [João Vieira](https://github.com/joaocv3)
|
206
|
+
- [Marc Anguera](https://github.com/markets)
|
180
207
|
|
181
|
-
Contributors
|
182
|
-
------------
|
208
|
+
### Contributors
|
183
209
|
|
184
|
-
[
|
210
|
+
Thanks to [all 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
|