yt 0.25.13 → 0.32.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +305 -1
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +86 -5
  5. data/YOUTUBE_IT.md +3 -3
  6. data/lib/yt.rb +5 -2
  7. data/lib/yt/actions/list.rb +3 -3
  8. data/lib/yt/associations/has_authentication.rb +33 -1
  9. data/lib/yt/associations/has_reports.rb +13 -18
  10. data/lib/yt/collections/assets.rb +2 -2
  11. data/lib/yt/collections/authentications.rb +9 -2
  12. data/lib/yt/collections/base.rb +3 -3
  13. data/lib/yt/collections/bulk_report_jobs.rb +28 -0
  14. data/lib/yt/collections/bulk_reports.rb +24 -0
  15. data/lib/yt/collections/claims.rb +22 -1
  16. data/lib/yt/collections/comment_threads.rb +41 -0
  17. data/lib/yt/collections/content_owners.rb +1 -1
  18. data/lib/yt/collections/group_infos.rb +27 -0
  19. data/lib/yt/collections/group_items.rb +45 -0
  20. data/lib/yt/collections/reports.rb +75 -13
  21. data/lib/yt/collections/revocations.rb +30 -0
  22. data/lib/yt/collections/video_groups.rb +29 -0
  23. data/lib/yt/collections/videos.rb +34 -9
  24. data/lib/yt/constants/geography.rb +326 -0
  25. data/lib/yt/errors/forbidden.rb +1 -3
  26. data/lib/yt/errors/no_items.rb +1 -3
  27. data/lib/yt/errors/request_error.rb +10 -7
  28. data/lib/yt/errors/server_error.rb +1 -3
  29. data/lib/yt/errors/unauthorized.rb +3 -3
  30. data/lib/yt/models/account.rb +12 -0
  31. data/lib/yt/models/advertising_options_set.rb +4 -4
  32. data/lib/yt/models/bulk_report.rb +23 -0
  33. data/lib/yt/models/bulk_report_job.rb +23 -0
  34. data/lib/yt/models/channel.rb +21 -12
  35. data/lib/yt/models/claim.rb +13 -2
  36. data/lib/yt/models/comment.rb +37 -0
  37. data/lib/yt/models/comment_thread.rb +50 -0
  38. data/lib/yt/models/content_detail.rb +6 -0
  39. data/lib/yt/models/content_owner.rb +31 -1
  40. data/lib/yt/models/group_info.rb +16 -0
  41. data/lib/yt/models/group_item.rb +15 -0
  42. data/lib/yt/models/resource.rb +3 -10
  43. data/lib/yt/models/revocation.rb +12 -0
  44. data/lib/yt/models/right_owner.rb +0 -2
  45. data/lib/yt/models/snippet.rb +24 -3
  46. data/lib/yt/models/video.rb +42 -11
  47. data/lib/yt/models/video_group.rb +186 -0
  48. data/lib/yt/request.rb +5 -3
  49. data/lib/yt/version.rb +2 -2
  50. data/spec/collections/comment_threads_spec.rb +46 -0
  51. data/spec/collections/playlist_items_spec.rb +1 -1
  52. data/spec/collections/reports_spec.rb +2 -2
  53. data/spec/constants/geography_spec.rb +16 -0
  54. data/spec/models/annotation_spec.rb +1 -1
  55. data/spec/models/claim_spec.rb +15 -3
  56. data/spec/models/comment_spec.rb +40 -0
  57. data/spec/models/comment_thread_spec.rb +93 -0
  58. data/spec/models/content_detail_spec.rb +7 -0
  59. data/spec/models/reference_spec.rb +2 -2
  60. data/spec/models/request_spec.rb +21 -0
  61. data/spec/models/resource_spec.rb +0 -15
  62. data/spec/models/video_spec.rb +1 -1
  63. data/spec/requests/as_account/account_spec.rb +16 -4
  64. data/spec/requests/as_account/authentications_spec.rb +1 -13
  65. data/spec/requests/as_account/channel_spec.rb +15 -45
  66. data/spec/requests/as_account/playlist_item_spec.rb +3 -3
  67. data/spec/requests/as_account/playlist_spec.rb +5 -32
  68. data/spec/requests/as_account/video_spec.rb +2022 -21
  69. data/spec/requests/as_content_owner/account_spec.rb +4 -0
  70. data/spec/requests/as_content_owner/bulk_report_job_spec.rb +19 -0
  71. data/spec/requests/as_content_owner/channel_spec.rb +59 -270
  72. data/spec/requests/as_content_owner/content_owner_spec.rb +89 -1
  73. data/spec/requests/as_content_owner/playlist_spec.rb +0 -15
  74. data/spec/requests/as_content_owner/video_group_spec.rb +112 -0
  75. data/spec/requests/as_content_owner/video_spec.rb +72 -146
  76. data/spec/requests/as_server_app/channel_spec.rb +1 -21
  77. data/spec/requests/as_server_app/comment_spec.rb +22 -0
  78. data/spec/requests/as_server_app/comment_thread_spec.rb +27 -0
  79. data/spec/requests/as_server_app/comment_threads_spec.rb +41 -0
  80. data/spec/requests/as_server_app/playlist_item_spec.rb +2 -2
  81. data/spec/requests/as_server_app/playlist_spec.rb +1 -22
  82. data/spec/requests/as_server_app/video_spec.rb +21 -19
  83. data/spec/requests/as_server_app/videos_spec.rb +5 -5
  84. data/spec/requests/unauthenticated/video_spec.rb +1 -9
  85. data/spec/spec_helper.rb +1 -1
  86. data/yt.gemspec +2 -1
  87. metadata +51 -17
  88. data/lib/yt/collections/ids.rb +0 -27
  89. data/lib/yt/config.rb +0 -54
  90. data/lib/yt/models/configuration.rb +0 -70
  91. data/lib/yt/models/description.rb +0 -58
  92. data/lib/yt/models/url.rb +0 -91
  93. data/spec/models/configuration_spec.rb +0 -44
  94. data/spec/models/description_spec.rb +0 -94
  95. data/spec/models/url_spec.rb +0 -84
  96. data/spec/requests/as_account/resource_spec.rb +0 -18
@@ -1,27 +0,0 @@
1
- require 'yt/collections/base'
2
- require 'yt/models/id'
3
-
4
- module Yt
5
- module Collections
6
- # @private
7
- class Ids < Base
8
-
9
- private
10
-
11
- def attributes_for_new_item(data)
12
- data['id']
13
- end
14
-
15
- def list_params
16
- super.tap do |params|
17
- params[:params] = ids_params
18
- params[:path] = "/youtube/v3/#{@parent.kind.pluralize}"
19
- end
20
- end
21
-
22
- def ids_params
23
- {for_username: @parent.username, part: 'id'}
24
- end
25
- end
26
- end
27
- end
@@ -1,54 +0,0 @@
1
- require 'yt/models/configuration'
2
-
3
- module Yt
4
- # Provides methods to read and write global configuration settings.
5
- #
6
- # A typical usage is to set the API keys retrieved from the
7
- # {http://console.developers.google.com Google Developers Console}.
8
- #
9
- # @example Set the API key for a server-only YouTube app:
10
- # Yt.configure do |config|
11
- # config.api_key = 'ABCDEFGHIJ1234567890'
12
- # end
13
- #
14
- # @example Set the API client id/secret for a web-client YouTube app:
15
- # Yt.configure do |config|
16
- # config.client_id = 'ABCDEFGHIJ1234567890'
17
- # config.client_secret = 'ABCDEFGHIJ1234567890'
18
- # end
19
- #
20
- # Note that Yt.configure has precedence over values through with
21
- # environment variables (see {Yt::Models::Configuration}).
22
- #
23
- module Config
24
- # Yields the global configuration to the given block.
25
- #
26
- # @example
27
- # Yt.configure do |config|
28
- # config.api_key = 'ABCDEFGHIJ1234567890'
29
- # end
30
- #
31
- # @yield [Yt::Models::Configuration] The global configuration.
32
- def configure
33
- yield configuration if block_given?
34
- end
35
-
36
- # Returns the global {Yt::Models::Configuration} object.
37
- #
38
- # While this method _can_ be used to read and write configuration settings,
39
- # it is easier to use {Yt::Config#configure} Yt.configure}.
40
- #
41
- # @example
42
- # Yt.configuration.api_key = 'ABCDEFGHIJ1234567890'
43
- #
44
- # @return [Yt::Models::Configuration] The global configuration.
45
- def configuration
46
- @configuration ||= Yt::Configuration.new
47
- end
48
- end
49
-
50
- # @note Config is the only module auto-loaded in the Yt module,
51
- # in order to have a syntax as easy as Yt.configure
52
-
53
- extend Config
54
- end
@@ -1,70 +0,0 @@
1
- module Yt
2
- module Models
3
- # Provides an object to store global configuration settings.
4
- #
5
- # This class is typically not used directly, but by calling
6
- # {Yt::Config#configure Yt.configure}, which creates and updates a single
7
- # instance of {Yt::Models::Configuration}.
8
- #
9
- # @example Set the API client id/secret for a web-client YouTube app:
10
- # Yt.configure do |config|
11
- # config.client_id = 'ABCDEFGHIJ1234567890'
12
- # config.client_secret = 'ABCDEFGHIJ1234567890'
13
- # end
14
- #
15
- # @see Yt::Config for more examples.
16
- #
17
- # An alternative way to set global configuration settings is by storing
18
- # them in the following environment variables:
19
- #
20
- # * +YT_CLIENT_ID+ to store the Client ID for web/device apps
21
- # * +YT_CLIENT_SECRET+ to store the Client Secret for web/device apps
22
- # * +YT_API_KEY+ to store the API key for server/browser apps
23
- # * +YT_LOG_LEVEL+ to store the verbosity level of the logs
24
- #
25
- # In case both methods are used together,
26
- # {Yt::Config#configure Yt.configure} takes precedence.
27
- #
28
- # @example Set the API client id/secret for a web-client YouTube app:
29
- # ENV['YT_CLIENT_ID'] = 'ABCDEFGHIJ1234567890'
30
- # ENV['YT_CLIENT_SECRET'] = 'ABCDEFGHIJ1234567890'
31
- #
32
- class Configuration
33
- # @return [String] the Client ID for web/device YouTube applications.
34
- # @see https://console.developers.google.com Google Developers Console
35
- attr_accessor :client_id
36
-
37
- # @return [String] the Client Secret for web/device YouTube applications.
38
- # @see https://console.developers.google.com Google Developers Console
39
- attr_accessor :client_secret
40
-
41
- # @return [String] the API key for server/browser YouTube applications.
42
- # @see https://console.developers.google.com Google Developers Console
43
- attr_accessor :api_key
44
-
45
- # @return [String] the level of output to print for debugging purposes.
46
- attr_accessor :log_level
47
-
48
- # Initialize the global configuration settings, using the values of
49
- # the specified following environment variables by default.
50
- def initialize
51
- @client_id = ENV['YT_CLIENT_ID']
52
- @client_secret = ENV['YT_CLIENT_SECRET']
53
- @api_key = ENV['YT_API_KEY']
54
- @log_level = ENV['YT_LOG_LEVEL']
55
- end
56
-
57
- # @return [Boolean] whether the logging output is extra-verbose.
58
- # Useful when developing (e.g., to print the curl of every request).
59
- def developing?
60
- log_level.to_s.in? %w(devel)
61
- end
62
-
63
- # @return [Boolean] whether the logging output is verbose.
64
- # Useful when debugging (e.g., to print the curl of failing requests).
65
- def debugging?
66
- log_level.to_s.in? %w(devel debug)
67
- end
68
- end
69
- end
70
- end
@@ -1,58 +0,0 @@
1
- require 'yt/models/url'
2
-
3
- module Yt
4
- module Models
5
- # Encapsulates information about the description of a resource, for
6
- # instance a channel.
7
- # @see https://developers.google.com/youtube/v3/docs/channels#resource
8
- #
9
- # The value has a maximum length of 1000 characters.
10
- class Description < String
11
- # @return [Boolean] whether the description includes a link to a video
12
- # @example
13
- # description = Yt::Models::Description.new 'Link to video: youtube.com/watch?v=MESycYJytkU'
14
- # description.has_link_to_video? #=> true
15
- #
16
- # @todo add an option to match the link to a specific video
17
- def has_link_to_video?
18
- links.any?{|link| link.kind == :video}
19
- end
20
-
21
- # @return [Boolean] whether the description includes a link to a channel
22
- # @example
23
- # description = Yt::Description.new 'Link to channel: youtube.com/fullscreen'
24
- # description.has_link_to_channel? #=> true
25
- #
26
- # @todo add an option to match the link to a specific channel
27
- def has_link_to_channel?(options = {})
28
- links.any?{|link| link.kind == :channel}
29
- end
30
-
31
- # @return [Boolean] whether the description includes a link to subscribe
32
- # @example
33
- # description = Yt::Description.new 'Link to subscribe: youtube.com/subscription_center?add_user=fullscreen'
34
- # description.has_link_to_subscribe? #=> true
35
- #
36
- # @todo add an option to match the link to subscribe to a specific channel
37
- def has_link_to_subscribe?(options = {})
38
- links.any?{|link| link.kind == :subscription}
39
- end
40
-
41
- # @return [Boolean] whether the description includes a link to a playlist
42
- # @example
43
- # description = Yt::Description.new 'Link to playlist: youtube.com/playlist?list=LLxO1tY8h1AhOz0T4ENwmpow'
44
- # description.has_link_to_playlist? #=> true
45
- #
46
- # @todo add an option to match the link to a specific playlist
47
- def has_link_to_playlist?
48
- links.any?{|link| link.kind == :playlist}
49
- end
50
-
51
- private
52
-
53
- def links
54
- @links ||= self.split(' ').map{|word| URL.new word}
55
- end
56
- end
57
- end
58
- end
@@ -1,91 +0,0 @@
1
- module Yt
2
- module Models
3
- # @private
4
- class URL
5
- attr_reader :kind
6
-
7
- def initialize(url)
8
- @url = url
9
- @kind ||= parse url
10
- @match_data ||= {}
11
- end
12
-
13
- def id
14
- @match_data[:id]
15
- rescue IndexError
16
- end
17
-
18
- def username
19
- @match_data[:username]
20
- rescue IndexError
21
- end
22
-
23
- private
24
-
25
- def parse(url)
26
- matching_pattern = patterns.find do |pattern|
27
- @match_data = url.match pattern[:regex]
28
- end
29
- matching_pattern[:kind] if matching_pattern
30
- end
31
-
32
- def patterns
33
- # @note: :channel *must* be the last since one of its regex eats the
34
- # remaining patterns. In short, don't change the following order
35
-
36
- @patterns ||= patterns_for :playlist, :subscription, :video, :channel
37
- end
38
-
39
- def patterns_for(*kinds)
40
- prefix = '^(?:https?://)?(?:www\.)?'
41
- suffix = '(?:|/)'
42
- kinds.map do |kind|
43
- patterns = send "#{kind}_patterns" # meta programming :/
44
- patterns.map do |pattern|
45
- {kind: kind, regex: %r{#{prefix}#{pattern}#{suffix}}}
46
- end
47
- end.flatten
48
- end
49
-
50
- def subscription_patterns
51
- name = '(?:[a-zA-Z0-9&_=-]*)'
52
-
53
- %W{
54
- subscription_center\\?add_user=#{name}
55
- subscribe_widget\\?p=#{name}
56
- channel/#{name}\\?sub_confirmation=1
57
- }.map{|path| "youtube\\.com/#{path}"}
58
- end
59
-
60
- def playlist_patterns
61
- playlist_id = '(?<id>[a-zA-Z0-9_-]+)'
62
-
63
- %W{
64
- playlist\\?list=#{playlist_id}
65
- }.map{|path| "youtube\\.com/#{path}"}
66
- end
67
-
68
- def video_patterns
69
- video_id = '(?<id>[a-zA-Z0-9_-]+)'
70
-
71
- %W{
72
- youtube\\.com/watch\\?v=#{video_id}
73
- youtu\\.be/#{video_id}
74
- youtube\\.com/embed/#{video_id}
75
- youtube\\.com/v/#{video_id}
76
- }
77
- end
78
-
79
- def channel_patterns
80
- channel_id = '(?<id>[a-zA-Z0-9_-]+)'
81
- username = '(?<username>[a-zA-Z0-9_-]+)'
82
-
83
- %W{
84
- channel/#{channel_id}
85
- user/#{username}
86
- #{username}
87
- }.map{|path| "youtube\\.com/#{path}"}
88
- end
89
- end
90
- end
91
- end
@@ -1,44 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Yt::Configuration do
4
- subject(:config) { Yt::Configuration.new }
5
-
6
- describe '#client_id' do
7
- context 'without an environment variable YT_CLIENT_ID' do
8
- before { ENV['YT_CLIENT_ID'] = nil }
9
- it {expect(config.client_id).to be_nil }
10
- end
11
-
12
- context 'given an environment variable YT_CLIENT_ID' do
13
- let(:client_id) { '1234567890.apps.googleusercontent.com' }
14
- before { ENV['YT_CLIENT_ID'] = client_id}
15
- it {expect(config.client_id).to eq client_id }
16
- end
17
- end
18
-
19
- describe '#client_secret' do
20
- context 'without an environment variable YT_CLIENT_SECRET' do
21
- before { ENV['YT_CLIENT_SECRET'] = nil }
22
- it {expect(config.client_secret).to be_nil }
23
- end
24
-
25
- context 'given an environment variable YT_CLIENT_SECRET' do
26
- let(:client_secret) { '1234567890' }
27
- before { ENV['YT_CLIENT_SECRET'] = client_secret}
28
- it {expect(config.client_secret).to eq client_secret }
29
- end
30
- end
31
-
32
- describe '#api_key' do
33
- context 'without an environment variable YT_API_KEY' do
34
- before { ENV['YT_API_KEY'] = nil }
35
- it {expect(config.api_key).to be_nil }
36
- end
37
-
38
- context 'given an environment variable YT_API_KEY' do
39
- let(:api_key) { '123456789012345678901234567890' }
40
- before { ENV['YT_API_KEY'] = api_key}
41
- it {expect(config.api_key).to eq api_key }
42
- end
43
- end
44
- end
@@ -1,94 +0,0 @@
1
- require 'spec_helper'
2
- require 'yt/models/description'
3
-
4
- describe Yt::Description do
5
- subject(:description) { Yt::Description.new text }
6
-
7
- describe '#text' do
8
- let(:text) { 'this is a description' }
9
- it { expect(description).to eq 'this is a description' }
10
- end
11
-
12
- describe '#length' do
13
- let(:text) { 'twenty one characters' }
14
- it { expect(description.length).to eq 21 }
15
- end
16
-
17
- describe '#has_link_to_video?' do
18
- context 'without a video URL' do
19
- let(:text) { 'Link to channel: youtube.com/fullscreen' }
20
- it { expect(description).not_to have_link_to_video }
21
- end
22
-
23
- context 'with a video long URL' do
24
- let(:text) { 'example.com and Link to video: youtube.com/watch?v=MESycYJytkU' }
25
- it { expect(description).to have_link_to_video }
26
- end
27
-
28
- context 'with a video short URL' do
29
- let(:text) { 'Link to video: youtu.be/MESycYJytkU' }
30
- it { expect(description).to have_link_to_video }
31
- end
32
-
33
- context 'with a playlist-embedded video URL' do
34
- let(:text) { 'Link to video in playlist: youtube.com/watch?v=MESycYJytkU&index=619&list=LLxO1tY8h1AhOz0T4ENwmpow' }
35
- it { expect(description).to have_link_to_video }
36
- end
37
- end
38
-
39
- describe '#has_link_to_channel?' do
40
- context 'without a channel URL' do
41
- let(:text) { 'youtu.be/MESycYJytkU is a video link' }
42
- it { expect(description).not_to have_link_to_channel }
43
- end
44
-
45
- context 'with a channel long URL' do
46
- let(:text) { 'Link to channel: youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow' }
47
- it { expect(description).to have_link_to_channel }
48
- end
49
-
50
- context 'with a channel short URL' do
51
- let(:text) { 'Link to channel: youtube.com/fullscreen' }
52
- it { expect(description).to have_link_to_channel }
53
- end
54
-
55
- context 'with a channel user URL' do
56
- let(:text) { 'Link to channel: youtube.com/user/fullscreen' }
57
- it { expect(description).to have_link_to_channel }
58
- end
59
- end
60
-
61
- describe '#has_link_to_subscribe?' do
62
- context 'without a subscribe URL' do
63
- let(:text) { 'Link to video: youtu.be/MESycYJytkU' }
64
- it { expect(description).not_to have_link_to_subscribe }
65
- end
66
-
67
- context 'with a subscribe center URL' do
68
- let(:text) { 'Link to subscribe: youtube.com/subscription_center?add_user=fullscreen' }
69
- it { expect(description).to have_link_to_subscribe }
70
- end
71
-
72
- context 'with a subscribe short URL' do
73
- let(:text) { 'Link to subscribe: youtube.com/subscribe_widget?p=fullscreen' }
74
- it { expect(description).to have_link_to_subscribe }
75
- end
76
-
77
- context 'with a subscribe confirm URL' do
78
- let(:text) { 'Link to subscribe: youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow?sub_confirmation=1' }
79
- it { expect(description).to have_link_to_subscribe }
80
- end
81
- end
82
-
83
- describe '#has_link_to_playlist?' do
84
- context 'without a playlist URL' do
85
- let(:text) { 'Link to video: youtu.be/MESycYJytkU' }
86
- it { expect(description).not_to have_link_to_playlist }
87
- end
88
-
89
- context 'with a playlist long URL' do
90
- let(:text) { 'Link to playlist: youtube.com/playlist?list=LLxO1tY8h1AhOz0T4ENwmpow' }
91
- it { expect(description).to have_link_to_playlist }
92
- end
93
- end
94
- end
@@ -1,84 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'spec_helper'
4
- require 'yt/models/url'
5
-
6
- describe Yt::URL do
7
- subject(:url) { Yt::URL.new text }
8
-
9
- context 'given a long video URL' do
10
- let(:text) { 'youtube.com/watch?v=MESycYJytkU' }
11
- it {expect(url.kind).to eq :video }
12
- it {expect(url.id).to eq 'MESycYJytkU' }
13
- it {expect(url.username).to be_nil }
14
- end
15
-
16
- context 'given a short video URL' do
17
- let(:text) { 'https://youtu.be/MESycYJytkU' }
18
- it {expect(url.kind).to eq :video }
19
- it {expect(url.id).to eq 'MESycYJytkU' }
20
- end
21
-
22
- context 'given an embed video URL' do
23
- let(:text) { 'https://www.youtube.com/embed/MESycYJytkU' }
24
- it {expect(url.kind).to eq :video }
25
- it {expect(url.id).to eq 'MESycYJytkU' }
26
- end
27
-
28
- context 'given a v video URL' do
29
- let(:text) { 'https://www.youtube.com/v/MESycYJytkU' }
30
- it {expect(url.kind).to eq :video }
31
- it {expect(url.id).to eq 'MESycYJytkU' }
32
- end
33
-
34
- context 'given a playlist-embedded video URL' do
35
- let(:text) { 'youtube.com/watch?v=MESycYJytkU&list=LLxO1tY8h1AhOz0T4ENwmpow' }
36
- it {expect(url.kind).to eq :video }
37
- it {expect(url.id).to eq 'MESycYJytkU' }
38
- end
39
-
40
- context 'given a long channel URL' do
41
- let(:text) { 'http://youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow' }
42
- it {expect(url.kind).to eq :channel }
43
- it {expect(url.id).to eq 'UCxO1tY8h1AhOz0T4ENwmpow' }
44
- end
45
-
46
- context 'given a short channel URL' do
47
- let(:text) { 'https://www.youtube.com/Fullscreen' }
48
- it {expect(url.kind).to eq :channel }
49
- it {expect(url.username).to eq 'Fullscreen' }
50
- it {expect(url.id).to be_nil }
51
- end
52
-
53
- context 'given a user’s channel URL' do
54
- let(:text) { 'https://www.youtube.com/user/Fullscreen' }
55
- it {expect(url.kind).to eq :channel }
56
- it {expect(url.username).to eq 'Fullscreen' }
57
- end
58
-
59
- context 'given a subscription center URL' do
60
- let(:text) { 'youtube.com/subscription_center?add_user=Fullscreen' }
61
- it {expect(url.kind).to eq :subscription }
62
- end
63
-
64
- context 'given a subscription widget URL' do
65
- let(:text) { 'youtube.com/subscribe_widget?p=Fullscreen' }
66
- it {expect(url.kind).to eq :subscription }
67
- end
68
-
69
- context 'given a subscription confirmation URL' do
70
- let(:text) { 'youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow?sub_confirmation=1' }
71
- it {expect(url.kind).to eq :subscription }
72
- end
73
-
74
- context 'given a long playlist URL' do
75
- let(:text) { 'youtube.com/playlist?list=LLxO1tY8h1AhOz0T4ENwmpow' }
76
- it {expect(url.kind).to eq :playlist }
77
- it {expect(url.id).to eq 'LLxO1tY8h1AhOz0T4ENwmpow' }
78
- end
79
-
80
- context 'given a valid URL with a trailing slash' do
81
- let(:text) { 'https://www.youtube.com/user/Fullscreen/' }
82
- it {expect(url.kind).to eq :channel }
83
- end
84
- end