So, just a heads up, this is my first time working with google's apis and developer console, so forgive me if I missed something obvious that a more seasoned google developer would deem common sense. That being said. I am trying to create an installed application which will upload a video to youtube under my account. I am writing the application in powershell, so I am importing the appropriate google .Net libraries when the script is launched. From there, I essentially used the sample located here and just converted the content to powershell:
Add-Type -AssemblyName mscorlib
Add-Type -AssemblyName System.Net.Http
Add-Type -AssemblyName System
Add-Type -AssemblyName System.Core
Add-Type -AssemblyName System.Numerics
Add-Type -AssemblyName System.Xml
Add-Type -AssemblyName System.Xml.Linq
Add-Type -AssemblyName System.Data
Add-Type -AssemblyName System.Runtime.Serialization
#the below command imports the following assemblies: Google.Apis.Auth.dll, Google.Apis.Auth.PlatformServices.dll, Google.Apis.Core.dll, Google.Apis.dll, Google.Apis.PlatformServices.dll, Google.Apis.YouTube.v3.dll
Get-ChildItem 'C:\Users\whiggs\Documents\SAPIEN\PowerShell Studio\Projects\youtube\*.dll' | % {[reflection.assembly]::LoadFrom($_.FullName)}
$vid = "C:\Users\whiggs\Documents\gery2.mp4"
#$file = [System.IO.File]::OpenRead("C:\Users\whiggs\Documents\SAPIEN\PowerShell Studio\Projects\youtube\client_id.json")
$filemode = [System.IO.FileMode]::Open
$fileaccess = [System.IO.FileAccess]::Read
$stream = New-object System.IO.FileStream -ArgumentList "C:\Users\whiggs\Documents\SAPIEN\PowerShell Studio\Projects\youtube\client_secret.json", $filemode, $fileaccess
$googlebroker = New-object Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker
$thing = [Google.Apis.Auth.OAuth2.GoogleClientSecrets]::Load($stream)
[string[]]$scope = [Google.Apis.YouTube.v3.YouTubeService+ScopeConstants]::YoutubeUpload
#$scope = [Google.Apis.YouTube.v3.YouTubeService+Scope]::YoutubeUpload
$cancellation = [System.Threading.CancellationToken]::None
$googlebroker = [Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker]::AuthorizeAsync($thing.Secrets, $scope, "<google_username>", $cancellation)
$googlebroker.Wait()
[Google.Apis.Auth.OAuth2.UserCredential]$cred = $googlebroker.Result
$baseclient = new-object Google.Apis.Services.BaseClientService+Initializer
$baseclient.HttpClientInitializer = $cred
$baseclient.ApplicationName = "Contacts Tool"
$service = New-Object Google.Apis.YouTube.v3.YouTubeService($baseclient)
$video = New-Object Google.Apis.YouTube.v3.Data.Video
$video.Snippet = New-Object Google.Apis.YouTube.v3.Data.VideoSnippet
$video.Snippet.Title = "test"
$video.Snippet.Description = "none"
$video.Status = New-Object Google.Apis.YouTube.v3.Data.VideoStatus
$video.Status.PrivacyStatus = "public"
$vidstream = New-Object System.IO.FileStream -ArgumentList $vid, $filemode
$request = $service.Videos.Insert($video, "public", $vidstream, "video/*")
$task = $request.UploadAsync()
$task.Wait()
$vidstream.close()
$vidstream.Dispose()
Don't really need to include the code, because I know it is written correctly as no exception is generated. When I run the above code, it runs to completion without generating an exception, but if I take a look at the object stored in $task (type System.Threading.Tasks.Task), while the overall object reports that it ran to completion, digging deeper into the object's "Result" property reveals the task actually failed, and digging even further into the "exception" property provides the below error message:
The service youtube has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Access Not Configured. YouTube Data API has not been used in project <snip> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/youtube.googleapis.com/overview?project=<snip> then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry. [403]
Errors [
Message[Access Not Configured. YouTube Data API has not been used in project <snip> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/youtube.googleapis.com/overview?project=<snip> then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.] Location[ - ] Reason[accessNotConfigured] Domain[usageLimits]
]
at Google.Apis.Upload.ResumableUpload`1.<InitiateSessionAsync>d__25.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Upload.ResumableUpload.<UploadAsync>d__70.MoveNext()
So, it is clear that there is some kind of issue with the app as it is configured or the way in which I am authenticating to it. However, I know that the app is at least receiving the requests, as you can see here. So, after doing so research, I have a couple of educated guesses as to what the problem might be, and need some input as to a) which of these (if any) is the actual problem and b) what needs to be done to correct it. My first educated guess involves the parameters I passed to the "AuthorizeAsync" method of the Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker class. According to this document: "In this sample code a new UserCredential instance is created by calling the GoogleWebAuthorizationBroker.AuthorizeAsync method. This static method gets the client secret (or a stream to the client secret), the required scopes, the user identifier, the cancellation token for cancelling an operation, and an optional data store. If the data store is not specified, the default is a FileDataStore with a default Google.Apis.Auth folder. The folder is created in Environment.SpecialFolder.ApplicationData."
The part I want to focus on in the above statement is "the user identifier", as that is all the information that provided as to this parameter's description. The value that I put in was a string containing the user name for the google account that the app is registered under and the account that would upload the youtube videos, but I don't know if that was the value that was needed, as I had to login to the account anyway via a web browser as part of this process. If this is indeed the problem, what is "the user identifier" as far as this parameter is concerned. A little more detail in the documentation can go a long way. My second educated guess as to what is causing this has to do with the configuration of the application, but more specifically, the generated oauth credentials. The scopes that the app would need access to are apparently considered sensitive, and, if I am understanding this correctly, I have to authenticate from a verified domain and configure a bunch of advanced settings that, as someone writing this project for myself and not a company, I just do not have access to. I just want to upload a youtube video to my account, so why do I need to authenticate from a verified domain? What can I do to get around this? Any info would be great.
"<google_username>"
is used by filedatastore to store the credeitals for the user once they have consented access to your client. If you want to understand more about this then you should try and read my tutorial on file datastore
$googlebroker = [Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker]::AuthorizeAsync($thing.Secrets, $scope, "<google_username>", $cancellation)
YouTube Data API has not been used in project before or it is disabled.
Means that you have not enabled the YouTube api in your project on google Developer console or you have not applied and been granted any quota to this api yet. In Google developer console go to API Library -> YouTube Data API v3 and enable it. Once you have done that click manage then go to Quota. If you have not previously enabled it which i suspect you hadn't then now you will have 0 quota.
click the penile icon and apply for a quota for this api. It can take a while to get a response.