yt 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -23
- data/{HISTORY.md → CHANGELOG.md} +142 -41
- data/Gemfile.lock +12 -10
- data/README.md +4 -1
- data/Rakefile +2 -14
- data/lib/yt/collections/content_owner_details.rb +36 -0
- data/lib/yt/models/channel.rb +15 -0
- data/lib/yt/models/content_owner_detail.rb +47 -0
- data/lib/yt/version.rb +1 -1
- data/spec/models/content_owner_detail_spec.rb +30 -0
- data/spec/requests/as_account/channel_spec.rb +5 -0
- data/spec/requests/as_content_owner/channel_spec.rb +14 -2
- data/spec/requests/as_content_owner/content_owner_spec.rb +0 -5
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db90684e975d4957dfb63d6ae4dd5a7c4b48749c
|
4
|
+
data.tar.gz: a49f7815ae7a37e73ac6e26cb9f12cee97a011d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 109d5c7feb5b3f1664b5f45a5618cbcbc75cda94cd44e7b0c7f86881ff9cbdf3959fffe2accdbcc1c6ae91bd5bf5f1173752c7a98a5eb5b83f85cfdafe6491fb
|
7
|
+
data.tar.gz: 49efcf9203a7f65e44aa28a498c860b6bde0afe64dbf648fcc9ab9d525dcfe968103238af05e70b855d6002523db3dc6a39683b49750c431ed394c534df160b8
|
data/.travis.yml
CHANGED
@@ -5,27 +5,5 @@ matrix:
|
|
5
5
|
include:
|
6
6
|
- rvm: 1.9.3
|
7
7
|
gemfile: gemfiles/Gemfile.activesupport-3.x
|
8
|
-
env:
|
9
|
-
- secure: OsmWyhhYNILEb1lhqxPX+iEfbWzC3dELuxQ7JGP9iN/FhqBtlV51cu+u2cBBdql6Gzuqi4VlMEeJSX0PQUmzOsMb0vHhOJDyp4a32NE+xry8LOT8XdCwni20ZBcUeFxC5hMUVebPuhqBTFjBWbXQKwKSXIdPnNWz31d9kyGIsxk=
|
10
8
|
- rvm: 2.0.0
|
11
|
-
gemfile: gemfiles/Gemfile.activesupport-4.x
|
12
|
-
env:
|
13
|
-
- secure: FrmFA2BE0FYyuKsf0FEO0EAXY+h048HbD1p3lu5XPo9/lxpAl7wM5m12HsnJQuNY6UlUmZ5bp9f8upCBZpz7cLZK5e/FWLWSvkv3Fts+NVsbAcVtFgvBKOCgTznZi/qgUtqbWBevkM3gyXyylzdB+c4wWjoOO/xSDVR227m8nMA=
|
14
|
-
env:
|
15
|
-
global:
|
16
|
-
- secure: ApPj5c9h6xk+AbHHf4KXL10QnleYCWwcp2+qMFolrS6RWR5vhrnKq1UBo0h59HuvXeOQIgZ/GmocuSEZovS9c1hQP3n0PHSNEnGUNJyn6CS3BiPQSWmC3p2pONo1Xv+hVWfzDoEv80b82GX5P5x/l1BSqhpxLA9geITJprWsoLg=
|
17
|
-
- secure: CkLyqIq/yTV5h/41b0wxIhMN0LvTk51IBht1+l678YSK7zT9emo9DcwnZVQ9f9KluDD8SyUGRORD40eQs8XmqpDCx7gj7i5e3TEVBofM9YnyFMR1lsWRiMr8jf2eksuP10kEkV7S7E1KH4LI2K1ZcOVqfN0G3Vs0C5D8GwpEcQ8=
|
18
|
-
- secure: XzuEz0AV6eDeT3+VaodXRMOh+fDvtG1X/VDfnh3f3gmVsnW1d8gdZY9Gw9rkSixK0SwL58BcSu+SU9BlDAsa0asv2XF8h51Q7s3x0ld9I60ssV/4DXSXqicHYcq13Vd86JMmURUuLiJM3y5lXb0bMGXNOkgYZ19gd5X9No+Tkww=
|
19
|
-
- secure: GvFLpteuIhPHtNT41VBR49sJf5yAWpwwGA24Ov92e5FaVzZD8eiBQZYwjx3Whyo5nkSN5nDzYeKvEdkHaE+sIhSjhoeSY6Q85YK9o/4hSSxjo71OepZXfawKH0xtpkbI+N1fMuUCZR0ustSCLx1snLLZtFRQR2YWU6qg+Yj48Ds=
|
20
|
-
- secure: d7yJZSz7Xk0LgJJSTbiK+yb12fdu9101wGXR56sSaRb5BoulBO12uKQgMYMa1kAh6imrNL4WzGOQQGC3SXDAEL6riHcuQJQOmM5zRJtZOrgitVe4cUm9Lv7jo4OyoJNd65EqpOaFPlI0Z3hp0xy3tOuTXemjie44ReKsCUp7z2Y=
|
21
|
-
- secure: Hpv62bpHo2zNHwB6VYNKxXLv12GHC0fiGUZ/uDv/4ncukifR9zEeucp104o3f4jqRpauy533kNw1JmucXI6Y+IEyHoEcqA99/i/HirS5WlB7vRH1ATX20Jj3kQ2JaFBIzidX9gNXvSNwpI2XK267eqfZUDFU8zp6aUPnJ6tgpq0=
|
22
|
-
- secure: Ejj8tsuwyrRVmCc/R9ubKWCHWhCGpe0Dy6fc1UuPCkcMZyXq9ZC02v2obWsTQQ7epEgsCYZAO4v/gWpuv1b1huGcWdfJzMW7RCoY87cEf9HnAK0lSwGx4+/pYkEMe8y5p149C3vAR8nqczvEavN1fUq/WwPUqp+JyDP7kwFTs2Y=
|
23
|
-
- secure: gE5kAT1R54hmS+W3YYGcUtlD8ZskvTctVR3sr+C5CUjVPdq6Ktx5Q/a6EJyAVVrhxpaCOuk3LG+VkzdQIVFUNRiDPcOulkond4HkSQDoy+IJ/wTXvUS+lIJ1ERUnWega+APrQUjH5s2WayPGZUBqWt/u8Tt9EmSUZfuKZSEXqZk=
|
24
|
-
- secure: ZUx5v/wHW/TENg8NfFINiiMoe2D031ntDTiuIBdf88c/bMClkEtRRgomtK9RBkFonEyGEOkXxUm2SLzRf340V3eIXWQhil7ab1lcYs8X59aVS/NK/GqChH8Nia17gc3OTQ9k6rYvj4Lp60Dh9WG1cijLPd4/OvPmf6qX9uYfJMw=
|
25
|
-
- secure: DumQVO01Y3Ki1skuOYOZzosDb6jS0XyG1O8Agy3mVxXGJzQE+s1z2UFz4gMpsU9o/gmiNMddp7I6+RtbZjo9hN3H7vlRRwEeB7tuUMiDyomSx1FlHcCFfPdTmhxGg8X78SErMWqNC6eReGrCTgBdIq1ho7dIu53qJNxTEFqx7eI=
|
26
|
-
- secure: UCceSRqPe5Y8WCM85qj0i8wlB5gJRSegJZfVj5jnwyermcOc1ZucwDZwTzkYVbLfDGTqTqzqW6M322a1tWm74xeIbxuHG7fw3Waoxk4zh3tg1CmNkzeDZFnl6V10uOMT6pn5E3kfhLzqOzftJN6fTMCgYMdkwJcfdrMX+z1cxwM=
|
27
|
-
- secure: QIOy4cACShEuU96BRBC4IdFFbi9Dr58wdFF25q3Tb1FXHQCxeOINF6tGuHsEBa04dNVLsZFCIbP+1mP2li8W40eSxg0PXd5r61mhR106dhBzN1ROX+EIP+mbecGCHgWIYVAtollSkCgHo9UBKUQOHavPnrvt1bTuV0eYvWiCZtc=
|
28
|
-
- secure: WICaR3cq/6SS4855tAJSZx0H/EkovfZZsxHY66y/lQ20p+DYJ0l6Jc6CRaZNvDPtj6Zp9Lu72CB2v6J2AO1WkrAvVBiMEj5zkPtVHwCcHxH0FasQCTFaLWy/zvcQeEIvidcBqABMsq1Pqv8p7UD8BRoQq22Vfe2LEjT/X2/eJwY=
|
29
|
-
- secure: E1ZoB5XyFxn3b9RVnXgt/JY+ikKLw57+CGcim0us8SdIwKctH8IWv0U7MggWATw2KtLgxEt1YU5MRFBxdO3nWY7XkvsYVCbLpmyFFzSDGZLNaaSLRZqon/N1lwias1pvOFL8cN2yLFXj6qMH67dBCyuQ1Q9LhejlWiGRBiLjfF8=
|
30
|
-
- secure: TnQ7HnvTM7pTwO0G7gYj+UjxxhPd0TOYAgHiafExrfr2nG+mkv1tc2OY/f1iB6kNp3+KEw+sNuyVZd1M9pFL93ARhla6FKqi/JoYFR0E2CxiVzAbLcabdtglqb8Jxw9a73YG7zFABZBWdTo5eR0TvpIK+rdTneUaEyCNU+Plh1E=
|
31
|
-
- secure: bZs3JaE02u3eS7hx7CXNZrUigSdYpbnKUdaHfNj7If0emfh15Tv6WaIszcKPVFUj1hMy6jeJcGJlAkYPA6iczLlmkD/1vzr75t1cNhXdCVq27uH3KWF6TN+/XsX1s4A29eIQTuHZ9q5qJyFyZVujqg1hvGjt0CSJYPxO+0muucE=
|
9
|
+
gemfile: gemfiles/Gemfile.activesupport-4.x
|
data/{HISTORY.md → CHANGELOG.md}
RENAMED
@@ -1,28 +1,137 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
*
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
*
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
For more information about changelogs, check
|
6
|
+
[Keep a Changelog](http://keepachangelog.com) and
|
7
|
+
[Vandamme](http://tech-angels.github.io/vandamme).
|
8
|
+
|
9
|
+
## 0.9.8 - 2014-08-11
|
10
|
+
|
11
|
+
* [FEATURE] Add `.content_owner` and `.linked_at` to channels managed by a CMS content owner
|
12
|
+
|
13
|
+
## 0.9.7 - 2014-08-02
|
14
|
+
|
15
|
+
* [BUGFIX] Correctly parse videos’ duration for videos longer than 24 hours
|
16
|
+
|
17
|
+
## 0.9.6 - 2014-08-02
|
18
|
+
|
19
|
+
* [ENHANCEMENT] Accept angle brackets characters in videos’ and playlists’ metadata
|
20
|
+
|
21
|
+
## 0.9.5 - 2014-08-02
|
22
|
+
|
23
|
+
* [FEATURE] Allow status attributes of a video to be updated
|
24
|
+
|
25
|
+
`video.update` now accepts three new attributes: `privacy_status`,
|
26
|
+
`public_stats_viewable` and `publish_at`.
|
27
|
+
|
28
|
+
## 0.9.4 - 2014-08-02
|
29
|
+
|
30
|
+
* [FEATURE] Expose metadata for live-streaming videos
|
31
|
+
|
32
|
+
New method are now available for `Video` instance to check their live-streaming
|
33
|
+
details: `actual_start_time`, `actual_end_time`, `scheduled_start_time`,
|
34
|
+
`scheduled_end_time` and `concurrent_viewers`.
|
35
|
+
|
36
|
+
## 0.9.3 - 2014-07-30
|
37
|
+
|
38
|
+
* [BUGFIX] Don’t cache `.where` conditions on multiple calls
|
39
|
+
|
40
|
+
For instance, invoking `account.videos.where(q: 'x').count` followed by
|
41
|
+
`account.videos.count` used to return the same result, because the `where`
|
42
|
+
conditions of the first request were wrongly kept for the successive request.
|
43
|
+
|
44
|
+
* [FEATURE] Check if a ContentID claim is third-party with `claim.third_party?`
|
45
|
+
* [ENHANCEMENT] `update` methods accept both underscore and camel-case attributes
|
46
|
+
|
47
|
+
For instance, either of the following syntaxes can now be used:
|
48
|
+
`video.update categoryId: "22"` or `video.update category_id: "22"`.
|
49
|
+
|
50
|
+
## 0.9.2 - 2014-07-29
|
51
|
+
|
52
|
+
* [FEATURE] List ContentID policies with `content_owner.policies`
|
53
|
+
|
54
|
+
## 0.9.1 - 2014-07-28
|
55
|
+
|
56
|
+
* [FEATURE] List ContentID references with `content_owner.references`
|
57
|
+
* [ENHANCEMENT] `playlist.update` accepts both `privacyStatus` and `privacy_status`
|
58
|
+
|
59
|
+
For instance, either of the following syntaxes can now be used:
|
60
|
+
`playlist.update privacyStatus: "unlisted"` or
|
61
|
+
`playlist.update privacy_status: "unlisted"`.
|
62
|
+
|
63
|
+
## 0.9.0 - 2014-07-28
|
64
|
+
|
65
|
+
**How to upgrade**
|
66
|
+
|
67
|
+
If your code never declares instances of `Yt::Rating`, or never calls the
|
68
|
+
`update` method on them, then you are good to go.
|
69
|
+
|
70
|
+
If it does, then *simply replace `update` with `set`*:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
rating = Yt::Rating.new
|
74
|
+
# old syntax
|
75
|
+
rating.update :like
|
76
|
+
# new syntax
|
77
|
+
rating.set :like
|
78
|
+
```
|
79
|
+
|
80
|
+
* [ENHANCEMENT] `rating.set` replaces `rating.update` to rate a video
|
81
|
+
|
82
|
+
## 0.8.5 - 2014-07-28
|
83
|
+
|
84
|
+
* [FEATURE] Delete a video with `video.delete`
|
85
|
+
|
86
|
+
## 0.8.4 - 2014-07-24
|
87
|
+
|
88
|
+
* [BUGFIX] Correctly parse annotations with timestamp written as `t='0'`
|
89
|
+
|
90
|
+
## 0.8.3 - 2014-07-24
|
91
|
+
|
92
|
+
* [FEATURE] List content owners managed by an account with `account.content_owners`
|
93
|
+
|
94
|
+
## 0.8.2 - 2014-07-23
|
95
|
+
|
96
|
+
* [FEATURE] List ContentID claims administered by a content owner with `content_owner.claims`
|
97
|
+
|
98
|
+
## 0.8.1 - 2014-07-22
|
99
|
+
|
100
|
+
* [FEATURE] Include all the video-related status information in `video.status`
|
101
|
+
|
102
|
+
New method are now available for `Video` instance to check their status
|
103
|
+
information: `public?`, `uploaded?`, `rejected?`, `failed?`, `processed?`,
|
104
|
+
`deleted?`, `uses_unsupported_codec?`, `has_failed_conversion?`, `empty?`,
|
105
|
+
`invalid?`, `too_small?`, `aborted?`, `claimed?`, `infringes_copyright?`,
|
106
|
+
`duplicate?`, `inappropriate?`, `too_long?`, `belongs_to_closed_account?`,
|
107
|
+
`infringes_trademark?`, `violates_terms_of_use?`, `has_public_stats_viewable?`,
|
108
|
+
`belongs_to_suspended_account?`, `scheduled?`, `scheduled_at`, `embeddable?`
|
109
|
+
`licensed_as_creative_commons?` and `licensed_as_standard_youtube?`.
|
110
|
+
|
111
|
+
## 0.8.0 - 2014-07-19
|
112
|
+
|
113
|
+
**How to upgrade**
|
114
|
+
|
115
|
+
If your code never declares instances of `Yt::Channel`, or never calls the
|
116
|
+
`subscribe` method on them, then you are good to go.
|
117
|
+
|
118
|
+
If it does, then be aware that `subscribe` will not raise an error anymore if
|
119
|
+
a YouTube user tries to subscribe to her/his own YouTube channel. Instead,
|
120
|
+
`subscribe` will simply return `nil`. If this is acceptable, then you are good
|
121
|
+
to go. If you want the old behavior, replace `subscribe` with `subscribe!`:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
account = Yt::Account.new access_token: 'ya29...'
|
125
|
+
channel = account.channel
|
126
|
+
# old behavior
|
127
|
+
channel.subscribe # => raise error
|
128
|
+
# new behavior
|
129
|
+
channel.subscribe # => nil
|
130
|
+
channel.subscribe! # => raise error
|
131
|
+
```
|
132
|
+
* [ENHANCEMENT] `channel.subscribe` does not raise error when trying to subscribe to one’s own channel
|
133
|
+
|
134
|
+
## 0.7 - 2014/06/18
|
26
135
|
|
27
136
|
* [breaking change] Rename DetailsSet to ContentDetail
|
28
137
|
* Add statistics_set to Video (views, likes, dislikes, favorites, comments)
|
@@ -41,8 +150,7 @@ v0.7 - 2014/06/18
|
|
41
150
|
* Make channel.videos access more than 500 videos per channel
|
42
151
|
* Add viewer percentage (age group, gender) to Channel and Video reports
|
43
152
|
|
44
|
-
|
45
|
-
-----------------
|
153
|
+
## 0.6 - 2014/06/05
|
46
154
|
|
47
155
|
* [breaking change] Rename Channel#earning to Channel#earnings_on
|
48
156
|
* [breaking change] Account#videos shows *all* videos owned by account (public and private)
|
@@ -52,8 +160,7 @@ v0.6 - 2014/06/05
|
|
52
160
|
* Handle annotations with "never" as the timestamp, without text, singleton positions, of private videos
|
53
161
|
* New methods for Video: hd?, stereoscopic?, captioned?, licensed?
|
54
162
|
|
55
|
-
|
56
|
-
-----------------
|
163
|
+
## 0.5 - 2014/05/16
|
57
164
|
|
58
165
|
* More complete custom exception Yt::Error, with code, body and curl
|
59
166
|
* Replace `:ignore_not_found` and `:ignore_duplicates` with `:ignore_errors`
|
@@ -76,8 +183,7 @@ v0.5 - 2014/05/16
|
|
76
183
|
* Wait 3 seconds and retry *every* request that returns 500, 503 or 400 with "Invalid query"
|
77
184
|
* New Views collection to retrieve view count for YouTube-partnered channels
|
78
185
|
|
79
|
-
|
80
|
-
--------------------
|
186
|
+
## 0.4 - 2014/05/09
|
81
187
|
|
82
188
|
* Complete rewrite, using ActiveSupport and separating models and collections
|
83
189
|
* New methods to handle annotations, details sets
|
@@ -88,33 +194,28 @@ v0.4 - 2014/05/09
|
|
88
194
|
* Allow to configure Yt credentials through environment variables
|
89
195
|
* When updating a playlist, only changes the specified attributes
|
90
196
|
|
91
|
-
|
92
|
-
--------------------
|
197
|
+
## 0.3.0 - 2014/04/16
|
93
198
|
|
94
199
|
* New and improved methods to handle subscriptions, playlists, playlist items
|
95
200
|
* `find_or_create_playlist_by` does not yield a block anymore
|
96
201
|
* `account.subscribe_to!` raises error in case of duplicate subscription, but `account.subscribe_to` does not
|
97
202
|
|
98
|
-
|
99
|
-
--------------------
|
203
|
+
## 0.2.1 - 2014/04/10
|
100
204
|
|
101
205
|
* `account.subscribe_to!` does not raise error in case of duplicate subscription
|
102
206
|
* Accountable objects can be initialized with the OAuth access token if there's no need to get a fresh one with a refresh token
|
103
207
|
|
104
|
-
|
105
|
-
--------------------
|
208
|
+
## 0.2.0 - 2014/04/09
|
106
209
|
|
107
210
|
* Replaced `account.perform!` with `account.like!`, `account.subscribe_to!`
|
108
211
|
* Added `account.add_to!` to add a video to an account’s playlist
|
109
212
|
* Added `account.find_or_create_playlist_by` to find or create an account’s playlist
|
110
213
|
|
111
|
-
|
112
|
-
--------------------
|
214
|
+
## 0.1.1 - 2014/04/09
|
113
215
|
|
114
216
|
* Added support for Ruby 2.0.0
|
115
217
|
|
116
|
-
|
117
|
-
--------------------
|
218
|
+
## 0.1.0 - 2014/04/08
|
118
219
|
|
119
220
|
* Support for authenticated resources: Youtube accounts and Google accounts
|
120
221
|
* Support for public Youtube resources: channels and videos
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
yt (0.9.
|
4
|
+
yt (0.9.8)
|
5
5
|
activesupport
|
6
6
|
|
7
7
|
GEM
|
@@ -21,27 +21,29 @@ GEM
|
|
21
21
|
thor
|
22
22
|
diff-lcs (1.2.5)
|
23
23
|
docile (1.1.5)
|
24
|
-
i18n (0.6.
|
24
|
+
i18n (0.6.11)
|
25
25
|
json (1.8.1)
|
26
26
|
mime-types (2.3)
|
27
|
-
minitest (5.
|
27
|
+
minitest (5.4.0)
|
28
28
|
multi_json (1.10.1)
|
29
|
+
netrc (0.7.7)
|
29
30
|
rake (10.3.2)
|
30
|
-
rest-client (1.
|
31
|
-
mime-types (>= 1.16)
|
31
|
+
rest-client (1.7.2)
|
32
|
+
mime-types (>= 1.16, < 3.0)
|
33
|
+
netrc (~> 0.7)
|
32
34
|
rspec (3.0.0)
|
33
35
|
rspec-core (~> 3.0.0)
|
34
36
|
rspec-expectations (~> 3.0.0)
|
35
37
|
rspec-mocks (~> 3.0.0)
|
36
|
-
rspec-core (3.0.
|
38
|
+
rspec-core (3.0.3)
|
37
39
|
rspec-support (~> 3.0.0)
|
38
|
-
rspec-expectations (3.0.
|
40
|
+
rspec-expectations (3.0.3)
|
39
41
|
diff-lcs (>= 1.2.0, < 2.0)
|
40
42
|
rspec-support (~> 3.0.0)
|
41
|
-
rspec-mocks (3.0.
|
43
|
+
rspec-mocks (3.0.3)
|
42
44
|
rspec-support (~> 3.0.0)
|
43
|
-
rspec-support (3.0.
|
44
|
-
simplecov (0.
|
45
|
+
rspec-support (3.0.3)
|
46
|
+
simplecov (0.9.0)
|
45
47
|
docile (~> 1.1.0)
|
46
48
|
multi_json
|
47
49
|
simplecov-html (~> 0.8.0)
|
data/README.md
CHANGED
@@ -41,7 +41,7 @@ To install on your system, run
|
|
41
41
|
|
42
42
|
To use inside a bundled Ruby project, add this line to the Gemfile:
|
43
43
|
|
44
|
-
gem 'yt', '~> 0.9.
|
44
|
+
gem 'yt', '~> 0.9.8'
|
45
45
|
|
46
46
|
Since the gem follows [Semantic Versioning](http://semver.org),
|
47
47
|
indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
|
@@ -194,6 +194,9 @@ channel.impressions_on 5.days.ago #=> 157.0
|
|
194
194
|
|
195
195
|
channel.viewer_percentages #=> {female: {'18-24' => 12.12, '25-34' => 16.16,…}…}
|
196
196
|
channel.viewer_percentage(gender: :female) #=> 49.12
|
197
|
+
|
198
|
+
channel.content_owner #=> 'FullScreen'
|
199
|
+
channel.linked_at #=> Wed, 28 May 2014
|
197
200
|
```
|
198
201
|
|
199
202
|
*The methods above require to be authenticated as the channel’s content owner (see below).*
|
data/Rakefile
CHANGED
@@ -5,19 +5,7 @@ Bundler::GemHelper.install_tasks
|
|
5
5
|
require "rspec/core/rake_task"
|
6
6
|
require "rspec/core/version"
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# @note: During the last 48 hours, YouTube API has being responding with
|
12
|
-
# unexpected and undocumented errors to the content-owner endpoints.
|
13
|
-
# Since some pull requests are waiting for tests to pass on Travis CI and
|
14
|
-
# do not touch the content-owner component at all, those tests are
|
15
|
-
# temporarily skipped to allow those PRs to be accepted. This will cause
|
16
|
-
# code coverage to go down, but it's a temporary fix waiting for YouTube
|
17
|
-
# API to work again.
|
18
|
-
desc "Run all examples except ones with access to Content Owner"
|
19
|
-
RSpec::Core::RakeTask.new(:spec) do |t|
|
20
|
-
t.rspec_opts = '--tag ~partner --tag ~device_app'
|
21
|
-
end
|
8
|
+
desc "Run all examples"
|
9
|
+
RSpec::Core::RakeTask.new :spec
|
22
10
|
|
23
11
|
task default: [:spec]
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'yt/collections/base'
|
2
|
+
require 'yt/models/content_owner_detail'
|
3
|
+
|
4
|
+
module Yt
|
5
|
+
module Collections
|
6
|
+
class ContentOwnerDetails < Base
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
# @return [Yt::Models::ContentOwnerDetail] a new content detail
|
11
|
+
# initialized with one of the items returned by asking YouTube for a
|
12
|
+
# list of them.
|
13
|
+
def new_item(data)
|
14
|
+
Yt::ContentOwnerDetail.new data: data['contentOwnerDetails']
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Hash] the parameters to submit to YouTube to get the
|
18
|
+
# content owner detail of a channel.
|
19
|
+
# @see https://developers.google.com/youtube/v3/docs/channels#contentOwnerDetails
|
20
|
+
def list_params
|
21
|
+
super.tap do |params|
|
22
|
+
params[:params] = content_owner_details_params
|
23
|
+
params[:path] = '/youtube/v3/channels'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def content_owner_details_params
|
28
|
+
@parent.content_owner_details_params.tap do |params|
|
29
|
+
params[:max_results] = 50
|
30
|
+
params[:part] = 'contentOwnerDetails'
|
31
|
+
params[:id] = @parent.id
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/yt/models/channel.rb
CHANGED
@@ -47,6 +47,12 @@ module Yt
|
|
47
47
|
delegate :view_count, :comment_count, :video_count, :subscriber_count,
|
48
48
|
:subscriber_count_visible?, to: :statistics_set
|
49
49
|
|
50
|
+
# @!attribute [r] content_owner_detail
|
51
|
+
# @return [Yt::Models::ContentOwnerDetail] the video’s content owner
|
52
|
+
# details.
|
53
|
+
has_one :content_owner_detail
|
54
|
+
delegate :content_owner, :linked_at, to: :content_owner_detail
|
55
|
+
|
50
56
|
# Returns whether the authenticated account is subscribed to the channel.
|
51
57
|
#
|
52
58
|
# This method requires {Resource#auth auth} to return an
|
@@ -135,6 +141,15 @@ module Yt
|
|
135
141
|
end
|
136
142
|
end
|
137
143
|
end
|
144
|
+
|
145
|
+
# @private
|
146
|
+
# Tells `has_one :content_owner_detail` to retrieve the content owner
|
147
|
+
# detail as the Content Owner, it the channel was authorized with one.
|
148
|
+
# If it was not, the call will fail, since YouTube only allows content
|
149
|
+
# owners to check who is the content owner of a channel.
|
150
|
+
def content_owner_details_params
|
151
|
+
{on_behalf_of_content_owner: auth.owner_name || auth.id}
|
152
|
+
end
|
138
153
|
end
|
139
154
|
end
|
140
155
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'yt/models/base'
|
2
|
+
|
3
|
+
module Yt
|
4
|
+
module Models
|
5
|
+
# Encapsulates channel data that is relevant for YouTube Partners linked
|
6
|
+
# with the channel.
|
7
|
+
# @see https://developers.google.com/youtube/v3/docs/channels#contentOwnerDetails
|
8
|
+
class ContentOwnerDetail < Base
|
9
|
+
def initialize(options = {})
|
10
|
+
@data = options[:data] || {}
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the name of the content owner linked to the channel.
|
14
|
+
#
|
15
|
+
# This method requires {Resource#auth auth} to return an authenticated
|
16
|
+
# instance of {Yt::ContentOwner} that can administer the channel.
|
17
|
+
# @return [String] if the channel is partnered with a content owner,
|
18
|
+
# the name of the content owner linked to the channel.
|
19
|
+
# @return [nil] if the channel is not partnered with a content owner.
|
20
|
+
# @return [nil] if {Resource#auth auth} is a content owner without
|
21
|
+
# permissions to administer the channel.
|
22
|
+
# @raise [Yt::Errors::Forbidden] if {Resource#auth auth} does not
|
23
|
+
# return an authenticated content owner.
|
24
|
+
def content_owner
|
25
|
+
@content_owner ||= @data['contentOwner']
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the date and time of when the channel was linked to the content
|
29
|
+
# owner.
|
30
|
+
#
|
31
|
+
# This method requires {Resource#auth auth} to return an authenticated
|
32
|
+
# instance of {Yt::ContentOwner} that can administer the channel.
|
33
|
+
# @return [Time] if the channel is partnered with a content owner,
|
34
|
+
# the date and time when the channel was linked with the content owner.
|
35
|
+
# @return [nil] if the channel is not partnered with a content owner.
|
36
|
+
# @return [nil] if {Resource#auth auth} is a content owner without
|
37
|
+
# permissions to administer the channel.
|
38
|
+
# @raise [Yt::Errors::Forbidden] if {Resource#auth auth} does not
|
39
|
+
# return an authenticated content owner.
|
40
|
+
def linked_at
|
41
|
+
@linked_at ||= if @data['timeLinked']
|
42
|
+
Time.parse @data['timeLinked']
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/yt/version.rb
CHANGED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yt/models/content_owner_detail'
|
3
|
+
|
4
|
+
describe Yt::ContentOwnerDetail do
|
5
|
+
subject(:content_owner_detail) { Yt::ContentOwnerDetail.new data: data }
|
6
|
+
|
7
|
+
describe '#content_owner' do
|
8
|
+
context 'given a content_owner_detail with a content owner' do
|
9
|
+
let(:data) { {"contentOwner"=>"FullScreen"} }
|
10
|
+
it { expect(content_owner_detail.content_owner).to eq 'FullScreen' }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'given a content_owner_detail without a content owner' do
|
14
|
+
let(:data) { {} }
|
15
|
+
it { expect(content_owner_detail.content_owner).to be_nil }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#linked_at' do
|
20
|
+
context 'given a content_owner_detail with a timeLinked' do
|
21
|
+
let(:data) { {"timeLinked"=>"2014-04-22T19:14:49.000Z"} }
|
22
|
+
it { expect(content_owner_detail.linked_at.year).to be 2014 }
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'given a content_owner_detail with a timeLinked' do
|
26
|
+
let(:data) { {} }
|
27
|
+
it { expect(content_owner_detail.linked_at).to be_nil }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -105,6 +105,11 @@ describe Yt::Channel, :device_app do
|
|
105
105
|
expect{channel.viewer_percentages}.not_to raise_error
|
106
106
|
expect{channel.viewer_percentage}.not_to raise_error
|
107
107
|
end
|
108
|
+
|
109
|
+
it 'cannot give information about its content owner' do
|
110
|
+
expect{channel.content_owner}.to raise_error Yt::Errors::Forbidden
|
111
|
+
expect{channel.linked_at}.to raise_error Yt::Errors::Forbidden
|
112
|
+
end
|
108
113
|
end
|
109
114
|
|
110
115
|
context 'given an unknown channel' do
|
@@ -263,13 +263,25 @@ describe Yt::Channel, :partner do
|
|
263
263
|
expect(channel.viewer_percentage(gender: :male)).to be_a Float
|
264
264
|
expect(channel.viewer_percentage(gender: :female)).to be_a Float
|
265
265
|
end
|
266
|
+
|
267
|
+
specify 'information about its content owner can be retrieved' do
|
268
|
+
expect(channel.content_owner).to be_a String
|
269
|
+
expect(channel.linked_at).to be_a Time
|
270
|
+
end
|
266
271
|
end
|
267
272
|
|
268
273
|
context 'not managed by the authenticated Content Owner' do
|
269
274
|
let(:id) { 'UCBR8-60-B28hp2BmDPdntcQ' }
|
270
275
|
|
271
|
-
|
272
|
-
|
276
|
+
specify 'earnings and impressions cannot be retrieved' do
|
277
|
+
expect{channel.earnings}.to raise_error Yt::Errors::Forbidden
|
278
|
+
expect{channel.views}.to raise_error Yt::Errors::Forbidden
|
279
|
+
end
|
280
|
+
|
281
|
+
specify 'information about its content owner cannot be retrieved' do
|
282
|
+
expect(channel.content_owner).to be_nil
|
283
|
+
expect(channel.linked_at).to be_nil
|
284
|
+
end
|
273
285
|
end
|
274
286
|
end
|
275
287
|
end
|
@@ -58,11 +58,6 @@ describe Yt::ContentOwner, :partner do
|
|
58
58
|
let(:video_id) { ENV['YT_TEST_PARTNER_VIDEO_ID'] }
|
59
59
|
it { expect(count).to be > 0 }
|
60
60
|
end
|
61
|
-
|
62
|
-
context 'given an unknown video ID' do
|
63
|
-
let(:video_id) { '--not-a-matching-video-id--' }
|
64
|
-
it { expect(count).to be_zero }
|
65
|
-
end
|
66
61
|
end
|
67
62
|
|
68
63
|
describe '.where(q: query)' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claudio Baccigalupo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-08-
|
11
|
+
date: 2014-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -106,9 +106,9 @@ files:
|
|
106
106
|
- ".rspec"
|
107
107
|
- ".travis.yml"
|
108
108
|
- ".yardopts"
|
109
|
+
- CHANGELOG.md
|
109
110
|
- Gemfile
|
110
111
|
- Gemfile.lock
|
111
|
-
- HISTORY.md
|
112
112
|
- MIT-LICENSE
|
113
113
|
- README.md
|
114
114
|
- Rakefile
|
@@ -134,6 +134,7 @@ files:
|
|
134
134
|
- lib/yt/collections/channels.rb
|
135
135
|
- lib/yt/collections/claims.rb
|
136
136
|
- lib/yt/collections/content_details.rb
|
137
|
+
- lib/yt/collections/content_owner_details.rb
|
137
138
|
- lib/yt/collections/content_owners.rb
|
138
139
|
- lib/yt/collections/device_flows.rb
|
139
140
|
- lib/yt/collections/ids.rb
|
@@ -170,6 +171,7 @@ files:
|
|
170
171
|
- lib/yt/models/configuration.rb
|
171
172
|
- lib/yt/models/content_detail.rb
|
172
173
|
- lib/yt/models/content_owner.rb
|
174
|
+
- lib/yt/models/content_owner_detail.rb
|
173
175
|
- lib/yt/models/description.rb
|
174
176
|
- lib/yt/models/device_flow.rb
|
175
177
|
- lib/yt/models/id.rb
|
@@ -209,6 +211,7 @@ files:
|
|
209
211
|
- spec/models/claim_spec.rb
|
210
212
|
- spec/models/configuration_spec.rb
|
211
213
|
- spec/models/content_detail_spec.rb
|
214
|
+
- spec/models/content_owner_detail_spec.rb
|
212
215
|
- spec/models/description_spec.rb
|
213
216
|
- spec/models/live_streaming_detail_spec.rb
|
214
217
|
- spec/models/playlist_item_spec.rb
|
@@ -291,6 +294,7 @@ test_files:
|
|
291
294
|
- spec/models/claim_spec.rb
|
292
295
|
- spec/models/configuration_spec.rb
|
293
296
|
- spec/models/content_detail_spec.rb
|
297
|
+
- spec/models/content_owner_detail_spec.rb
|
294
298
|
- spec/models/description_spec.rb
|
295
299
|
- spec/models/live_streaming_detail_spec.rb
|
296
300
|
- spec/models/playlist_item_spec.rb
|