yt 0.5.6 → 0.5.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -1
- data/Gemfile.lock +1 -1
- data/HISTORY.md +1 -0
- data/README.md +57 -10
- data/lib/yt/actions/list.rb +6 -2
- data/lib/yt/associations/earnings.rb +52 -0
- data/lib/yt/associations.rb +1 -0
- data/lib/yt/collections/earnings.rb +38 -0
- data/lib/yt/models/account.rb +3 -1
- data/lib/yt/models/channel.rb +1 -0
- data/lib/yt/version.rb +1 -1
- data/spec/associations/device_auth/earnings_spec.rb +43 -0
- data/spec/support/global_hooks.rb +14 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c6e034f7f20ce13ac90b4156e7e6845ef96730a
|
4
|
+
data.tar.gz: 95f4e7115e31707a6fbf64ea7d671f6c9dd34b19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 363c34358726c126c90b7fab58747d3df03a1fc0f1711e524d28cc35c954859865fbbde3a0e9207a6f6d49f2cc1235cb12ec5dc62632cc29699df0b4908fd271
|
7
|
+
data.tar.gz: 5d2436157647425de284a1fbb918f12c9e7f6f510b9c0dab9a8e97b2193468994cb4a53e2f8ffcdd3052c2d520e75cb3bed15e0aa57bd2c139383090158c96be
|
data/.travis.yml
CHANGED
@@ -15,4 +15,9 @@ env:
|
|
15
15
|
global:
|
16
16
|
- secure: ApPj5c9h6xk+AbHHf4KXL10QnleYCWwcp2+qMFolrS6RWR5vhrnKq1UBo0h59HuvXeOQIgZ/GmocuSEZovS9c1hQP3n0PHSNEnGUNJyn6CS3BiPQSWmC3p2pONo1Xv+hVWfzDoEv80b82GX5P5x/l1BSqhpxLA9geITJprWsoLg=
|
17
17
|
- secure: CkLyqIq/yTV5h/41b0wxIhMN0LvTk51IBht1+l678YSK7zT9emo9DcwnZVQ9f9KluDD8SyUGRORD40eQs8XmqpDCx7gj7i5e3TEVBofM9YnyFMR1lsWRiMr8jf2eksuP10kEkV7S7E1KH4LI2K1ZcOVqfN0G3Vs0C5D8GwpEcQ8=
|
18
|
-
- secure: XzuEz0AV6eDeT3+VaodXRMOh+fDvtG1X/VDfnh3f3gmVsnW1d8gdZY9Gw9rkSixK0SwL58BcSu+SU9BlDAsa0asv2XF8h51Q7s3x0ld9I60ssV/4DXSXqicHYcq13Vd86JMmURUuLiJM3y5lXb0bMGXNOkgYZ19gd5X9No+Tkww=
|
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=
|
data/Gemfile.lock
CHANGED
data/HISTORY.md
CHANGED
@@ -11,6 +11,7 @@ v0.5 - 2014/05/16
|
|
11
11
|
* New Authentication model to separate `access_token` and `refresh_token` from Account
|
12
12
|
* New types of Errors that render more verbose errors and the failing request in cURL syntax
|
13
13
|
* Separate Error class for 500 error, so they can be easily found in app logs
|
14
|
+
* New Earning collection to retrieve estimated earning for YouTube-partnered channels
|
14
15
|
|
15
16
|
v0.4 - 2014/05/09
|
16
17
|
--------------------
|
data/README.md
CHANGED
@@ -41,9 +41,9 @@ Use [Yt::Account](http://rubydoc.info/github/Fullscreen/yt/master/Yt/Account) to
|
|
41
41
|
* access the YouTube channel of the account
|
42
42
|
|
43
43
|
```ruby
|
44
|
-
account
|
44
|
+
# An account can be initialized with access token, refresh token or an authorization code
|
45
|
+
account = Yt::Account.new access_token: 'ya29.1.ABCDEFGHIJ'
|
45
46
|
|
46
|
-
# An OAuth2 prompt will appear before the following commands
|
47
47
|
account.email #=> .. your e-mail address..
|
48
48
|
account.channel #=> #<Yt::Channel @id=...>
|
49
49
|
```
|
@@ -60,6 +60,7 @@ Use [Yt::Channel](http://rubydoc.info/github/Fullscreen/yt/master/Yt/Channel) to
|
|
60
60
|
* access the playlists of a channel
|
61
61
|
* subscribe to and unsubscribe from a channel
|
62
62
|
* create and delete playlists from a channel
|
63
|
+
* retrieve the estimated daily earnings of a channel
|
63
64
|
|
64
65
|
```ruby
|
65
66
|
channel = Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow'
|
@@ -71,8 +72,14 @@ channel.videos.first #=> #<Yt::Video @id=...>
|
|
71
72
|
|
72
73
|
channel.playlists.count #=> 2
|
73
74
|
channel.playlists.first #=> #<Yt::Playlist @id=...>
|
75
|
+
```
|
76
|
+
|
77
|
+
*The methods above do not require authentication.*
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
account = Yt::Account.new access_token: 'ya29.1.ABCDEFGHIJ'
|
81
|
+
channel = Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow', auth: account
|
74
82
|
|
75
|
-
# An OAuth2 prompt will appear before the following commands
|
76
83
|
channel.subscribed? #=> false
|
77
84
|
channel.subscribe #=> true
|
78
85
|
|
@@ -81,7 +88,18 @@ channel.delete_playlists title: 'New playlist' #=> [true]
|
|
81
88
|
|
82
89
|
```
|
83
90
|
|
84
|
-
*
|
91
|
+
*The methods above require to be authenticated as a YouTube account (see below).*
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
content_owner = Yt::Account.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'
|
95
|
+
channel = Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow', auth: content_owner
|
96
|
+
|
97
|
+
channel.earning 5.days.ago #=> 12.23
|
98
|
+
channel.earnings since: 3.days.ago, until: 2.days.ago #=> {Wed, 28 May 2014 => 1.34, Thu, 29 May 2014 => 0.47}
|
99
|
+
```
|
100
|
+
|
101
|
+
*The methods above require to be authenticated as the channel’s content owner (see below).*
|
102
|
+
|
85
103
|
|
86
104
|
Yt::Video
|
87
105
|
-----------
|
@@ -100,13 +118,19 @@ video.description.has_link_to_subscribe? #=> false
|
|
100
118
|
|
101
119
|
video.annotations.count #=> 1
|
102
120
|
video.annotations.first #=> #<Yt::Annotation @id=...>
|
121
|
+
```
|
122
|
+
|
123
|
+
*The methods above do not require authentication.*
|
124
|
+
|
125
|
+
```ruby
|
126
|
+
account = Yt::Account.new access_token: 'ya29.1.ABCDEFGHIJ'
|
127
|
+
video = Yt::Video.new id: 'MESycYJytkU', auth: account
|
103
128
|
|
104
|
-
# An OAuth2 prompt will appear before the following commands
|
105
129
|
video.liked? #=> false
|
106
130
|
video.like #=> true
|
107
131
|
```
|
108
132
|
|
109
|
-
*
|
133
|
+
*The methods above require to be authenticated as a YouTube account (see below).*
|
110
134
|
|
111
135
|
Yt::Playlist
|
112
136
|
------------
|
@@ -127,14 +151,17 @@ playlist.playlist_items.count #=> 1
|
|
127
151
|
playlist.playlist_items.first #=> #<Yt::PlaylistItem @id=...>
|
128
152
|
playlist.playlist_items.first.position #=> 0
|
129
153
|
playlist.playlist_items.first.video.title #=> "Fullscreen Creator Platform"
|
154
|
+
```
|
155
|
+
|
156
|
+
*The methods above do not require authentication.*
|
130
157
|
|
131
|
-
|
158
|
+
```ruby
|
132
159
|
playlist.add_video 'MESycYJytkU'
|
133
160
|
playlist.add_videos ['MESycYJytkU', 'MESycYJytkU']
|
134
161
|
playlist.delete_playlist_items title: 'Fullscreen Creator Platform' #=> [true]
|
135
162
|
```
|
136
163
|
|
137
|
-
*
|
164
|
+
*The methods above require to be authenticated as the playlist’s owner (see below).*
|
138
165
|
|
139
166
|
|
140
167
|
Yt::Annotation
|
@@ -219,8 +246,28 @@ account.email #=> (retrieves the account’s e-mail address)
|
|
219
246
|
account.playlists.first.add_video 'MESycYJytkU' #=> (adds a video to an account’s playlist)
|
220
247
|
```
|
221
248
|
|
222
|
-
Scenario 3. If you don’t have
|
249
|
+
Scenario 3. If you don’t have any account’s token, then you can get one by
|
250
|
+
having the user authorize your app through the Google OAuth page. First,
|
251
|
+
build the the Google OAuth page URL with the following code:
|
223
252
|
|
253
|
+
```ruby
|
254
|
+
Yt::Account.new(scopes: scopes, redirect_uri: redirect_uri).authentication_url
|
255
|
+
```
|
256
|
+
|
257
|
+
where `scopes` is the list of scopes you want the user to authorize, and
|
258
|
+
`redirect_uri` is the page of your web app the user should come back after
|
259
|
+
authorizing (remember, this must be added to the Google Console as well).
|
260
|
+
Sample scopes are: `youtube`, `youtube.readonly` `userinfo.email`.
|
261
|
+
|
262
|
+
After authorizing your app, the user will be redirected to `redirect_uri`
|
263
|
+
with an extra `code` parameter that looks something like `4/Ja60jJ7_Kw0`.
|
264
|
+
Just pass the code to the following method to authenticate and initialize the account:
|
265
|
+
|
266
|
+
```ruby
|
267
|
+
account = Yt::Account.new authorization_code: '4/Ja60jJ7_Kw0'
|
268
|
+
account.email #=> (retrieves the account’s e-mail address)
|
269
|
+
account.playlists.first.add_video 'MESycYJytkU' #=> (adds a video to an account’s playlist)
|
270
|
+
```
|
224
271
|
|
225
272
|
Device apps that do require user interactions
|
226
273
|
---------------------------------------------
|
@@ -300,7 +347,7 @@ To install on your system, run
|
|
300
347
|
|
301
348
|
To use inside a bundled Ruby project, add this line to the Gemfile:
|
302
349
|
|
303
|
-
gem 'yt', '~> 0.5.
|
350
|
+
gem 'yt', '~> 0.5.7'
|
304
351
|
|
305
352
|
Since the gem follows [Semantic Versioning](http://semver.org),
|
306
353
|
indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
|
data/lib/yt/actions/list.rb
CHANGED
@@ -4,7 +4,7 @@ require 'yt/errors/no_items'
|
|
4
4
|
module Yt
|
5
5
|
module Actions
|
6
6
|
module List
|
7
|
-
delegate :count, :first, :any?, :each, :map, :find, to: :list
|
7
|
+
delegate :count, :first, :any?, :each, :map, :flat_map, :find, to: :list
|
8
8
|
alias size count
|
9
9
|
|
10
10
|
def first!
|
@@ -51,7 +51,7 @@ module Yt
|
|
51
51
|
request = Yt::Request.new params
|
52
52
|
response = request.run
|
53
53
|
token = response.body['nextPageToken']
|
54
|
-
items = response.body.fetch
|
54
|
+
items = response.body.fetch items_key, []
|
55
55
|
{items: items, token: token}
|
56
56
|
end
|
57
57
|
|
@@ -65,6 +65,10 @@ module Yt
|
|
65
65
|
params[:exptected_response] = Net::HTTPOK
|
66
66
|
end
|
67
67
|
end
|
68
|
+
|
69
|
+
def items_key
|
70
|
+
'items'
|
71
|
+
end
|
68
72
|
end
|
69
73
|
end
|
70
74
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'yt/collections/earnings'
|
2
|
+
|
3
|
+
module Yt
|
4
|
+
module Associations
|
5
|
+
# Provides the `has_many :earnings` method to YouTube resources, which
|
6
|
+
# allows to invoke earning-related methods, such as .earnings.
|
7
|
+
# YouTube resources with earning are: channels.
|
8
|
+
module Earnings
|
9
|
+
# Return the estimated earning for one specific day.
|
10
|
+
#
|
11
|
+
# @param [Date or Time or DateTime or String] date The date to obtain
|
12
|
+
# the estimated earnings for. If String, must be Date-parseable.
|
13
|
+
#
|
14
|
+
# @return [Float] The estimated earnings in USD.
|
15
|
+
def earning(date)
|
16
|
+
earnings(from: date, to: date).values.first
|
17
|
+
end
|
18
|
+
|
19
|
+
# Return the estimated earning for a range of days.
|
20
|
+
#
|
21
|
+
# @param [Hash] options the range of days to get the earnings for.
|
22
|
+
# @option options [Date or Time or DateTime or String] :since The start
|
23
|
+
# of the days range. If String, must be Date-parseable.
|
24
|
+
# @note options[:since] is aliased as options[:from]
|
25
|
+
# @option options [Date or Time or DateTime or String] :until The end
|
26
|
+
# of the days range. If String, must be Date-parseable.
|
27
|
+
# @note options[:until] is aliased as options[:to]
|
28
|
+
#
|
29
|
+
# @return [Hash] The estimated earnings by day. Each :key is a Date
|
30
|
+
# and each :value is a Float, representing estimated earnings in USD.
|
31
|
+
def earnings(options = {})
|
32
|
+
from = options[:since] || options[:from] || 1.week.ago
|
33
|
+
to = options[:until] || options[:to] || 1.day.ago
|
34
|
+
range = Range.new *[from, to].map(&:to_date)
|
35
|
+
|
36
|
+
Hash[*range.flat_map do |date|
|
37
|
+
[date, (@earnings ||= {})[date] ||= range_earnings(range)[date]]
|
38
|
+
end]
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def range_earnings(date_range)
|
44
|
+
(@range_earnings ||= {})[date_range] ||= all_earnings.within date_range
|
45
|
+
end
|
46
|
+
|
47
|
+
def all_earnings
|
48
|
+
Collections::Earnings.of self
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/yt/associations.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'yt/collections/base'
|
2
|
+
|
3
|
+
module Yt
|
4
|
+
module Collections
|
5
|
+
class Earnings < Base
|
6
|
+
|
7
|
+
def within(days_range)
|
8
|
+
@days_range = days_range
|
9
|
+
Hash[*flat_map{|daily_earning| daily_earning}]
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def new_item(data)
|
15
|
+
# NOTE: could use column headers to be more precise
|
16
|
+
[Date.iso8601(data.first), data.last]
|
17
|
+
end
|
18
|
+
|
19
|
+
def list_params
|
20
|
+
super.tap do |params|
|
21
|
+
params[:path] = '/youtube/analytics/v1/reports'
|
22
|
+
params[:params] = {}.tap do |params|
|
23
|
+
params['ids'] = "contentOwner==#{@auth.owner_name}"
|
24
|
+
params['filters'] = "channel==#{@parent.id}"
|
25
|
+
params['start-date'] = @days_range.begin
|
26
|
+
params['end-date'] = @days_range.end
|
27
|
+
params['metrics'] = :earnings
|
28
|
+
params['dimensions'] = :day
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def items_key
|
34
|
+
'rows'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/yt/models/account.rb
CHANGED
@@ -4,9 +4,10 @@ module Yt
|
|
4
4
|
module Models
|
5
5
|
# Provides methods to access a YouTube account.
|
6
6
|
class Account < Base
|
7
|
-
has_one :authentication, delegate: [:access_token, :refresh_token, :expires_at]
|
8
7
|
has_one :channel, delegate: [:videos, :playlists, :create_playlist, :delete_playlists, :update_playlists]
|
9
8
|
has_one :user_info, delegate: [:id, :email, :has_verified_email?, :gender, :name, :given_name, :family_name, :profile_url, :avatar_url, :locale, :hd]
|
9
|
+
has_one :authentication, delegate: [:access_token, :refresh_token, :expires_at]
|
10
|
+
attr_reader :owner_name
|
10
11
|
|
11
12
|
def initialize(options = {})
|
12
13
|
@access_token = options[:access_token]
|
@@ -15,6 +16,7 @@ module Yt
|
|
15
16
|
@authorization_code = options[:authorization_code]
|
16
17
|
@redirect_uri = options[:redirect_uri]
|
17
18
|
@scopes = options[:scopes]
|
19
|
+
@owner_name = options[:owner_name]
|
18
20
|
end
|
19
21
|
|
20
22
|
def auth
|
data/lib/yt/models/channel.rb
CHANGED
data/lib/yt/version.rb
CHANGED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Yt::Associations::Earnings, :partner do
|
4
|
+
context 'given a Youtube Partner channel (with a content owner)' do
|
5
|
+
let(:channel) { $partner_channel }
|
6
|
+
|
7
|
+
describe '#earning' do
|
8
|
+
context 'given a date for which YouTube has estimated earnings' do
|
9
|
+
let(:earning) { channel.earning 5.days.ago}
|
10
|
+
it { expect(earning).to be_a Float }
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'given a date for which YouTube does not have estimated earnings' do
|
14
|
+
let(:earning) { channel.earning 5.days.from_now}
|
15
|
+
it { expect(earning).to be_nil }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#earning' do
|
20
|
+
let(:date) { 4.days.ago }
|
21
|
+
|
22
|
+
context 'given a :since option' do
|
23
|
+
let(:earnings) { channel.earnings since: date}
|
24
|
+
it { expect(earnings.keys.min).to eq date.to_date }
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'given a :from option' do
|
28
|
+
let(:earnings) { channel.earnings from: date}
|
29
|
+
it { expect(earnings.keys.min).to eq date.to_date }
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'given a :until option' do
|
33
|
+
let(:earnings) { channel.earnings until: date}
|
34
|
+
it { expect(earnings.keys.max).to eq date.to_date }
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'given a :to option' do
|
38
|
+
let(:earnings) { channel.earnings to: date}
|
39
|
+
it { expect(earnings.keys.max).to eq date.to_date }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -30,4 +30,17 @@ RSpec.configure do |config|
|
|
30
30
|
config.api_key = ENV['YT_TEST_SERVER_API_KEY']
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
|
+
config.before :all, partner: true do
|
35
|
+
Yt.configure do |config|
|
36
|
+
config.client_id = ENV['YT_TEST_PARTNER_CLIENT_ID']
|
37
|
+
config.client_secret = ENV['YT_TEST_PARTNER_CLIENT_SECRET']
|
38
|
+
end
|
39
|
+
# Create one Youtube Partner channel, authenticated as the content owner
|
40
|
+
attrs = {refresh_token: ENV['YT_TEST_CONTENT_OWNER_REFRESH_TOKEN']}
|
41
|
+
attrs[:owner_name] = ENV['YT_TEST_CONTENT_OWNER_NAME']
|
42
|
+
content_owner = Yt::Account.new attrs
|
43
|
+
attrs = {id: ENV['YT_TEST_PARTNER_CHANNEL_ID'], auth: content_owner}
|
44
|
+
$partner_channel = Yt::Channel.new attrs
|
45
|
+
end
|
46
|
+
end
|
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.5.
|
4
|
+
version: 0.5.7
|
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-05-
|
11
|
+
date: 2014-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -127,6 +127,7 @@ files:
|
|
127
127
|
- lib/yt/associations/authentications.rb
|
128
128
|
- lib/yt/associations/channels.rb
|
129
129
|
- lib/yt/associations/details_sets.rb
|
130
|
+
- lib/yt/associations/earnings.rb
|
130
131
|
- lib/yt/associations/ids.rb
|
131
132
|
- lib/yt/associations/playlist_items.rb
|
132
133
|
- lib/yt/associations/playlists.rb
|
@@ -141,6 +142,7 @@ files:
|
|
141
142
|
- lib/yt/collections/base.rb
|
142
143
|
- lib/yt/collections/channels.rb
|
143
144
|
- lib/yt/collections/details_sets.rb
|
145
|
+
- lib/yt/collections/earnings.rb
|
144
146
|
- lib/yt/collections/ids.rb
|
145
147
|
- lib/yt/collections/playlist_items.rb
|
146
148
|
- lib/yt/collections/playlists.rb
|
@@ -178,6 +180,7 @@ files:
|
|
178
180
|
- spec/associations/device_auth/authentications_spec.rb
|
179
181
|
- spec/associations/device_auth/channels_spec.rb
|
180
182
|
- spec/associations/device_auth/details_sets_spec.rb
|
183
|
+
- spec/associations/device_auth/earnings_spec.rb
|
181
184
|
- spec/associations/device_auth/ids_spec.rb
|
182
185
|
- spec/associations/device_auth/playlist_items_spec.rb
|
183
186
|
- spec/associations/device_auth/playlists_spec.rb
|
@@ -260,6 +263,7 @@ test_files:
|
|
260
263
|
- spec/associations/device_auth/authentications_spec.rb
|
261
264
|
- spec/associations/device_auth/channels_spec.rb
|
262
265
|
- spec/associations/device_auth/details_sets_spec.rb
|
266
|
+
- spec/associations/device_auth/earnings_spec.rb
|
263
267
|
- spec/associations/device_auth/ids_spec.rb
|
264
268
|
- spec/associations/device_auth/playlist_items_spec.rb
|
265
269
|
- spec/associations/device_auth/playlists_spec.rb
|