{"id":13858626,"url":"https://github.com/nullscreen/yt","last_synced_at":"2025-10-08T17:11:05.472Z","repository":{"id":15839836,"uuid":"18579828","full_name":"nullscreen/yt","owner":"nullscreen","description":"The reliable YouTube API Ruby client","archived":false,"fork":false,"pushed_at":"2025-09-16T20:34:02.000Z","size":6240,"stargazers_count":753,"open_issues_count":13,"forks_count":162,"subscribers_count":57,"default_branch":"master","last_synced_at":"2025-10-07T19:10:45.122Z","etag":null,"topics":["gem","oauth2","rails","ruby","video","youtube","youtube-analytics","youtube-api"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nullscreen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-04-09T00:30:22.000Z","updated_at":"2025-10-04T15:34:41.000Z","dependencies_parsed_at":"2023-10-03T15:02:49.372Z","dependency_job_id":"dd7a2f96-cba8-4f4a-b352-2115ae586b68","html_url":"https://github.com/nullscreen/yt","commit_stats":{"total_commits":639,"total_committers":34,"mean_commits":"18.794117647058822","dds":0.5993740219092332,"last_synced_commit":"a3fb683f716028b14c48e149e34be39f45a51db8"},"previous_names":["fullscreen/yt","fullscreeninc/googol"],"tags_count":194,"template":false,"template_full_name":null,"purl":"pkg:github/nullscreen/yt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullscreen%2Fyt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullscreen%2Fyt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullscreen%2Fyt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullscreen%2Fyt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nullscreen","download_url":"https://codeload.github.com/nullscreen/yt/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nullscreen%2Fyt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278981518,"owners_count":26079640,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gem","oauth2","rails","ruby","video","youtube","youtube-analytics","youtube-api"],"created_at":"2024-08-05T03:02:15.407Z","updated_at":"2025-10-08T17:11:05.456Z","avatar_url":"https://github.com/nullscreen.png","language":"Ruby","readme":"Yt - a Ruby client for the YouTube API\n======================================================\n\nYt helps you write apps that need to interact with YouTube.\n\nThe **source code** is available on [GitHub](https://github.com/Fullscreen/yt) and the **documentation** on [RubyDoc](http://www.rubydoc.info/gems/yt/frames).\n\n[![Build Status](http://img.shields.io/travis/Fullscreen/yt/master.svg)](https://travis-ci.org/Fullscreen/yt)\n[![Coverage Status](http://img.shields.io/coveralls/Fullscreen/yt/master.svg)](https://coveralls.io/r/Fullscreen/yt)\n[![Dependency Status](http://img.shields.io/gemnasium/Fullscreen/yt.svg)](https://gemnasium.com/Fullscreen/yt)\n[![Code Climate](https://codeclimate.com/github/Fullscreen/yt.png)](https://codeclimate.com/github/Fullscreen/yt)\n[![Online docs](http://img.shields.io/badge/docs-✓-green.svg)](http://www.rubydoc.info/gems/yt/frames)\n[![Gem Version](http://img.shields.io/gem/v/yt.svg)](http://rubygems.org/gems/yt)\n\nAfter [registering your app](#configuring-your-app), you can run commands like:\n\n```ruby\nchannel = Yt::Channel.new id: 'UCxO1tY8h1AhOz0T4ENwmpow'\nchannel.title #=\u003e \"Fullscreen\"\nchannel.public? #=\u003e true\nchannel.videos.count #=\u003e 12\n```\n\n```ruby\nvideo = Yt::Video.new id: 'jNQXAC9IVRw'\nvideo.title #=\u003e \"Fullscreen Creator Platform\"\nvideo.comment_count #=\u003e 308\nvideo.hd? #=\u003e true\nvideo.annotations.count #=\u003e 1\nvideo.comment_threads #=\u003e #\u003cYt::Collections::CommentThreads ...\u003e\n# Use #take to limit the number of pages need to fetch from server\nvideo.comment_threads.take(99).map(\u0026:author_display_name) #=\u003e [\"Paul\", \"Tommy\", ...]\n```\n\nThe **full documentation** is available at [rubydoc.info](http://www.rubydoc.info/gems/yt/frames).\n\nHow to install\n==============\n\nTo install on your system, run\n\n    gem install yt\n\nTo use inside a bundled Ruby project, add this line to the Gemfile:\n\n    gem 'yt', '~\u003e 0.34.0'\n\nSince the gem follows [Semantic Versioning](http://semver.org),\nindicating the full version in your Gemfile (~\u003e *major*.*minor*.*patch*)\nguarantees that your project won’t occur in any error when you `bundle update`\nand a new version of Yt is released.\n\nAvailable resources\n===================\n\nYt::Account\n-----------\n\nCheck [nullscreen.github.io/yt](http://nullscreen.github.io/yt/accounts.html) for the list of methods available for `Yt::Account`.\n\n\nYt::ContentOwner\n----------------\n\nUse [Yt::ContentOwner](http://www.rubydoc.info/gems/yt/Yt/Models/ContentOwner) to:\n\n* authenticate as a YouTube content owner\n* list the channels partnered with a YouTube content owner\n* list the claims administered by the content owner\n* list and delete the references administered by the content owner\n* list the policies and policy rules administered by the content owner\n* create assets\n* list assets\n\n```ruby\n# Content owners can be initialized with access token, refresh token or an authorization code\ncontent_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'\n\ncontent_owner.partnered_channels.count #=\u003e 12\ncontent_owner.partnered_channels.map \u0026:title #=\u003e [\"Fullscreen\", \"Best of Fullscreen\", ...]\ncontent_owner.partnered_channels.where(part: 'statistics').map \u0026:subscriber_count #=\u003e [136925, 56945, ...]\n\ncontent_owner.claims.where(q: 'Fullscreen').count #=\u003e 24\ncontent_owner.claims.first #=\u003e #\u003cYt::Models::Claim @id=...\u003e\ncontent_owner.claims.first.video_id #=\u003e 'jNQXAC9IVRw'\ncontent_owner.claims.first.status #=\u003e \"active\"\n\nreference = content_owner.references.where(asset_id: \"ABCDEFG\").first #=\u003e #\u003cYt::Models::Reference @id=...\u003e\nreference.delete #=\u003e true\n\ncontent_owner.policies.first #=\u003e #\u003cYt::Models::Policy @id=...\u003e\ncontent_owner.policies.first.name #=\u003e \"Track in all countries\"\ncontent_owner.policies.first.rules.first #=\u003e #\u003cYt::Models::PolicyRule @id=...\u003e\ncontent_owner.policies.first.rules.first.action #=\u003e \"monetize\"\ncontent_owner.policies.first.rules.first.included_territories #=\u003e [\"US\", \"CA\"]\n\ncontent_owner.create_asset type: 'web' #=\u003e #\u003cYt::Models::Asset @id=...\u003e\n\ncontent_owner.assets.first #=\u003e #\u003cYt::Models::AssetSnippet:0x007ff2bc543b00 @id=...\u003e\ncontent_owner.assets.first.id #=\u003e \"A4532885163805730\"\ncontent_owner.assets.first.title #=\u003e \"Money Train\"\ncontent_owner.assets.first.type #=\u003e \"web\"\ncontent_owner.assets.first.custom_id #=\u003e \"MoKNJFOIRroc\"\n\n```\n\n*All the above methods require authentication (see below).*\n\nYt::Channel\n-----------\n\nCheck [nullscreen.github.io/yt](http://nullscreen.github.io/yt/channels.html) for the list of methods available for `Yt::Channel`.\n\nYt::Video\n---------\n\nCheck [nullscreen.github.io/yt](http://nullscreen.github.io/yt/videos.html) for the list of methods available for `Yt::Video`.\n\nYt::Playlist\n------------\n\nCheck [nullscreen.github.io/yt](http://nullscreen.github.io/yt/playlists.html) for the list of methods available for `Yt::Playlist`.\n\nYt::PlaylistItem\n----------------\n\nCheck [nullscreen.github.io/yt](http://nullscreen.github.io/yt/playlist_items.html) for the list of methods available for `Yt::PlaylistItem`.\n\nYt::CommentThread\n----------------\n\nUse [Yt::CommentThread](http://www.rubydoc.info/gems/yt/Yt/Models/CommentThread) to:\n\n* Show details of a comment_thread.\n\n```ruby\nYt::CommentThread.new id: 'z13vsnnbwtv4sbnug232erczcmi3wzaug'\n\ncomment_thread.video_id #=\u003e \"1234\"\ncomment_thread.total_reply_count #=\u003e 1\ncomment_thread.can_reply? #=\u003e true\ncomment_thread.public? #=\u003e true\n\ncomment_thread.top_level_comment #=\u003e #\u003cYt::Models::Comment ...\u003e\ncomment_thread.text_display #=\u003e \"funny video!\"\ncomment_thread.like_count #=\u003e 9\ncomment_thread.updated_at #=\u003e 2016-03-22 12:56:56 UTC\ncomment_thread.author_display_name #=\u003e \"Joe\"\n```\n\nYt::Comment\n----------------\n\nUse [Yt::Comment](http://www.rubydoc.info/gems/yt/Yt/Models/Comment) to:\n\n* Get details of a comment.\n\n```ruby\nYt::Comment.new id: 'z13vsnnbwtv4sbnug232erczcmi3wzaug'\n\ncomment.text_display #=\u003e \"awesome\"\ncomment.author_display_name #=\u003e \"Jack\"\ncomment.like_count #=\u003e 1\ncomment.updated_at #=\u003e 2016-03-22 12:56:56 UTC\ncomment.parent_id #=\u003e \"abc1234\" (return nil if the comment is not a reply)\n```\n\nYt::BulkReportJob\n----------------\n\nUse [Yt::BulkReportJob](http://www.rubydoc.info/gems/yt/Yt/Models/BulkReportJob) to:\n\n* Get details of a bulk report job.\n\n```ruby\ncontent_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'\nbulk_report_job = content_owner.bulk_report_jobs.first\n\nbulk_report_job.report_type_id #=\u003e \"content_owner_demographics_a1\"\n```\n\nYt::BulkReport\n----------------\n\nUse [Yt::BulkReport](http://www.rubydoc.info/gems/yt/Yt/Models/BulkReport) to:\n\n* Get details of a bulk report.\n\n```ruby\ncontent_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'\nbulk_report_job = content_owner.bulk_report_jobs.first\nbulk_report = bulk_report_job.bulk_reports.first\n\nbulk_report.start_time #=\u003e 2017-08-11 07:00:00 UTC\nbulk_report.end_time #=\u003e 2017-08-12 07:00:00 UTC\nbulk_report.download_url #=\u003e \"https://youtubereporting.googleapis.com/v1/...\"\n```\n\nYt::Collections::Videos\n-----------------------\n\nUse [Yt::Collections::Videos](http://www.rubydoc.info/gems/yt/Yt/Collections/Videos) to:\n\n* search for videos\n\n```ruby\nvideos = Yt::Collections::Videos.new\nvideos.where(order: 'viewCount').first.title #=\u003e  \"PSY - GANGNAM STYLE\"\nvideos.where(q: 'Fullscreen CreatorPlatform', safe_search: 'none').size #=\u003e 324\nvideos.where(chart: 'mostPopular', video_category_id: 44).first.title #=\u003e \"SINISTER - Trailer\"\nvideos.where(id: 'jNQXAC9IVRw,invalid').map(\u0026:title) #=\u003e [\"Fullscreen Creator Platform\"]\n```\n\n*The methods above do not require authentication.*\n\n\nYt::Annotation\n--------------\n\nCheck [nullscreen.github.io/yt](http://nullscreen.github.io/yt/annotations.html) for the list of methods available for `Yt::Annotation`.\n\n\nYt::MatchPolicy\n---------------\n\nUse [Yt::MatchPolicy](http://www.rubydoc.info/gems/yt/Yt/Models/MatchPolicy) to:\n\n* update the policy used by an asset\n\n```ruby\ncontent_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'\nmatch_policy = Yt::MatchPolicy.new asset_id: 'ABCD12345678', auth: content_owner\nmatch_policy.update policy_id: 'aBcdEF6g-HJ' #=\u003e true\n```\n\nYt::Asset\n---------\n\nUse [Yt::Asset](http://www.rubydoc.info/gems/yt/Yt/Models/Asset) to:\n\n* read the ownership of an asset\n* update the attributes of an asset\n\n```ruby\n\ncontent_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'\nasset = Yt::Asset.new id: 'ABCD12345678', auth: content_owner\nasset.ownership #=\u003e #\u003cYt::Models::Ownership @general=...\u003e\nasset.ownership.obtain! #=\u003e true\nasset.general_owners.first.owner #=\u003e 'CMSname'\nasset.general_owners.first.everywhere? #=\u003e true\nasset.ownership.release! #=\u003e true\n\nasset.update metadata_mine: {notes: 'Some notes'} #=\u003e true\n```\n\n* to retrieve metadata for an asset (e.g. title, notes, description, custom_id)\n\n```ruby\ncontent_owner = Yt::ContentOwner.new(...)\nasset = content_owner.assets.where(id: 'A969176766549462', fetch_metadata: 'mine').first\nasset.metadata_mine.title #=\u003e \"Master Final   Neu La Anh Fix\"\n\nasset = content_owner.assets.where(id: 'A969176766549462', fetch_metadata: 'effective').first\nasset.metadata_effective.title #=\u003e \"Neu la anh\" (different due to ownership conflicts)\n```\n\n```ruby\nasset = content_owner.assets.where(id: 'A125058570526569', fetch_ownership: 'effective').first\nasset.ownership_effective.general_owners.first.owner # =\u003e \"XOuN81q-MeEUVrsiZeK1lQ\"\n```\n\n* to search for an asset\n\n```ruby\ncontent_owner.assets.where(labels: \"campaign:cpiuwdz-8oc\").size #=\u003e 417\ncontent_owner.assets.where(labels: \"campaign:cpiuwdz-8oc\").first.title #=\u003e \"Whoomp! (Supadupafly) (Xxl Hip House Mix)\"\n```\n\nYt::Claim\n---------\n\nUse [Yt::Claim](http://www.rubydoc.info/gems/yt/Yt/Models/Claim) to:\n\n* read the attributes of a claim\n* view the history of a claim\n* update the attributes of an claim\n\n```ruby\n\ncontent_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'\nclaim = Yt::Claim.new id: 'ABCD12345678', auth: content_owner\nclaim.video_id #=\u003e 'va141cJga2'\nclaim.asset_id #=\u003e 'A1234'\nclaim.content_type #=\u003e 'audiovisual'\nclaim.active? #=\u003e true\n\nclaim.claim_history #=\u003e #\u003cYt::Models::ClaimHistory ...\u003e\nclaim.claim_history.events[0].type #=\u003e \"claim_create\"\n\nclaim.delete #=\u003e true\n\ndata = {\n  is_manual_claim: true,\n  content_type: 'audiovisual',\n  asset_id: 'A123123123123123',\n  policy: { id: 'S123123123123123' },\n  video_id: 'myvIdeoIdYT',\n  match_info: {\n    match_segments: [\n      {\n        manual_segment: {\n          start: '00:00:20.000',\n          finish: '00:01:20.000'\n        }\n      },\n      {\n        manual_segment: {\n          start: '00:02:30.000',\n          finish: '00:03:50.000'\n        }\n      }\n    ]\n  }\n}\n\ncontent_owner.claims.insert(data)\n```\n\n*The methods above require to be authenticated as the video’s content owner (see below).*\n\nYt::Ownership\n-------------\n\nUse [Yt::Ownership](http://www.rubydoc.info/gems/yt/Yt/Models/Ownership) to:\n\n* update the ownership of an asset\n\n```ruby\ncontent_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'\nownership = Yt::Ownership.new asset_id: 'ABCD12345678', auth: $content_owner\nnew_general_owner_attrs = {ratio: 100, owner: 'CMSname', type: 'include', territories: ['US', 'CA']}\nownership.update general: [new_general_owner_attrs]\n```\n\n*The methods above require to be authenticated as the video’s content owner (see below).*\n\nYt::AdvertisingOptionsSet\n-------------------------\n\nUse [Yt::AdvertisingOptionsSet](http://www.rubydoc.info/gems/yt/Yt/Models/AdvertisingOptionsSet) to:\n\n* update the advertising settings of a video\n\n```ruby\ncontent_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.1.ABCDEFGHIJ'\nad_options = Yt::AdvertisingOptionsSet.new video_id: 'jNQXAC9IVRw', auth: $content_owner\nad_options.update ad_formats: %w(standard_instream long) #=\u003e true\n```\n\n*The methods above require to be authenticated as the video’s content owner (see below).*\n\nInstrumentation\n===============\n\nYt leverages [Active Support Instrumentation](http://edgeguides.rubyonrails.org/active_support_instrumentation.html) to provide a hook which developers can use to be notified when HTTP requests to YouTube are made.  This hook may be used to track the number of requests over time, monitor quota usage, provide an audit trail, or track how long a specific request takes to complete.\n\nSubscribe to the `request.yt` notification within your application:\n\n```ruby\nActiveSupport::Notifications.subscribe 'request.yt' do |*args|\n  event = ActiveSupport::Notifications::Event.new(*args)\n\n  event.payload[:request_uri] #=\u003e #\u003cURI::HTTPS URL:https://www.googleapis.com/youtube/v3/channels?id=UCxO1tY8h1AhOz0T4ENwmpow\u0026part=snippet\u003e\n  event.payload[:method] #=\u003e :get\n  event.payload[:response] #=\u003e #\u003cNet::HTTPOK 200 OK readbody=true\u003e\n\n  event.end #=\u003e 2014-08-22 16:57:17 -0700\n  event.duration #=\u003e 141.867 (ms)\nend\n```\n\nConfiguring your app\n====================\n\nIn order to use Yt you must register your app in the [Google Developers Console](https://console.developers.google.com).\n\nIf you don’t have a registered app, browse to the console and select \"Create Project\":\n![01-create-project](https://cloud.githubusercontent.com/assets/7408595/3373043/4224c894-fbb0-11e3-9f8a-4d96bddce136.png)\n\nWhen your project is ready, select APIs \u0026 Auth in the menu and individually enable Google+, YouTube Analytics and YouTube Data API:\n![02-select-api](https://cloud.githubusercontent.com/assets/4453997/8442701/5d0f77f4-1f35-11e5-93d8-07d4459186b5.png)\n![02a-enable google api](https://cloud.githubusercontent.com/assets/4453997/8442306/0f714cb8-1f33-11e5-99b3-f17a4b1230fe.png)\n![02b-enable youtube api](https://cloud.githubusercontent.com/assets/4453997/8442304/0f6fd0e0-1f33-11e5-981a-acf90ccd7409.png)\n![02c-enable youtube analytics api](https://cloud.githubusercontent.com/assets/4453997/8442305/0f71240e-1f33-11e5-9b60-4ecea02da9be.png)\n\nThe next step is to create an API key. Depending on the nature of your app, you should pick one of the following strategies.\n\nApps that do not require user interactions\n------------------------------------------\n\nIf you are building a read-only app that fetches public data from YouTube, then\nall you need is a **Public API access**.\n\nClick on \"Create new Key\" in the Public API section and select \"Server Key\":\n![03-create-key](https://cloud.githubusercontent.com/assets/7408595/3373045/42258fcc-fbb0-11e3-821c-699c8a3ce7bc.png)\n![04-create-server-key](https://cloud.githubusercontent.com/assets/7408595/3373044/42251db2-fbb0-11e3-93f9-8f06f8390b4e.png)\n\nOnce the key for server application is created, copy the API key and add it\nto your code with the following snippet of code (replacing with your own key):\n\n```ruby\nYt.configure do |config|\n  config.api_key = 'AIzaSyAO8dXpvZcaP2XSDFBD91H8yQ'\nend\n```\n\nRemember: this kind of app is not allowed to perform any destructive operation,\nso you won’t be able to like a video, subscribe to a channel or delete a\nplaylist from a specific account. You will only be able to retrieve read-only\ndata.\n\nWeb apps that require user interactions\n---------------------------------------\n\nIf you are building a web app that manages YouTube accounts, you need the\nowner of each account to authorize your app. There are three scenarios:\n\nScenario 1. If you already have the account’s **access token**, then you are ready to go.\nJust pass that access token to the account initializer, such as:\n\n```ruby\naccount = Yt::Account.new access_token: 'ya29.1.ABCDEFGHIJ'\naccount.email #=\u003e (retrieves the account’s e-mail address)\naccount.videos #=\u003e (lists a video to an account’s playlist)\n```\n\nScenario 2. If you don’t have the account’s access token, but you have the\n**refresh token**, then it’s almost as easy.\nIn the [Google Developers Console](https://console.developers.google.com),\nfind the web application that was used to obtain the refresh token, copy the\nClient ID and Client secret and add them to you code with the following snippet\nof code (replacing with your own keys):\n\n```ruby\nYt.configure do |config|\n  config.client_id = '1234567890.apps.googleusercontent.com'\n  config.client_secret = '1234567890'\nend\n```\nThen you can manage a YouTube account by passing the refresh token to the\naccount initializer, such as:\n\n```ruby\naccount = Yt::Account.new refresh_token: '1/1234567890'\naccount.email #=\u003e (retrieves the account’s e-mail address)\naccount.videos #=\u003e (lists a video to an account’s playlist)\n```\n\nScenario 3. If you don’t have any account’s token, then you can get one by\nhaving the user authorize your app through the Google OAuth page.\n\nIn the [Google Developers Console](https://console.developers.google.com),\nclick on \"Create new Client ID\" in the OAuth section and select \"Web application\":\n![06-create-client-key](https://cloud.githubusercontent.com/assets/7408595/3373047/42379eba-fbb0-11e3-89c4-16b10e072de6.png)\n\nFill the \"Authorized Redirect URI\" textarea with the URL of your app where you\nwant to redirect users after they authorize their YouTube account.\n\nOnce the Client ID for web application is created, copy the Client ID and secret\nand add them to your code with the following snippet of code (replacing with your own keys):\n\n```ruby\nYt.configure do |config|\n  config.client_id = '49781862760-4t610gtk35462g.apps.googleusercontent.com'\n  config.client_secret = 'NtFHjZkJcwYZDfYVz9mp8skz9'\nend\n```\n\nFinally, in your web app, add a link to the URL generated by running\n\n```ruby\nYt::Account.new(scopes: scopes, redirect_uri: redirect_uri).authentication_url\n```\n\nwhere `redirect_uri` is the URL you entered in the form above, and `scopes` is\nthe list of YouTube scopes you want the user to authorize. Depending on the\nnature of your app, you can pick one or more among `youtube`, `youtube.readonly` `userinfo.email`.\n\nEvery user who authorizes your app will be redirected to the `redirect_uri`\nwith an extra `code` parameter that looks something like `4/Ja60jJ7_Kw0`.\nJust pass the code to the following method to authenticate and initialize the account:\n\n```ruby\naccount = Yt::Account.new authorization_code: '4/Ja60jJ7_Kw0', redirect_uri: redirect_uri\naccount.email #=\u003e (retrieves the account’s e-mail address)\naccount.videos #=\u003e (lists a video to an account’s playlist)\n```\n\nConfiguring with environment variables\n--------------------------------------\n\nAs an alternative to the approach above, you can configure your app with\nvariables. Setting the following environment variables:\n\n```bash\nexport YT_CLIENT_ID=\"1234567890.apps.googleusercontent.com\"\nexport YT_CLIENT_SECRET=\"1234567890\"\nexport YT_API_KEY=\"123456789012345678901234567890\"\n```\n\nis equivalent to configuring your app with the initializer:\n\n```ruby\nYt.configure do |config|\n  config.client_id = '1234567890.apps.googleusercontent.com'\n  config.client_secret = '1234567890'\n  config.api_key = '123456789012345678901234567890'\nend\n```\n\nso use the approach that you prefer.\nIf a variable is set in both places, then `Yt.configure` takes precedence.\n\nHow to test\n===========\n\nTo run tests:\n\n```bash\nrspec\n```\n\nWe recommend RSpec \u003e= 3.8.\n\nYt comes with two different sets of tests:\n\n1. Unit tests in `spec/models`, `spec/collections` and `spec/errors`\n2. Legacy integration tests in `spec/requests`\n\nComing soon will be a new set of high-level integration tests.\n\nIntegration tests are recorded with VCR. Some of the tests refer to\nfixture data that an arbitrary account may not have access to. If you\nneed to modify one of these tests or re-record the cassette, we'd\nsuggest working against your own version of the testing setup. Then in\nyour pull request, we can help canonize your test/fixtures.\n\nSome of the integration tests require authentication. These can be set\nwith the following environment variables:\n\n* `YT_TEST_CLIENT_ID`\n* `YT_TEST_CLIENT_SECRET`\n* `YT_TEST_API_KEY`\n* `YT_TEST_REFRESH_TOKEN`\n\nHow to release new versions\n===========================\n\nIf you are a manager of this project, remember to upgrade the [Yt gem](http://rubygems.org/gems/yt)\nwhenever a new feature is added or a bug gets fixed.\n\nMake sure all the tests are passing on [Travis CI](https://travis-ci.org/Fullscreen/yt),\ndocument the changes in CHANGELOG.md and README.md, bump the version, then run\n\n    rake release\n\nRemember that the yt gem follows [Semantic Versioning](http://semver.org).\nAny new release that is fully backward-compatible should bump the *patch* version (0.0.x).\nAny new version that breaks compatibility should bump the *minor* version (0.x.0)\n\nHow to contribute\n=================\n\nYt needs your support!\nThe goal of Yt is to provide a Ruby interface for all the methods exposed by\nthe [YouTube Data API (v3)](https://developers.google.com/youtube/v3) and by\nthe [YouTube Analytics API](https://developers.google.com/youtube/analytics).\n\nIf you find that a method is missing, fork the project, add the missing code,\nwrite the appropriate tests, then submit a pull request, and it will gladly\nbe merged!\n\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnullscreen%2Fyt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnullscreen%2Fyt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnullscreen%2Fyt/lists"}