Google chat - Invalid space resource name in request - c#

can someone help me with "Invalid space resource name in request." error?
I created service account/application in Google Cloud
I created Google Chat API
I created space "server" and added my application to space
using Google.Apis.Auth.OAuth2;
using Google.Apis.HangoutsChat.v1;
using Google.Apis.Services;
Console.WriteLine("START");
SendMessage("spaces/server", "Hello Jozef");
Console.WriteLine("END");
void SendMessage(string space, string message, string thread = null)
{
try
{
var jsonPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "E://serverapplication-92ed800d27af.json");
using (var stream = new FileStream(jsonPath, FileMode.Open, FileAccess.Read))
{
string[] scopes = new[] { "https://www.googleapis.com/auth/chat.bot" };
var credential = GoogleCredential.FromStream(stream)
.CreateScoped(scopes);
var service = new HangoutsChatService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "ServerApplication"
});
var pubSubMessage = new Google.Apis.HangoutsChat.v1.Data.Message
{
Text = message,
Thread = new Google.Apis.HangoutsChat.v1.Data.Thread() { Name = thread },
Sender = new Google.Apis.HangoutsChat.v1.Data.User() { Name = "ServerApplication", DisplayName = "ServerApplication" },
};
SpacesResource.MessagesResource.CreateRequest req = new SpacesResource.MessagesResource(service).Create(pubSubMessage, space);
var result = req.Execute();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
It seems that application and credentials are ok. What can cause this error? Is it correct if I created a "server" space and added this application there?
The service chat has thrown an exception.
HttpStatusCode is BadRequest.
Google.Apis.Requests.RequestError
Invalid space resource name in request. [400]
Errors [
Message[Invalid space resource name in request.] Location[ - ] Reason[badRequest] Domain[global]
]
Google.GoogleApiException: The service chat has thrown an exception. HttpStatusCode is BadRequest. Invalid space resource name in request.
at Google.Apis.Requests.ClientServiceRequest`1.ParseResponse(HttpResponseMessage response)
at Google.Apis.Requests.ClientServiceRequest`1.Execute()
at Program.<<Main>$>g__SendMessage|0_0(String space, String message, String thread) in E:\TestGoogleChat\Program.cs:line 37
Thank you for any ideas or observations

Your calling the method wrong. All methods need to be called though the service object.
This will get you a list of spaces.
var listOfSpaces = service.Spaces.List().Execute();
Then to create a message you add it to the space
var request = service.Spaces.Messages.Create(new Message(), "spaces/{SpaceId}");
var response = request.Execute();
spaces create
As stated in the docs for spaces.create
Developer Preview: Available as part of the Google Workspace Developer Preview Program, which grants early access to certain features.
As this method is not fully available this means that the client library will not be generated with this method. If you do have access to that method you would need to send the request yourself.

Related

Youtube v3 API captions downloading

I'm trying to download captions from some videos on Youtube using their nuget package. Here's some code:
var request = _youtube.Search.List("snippet,id");
request.Q = "Bill Gates";
request.MaxResults = 50;
request.Type = "video";
var results = request.Execute();
foreach (var result in results.Items)
{
var captionListRequest = _youtube.Captions.List("id,snippet", result.Id.VideoId);
var captionListResponse = captionListRequest.Execute();
var russianCaptions =
captionListResponse.Items.FirstOrDefault(c => c.Snippet.Language.ToLower() == "ru");
if (russianCaptions != null)
{
var downloadRequest = _youtube.Captions.Download(russianCaptions.Id);
downloadRequest.Tfmt = CaptionsResource.DownloadRequest.TfmtEnum.Srt;
var ms = new MemoryStream();
downloadRequest.Download(ms);
}
}
When the Download method is called I'm getting a weird Newtonsoft.JSON Exception that says:
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: T. Path '', line 0, position 0.'
at Newtonsoft.Json.JsonTextReader.ParseValue()
I've read some other threads on captions downloading problems and have tried to change my authorization workflow: first I've tried to use just the ApiKey but then also tried OAuth. Here's how it looks now:
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
new ClientSecrets
{
ClientId = "CLIENT_ID",
ClientSecret = "CLIENT_SECRET"
},
new[] { YouTubeService.Scope.YoutubeForceSsl },
"user",
CancellationToken.None,
new FileDataStore("Youtube.CaptionsCrawler")).Result;
_youtube = new YouTubeService(new BaseClientService.Initializer
{
ApplicationName = "LKS Captions downloader",
HttpClientInitializer = credential
});
So, is it even possible to do what I'm trying to achieve?
P.S. I was able to dig deep into the youtube nuget package and as I see, the actual message, that I get (that Newtonsoft.JSON is trying to deserialize, huh!) is "The permissions associated with the request are not sufficient to download the caption track. The request might not be properly authorized, or the video order might not have enabled third-party contributions for this caption."
So, do I have to be the video owner to download captions? But if so, how do other programs like Google2SRT work?
Found this post How to get "transcript" in youtube-api v3
You can get them via GET request on: http://video.google.com/timedtext?lang={LANG}&v={VIDEOID}
Example:
http://video.google.com/timedtext?lang=en&v=-osCkzoL53U
Note that they should have subtitles added, will not work if auto-generated.

How to programatically apply an existing SSL certificate to an Azure web app

I'm using the Azure Fluent Management API to automate our deployment process. Up until now, I've had minimal problems.
We have SSL certificates already uploaded into Azure and can manually bind them to a web site through the Azure portal. But I can't find a mechanism for doing this programmatically.
The closest I can find is below and in the documentation here.
webApp.Update()
.DefineSslBinding()
.ForHostname(domainName)
.WithPfxCertificateToUpload(pfxFile, password)
.WithSniBasedSsl()
.Attach();
However, this is obviously uploading a new certificate, not using an existing one.
There are two other options after the ForHostName() call:
WithExistingAppServiceCertificateOrder(certificateOrder)
and
WithNewStandardSslCertificateOrder(certificateOrderName)
But my understanding is that these are related to purchasing the certificates through Azure/Microsoft.
I also can't see anything in the REST API documentation.
So, how can I associate an existing certificate with a web app, in code?
Obviously this was not critical given I've only found an answer 9 months later.
Anyhow, the answer below is copied from the link provided.
await azure
.WebApps
.Inner
.CreateOrUpdateHostNameBindingWithHttpMessagesAsync(
resourceGroupName,
webAppName,
domain,
new HostNameBindingInner(
azureResourceType: AzureResourceType.Website,
hostNameType: HostNameType.Verified,
customHostNameDnsRecordType: CustomHostNameDnsRecordType.CName,
sslState: SslState.SniEnabled,
thumbprint: thumbprint));
As far as I know, the Azure Fluent Management API’s version is 1.0.0-beta50, so it maybe not contain the method add existing certificate to the host name.
I suggest you could use REST API to achieve it.
I suggest you could send request to below url.
Url: https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Web/sites/{snapshotName}?api-version={api-version}
Method: PUT
Parameter:
subscriptionId The identifier of your subscription where the snapshot is being created.
resourceGroup The name of the resource group that will contain the snapshot.
WebappName The name of the WebappName.
api-version The version of the API to use.
Request content:
{
"properties": {
"HostNameSslStates": [
{
"SslState": "the SSL state",
"ToUpdate": "True",
"Thumbprint": "The Thumbprint of the certificate, you could find it in the portal",
"Name": "yourwebsitename"
}
]
},
"kind": "app",
"location": "yourlocation",
"tags": {
"hidden-related:/subscriptions/{subscriptionId}/resourcegroups/{resourceGroup}/providers/Microsoft.Web/serverfarms/{yourserviceplan}": "empty"
}
}
More details, you could refer to below C# codes:
Json.txt:
{
"properties": {
"HostNameSslStates": [
{
"SslState": "1",
"ToUpdate": "True",
"Thumbprint": "BE58B05C5CADE03628D0D58B369D0DA6F535B0FA",
"Name": "test.azureclubs.com"
}
]
},
"kind": "app",
"location": "East Asia",
"tags": {
"hidden-related:/subscriptions/xxxxxxxxxxxxxxxx/resourcegroups/xxxxxxxxxxxxx/providers/Microsoft.Web/serverfarms/BrandoTestServicePlan": "empty"
}
}
Code:
string body = File.ReadAllText(#"D:\json.txt");
// Display the file contents to the console. Variable text is a string.
string tenantId = "xxxxxxxxxxxxxxxxxxxxxxxxx";
string clientId = "xxxxxxxxxxxxxxxxxxxxxxxxxxx";
string clientSecret = "xxxxxxxxxxxxxxxxxxxxxxxxx";
string subscriptionid = "xxxxxxxxxxxxxxxxxxxxxxxxxx";
string resourcegroup = "BrandoSecondTest";
string appname = "BrandoTestApp";
string version = "2015-08-01";
string authContextURL = "https://login.windows.net/" + tenantId;
var authenticationContext = new AuthenticationContext(authContextURL);
var credential = new ClientCredential(clientId, clientSecret);
var result = authenticationContext.AcquireTokenAsync(resource: "https://management.azure.com/", clientCredential: credential).Result;
if (result == null)
{
throw new InvalidOperationException("Failed to obtain the JWT token");
}
string token = result.AccessToken;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format("https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Web/sites/{2}?api-version={3}", subscriptionid, resourcegroup, appname, version));
request.Method = "PUT";
request.Headers["Authorization"] = "Bearer " + token;
request.ContentType = "application/json";
try
{
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(body);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// Get the response
var httpResponse = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
Console.WriteLine(streamReader.ReadToEnd());
}
This solution works in 2021. You only need to know the thumbprint of your certificate and it should be in the same resource group as your web app.
var webApp = azure.WebApps
.GetById("webapp resource Id goes here")
.Update()
.DefineSslBinding()
.ForHostname("host name goes here")
.WithExistingCertificate("thumbprint goes here")
.WithSniBasedSsl()
.Attach()
.Apply();

Youtube Live API - Broadcast premission denied using OAuth

I am trying to broadcast live from my .Net application using Youtube.Data.Api v3.
I have set up OAuth and downloaded the .JSON file, and that works fine. I know that, because I have already successfully obtained a list of channels resp. videos on my account, i.e., following code works:
var channelsRequest = ytService.Channels.List("contentDetails, snippet");
channelsRequest.Mine = true;
var channelsListResponse = channelsRequest.Execute();
But if I try to execute a insert request (for completeness I show you the whole method),
public static LiveBroadcast CreateImmediateBroadcast(string title = "DefaultBroadcast") {
var snippet = new LiveBroadcastSnippet();
snippet.Title = title;
snippet.ScheduledStartTime = DateTime.Now;
snippet.ScheduledEndTime = DateTime.Now + TimeSpan.FromMinutes(60);
var status = new LiveBroadcastStatus();
status.PrivacyStatus = "unlisted";
var broadcast = new LiveBroadcast();
broadcast.Kind = "youtube#liveBroadcast";
broadcast.Snippet = snippet;
broadcast.Status = status;
var insertBroadcastRequest = ytService.LiveBroadcasts.Insert(broadcast, "snippet, status");
insertBroadcastRequest.Execute();
return broadcast;
}
I get an exception when calling insertBroadcastRequest.Execute(), namely:
Google.GoogleApiException was unhandled
HResult=-2146233088
Message=Google.Apis.Requests.RequestError
Insufficient Permission [403]
Errors [
Message[Insufficient Permission] Location[ - ] Reason[insufficientPermissions] Domain[global]
]
ServiceName=youtube
Source=Google.Apis
StackTrace:
at Google.Apis.Requests.ClientServiceRequest`1.Execute() in C:\Users\cloudsharp\Documents\GitHub\google-api-dotnet-client\Src\Support\GoogleApis\Apis\Requests\ClientServiceRequest.cs:line 96
at YoutubeConsole.YouTubeAPI.CreateImmediateStream(String title) in C:\Users\bussg\Source\Workspaces\OwnExperimental\YoutubeConsole\YoutubeConsole\YouTubeAPI.cs:line 87
at YoutubeConsole.YouTubeAPI.Test() in
...
Also, for completeness, here is my authorization,
using (var stream = new FileStream(Directory.GetCurrentDirectory() + #"\GoogleAuthOtherApplication.json", FileMode.Open, FileAccess.Read)) {
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { YouTubeService.Scope.YoutubeForceSsl},
"user",
CancellationToken.None,
new FileDataStore("YouTubeAPI")
).Result;
}
Also, For the YouTubeService.Scope I have tried all options. The insert method should work with ForceSsl according to the documentation.
Also this documentation page sais
Note: A channel must be approved to use the YouTube Live feature, which enables the channel owner to stream live content to that channel. If you send API requests on behalf of an authenticated user whose channel is not enabled or eligible to stream live content, the API will return an insufficientPermissions error.
But all my channels are approved for Youtube Live. Any ideas how to get this to work?
Ok after some testing between us over Email.
You need to have the correct scope "YouTubeService.Scope.YoutubeForceSsl" by changing "user" we forced it to request permissions again. My tutorial on how filedata store works in the Google .net client library
remove the space "snippet, status" by sending "snippet,status" it worked for me.
For the fun of it: Issue 8568:LiveBroadcasts: insert - spaces in part

YouTube Data API v3: deleting videos using a service account: Unauthorized client or scope in request

I'm trying to delete one or more videos using a simple C# app (I intend to use a Windows Service later) and I'm getting this error:
Google.Apis.Auth.OAuth2.Responses.TokenResponseException: Error:"unauthorized_client", Description:"Unauthorized client or scope in request.", Uri:""
at Google.Apis.Requests.ClientServiceRequest`1.Execute() in c:\code\google.com\google-api-dotnet-client\default\Tools\Google.Apis.Release\bin\Debug\test\default\Src\GoogleApis\Apis\Requests\ClientServiceRequest.cs:line 93
Uploading videos works perfectly. For both operations, I use the same initialization method:
private static YouTubeService AuthorizeYoutubeService()
{
string serviceAccountEmail = "...#developer.gserviceaccount.com";
string keyFilePath = "Warehouse<...>.p12";
string userAccountEmail = "login#gmail.com";
if (!File.Exists(keyFilePath))
{
System.Windows.Forms.MessageBox.Show("Secret file not found!");
return null;
}
var scope = new string[] { YouTubeService.Scope.Youtube };
var cert = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);
try
{
ServiceAccountCredential credential = new ServiceAccountCredential
(new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scope,
User = userAccountEmail
}.FromCertificate(cert));
var service = new YouTubeService(new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = "warehouse"
});
return service;
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
return null;
}
}
The difference compared to simply uploading videos, is the defined Scope: YouTubeService.Scope.YoutubeUpload. When I try to delete a video using it, I get an insufficientPermissions (403) error.
So after looking in the documentation I've changed it to YouTubeService.Scope.Youtube.
Here's the code I'm trying to use:
var youtubeService = AuthorizeYoutubeService();
foreach (string id in deleteIds)
{
var videoDeleteRequest = youtubeService.Videos.Delete(id);
var result = videoDeleteRequest.Execute();
}
Where deleteIds is a list of 11 character strings containing IDs of existing videos.
I have YouTube Data API enabled in the developers console.
I've installed the API via NuGet, I don't think there's anything wrong with the packages.
I'm quite new to Google development, and all similar questions were about the calendar API.
I appreciate any help.
What I ended up doing is reseting the list of apps connected to the Google account and setting it up again from scratch. My app was added 2 times for some reason.

Cannot upload to azure Blob Storage: The remote server returned an error: (400) Bad Request

I'm trying to create a utility to download file from the internet and upload it again to Azure blob storage.
Blob containers already created well; But for some reason i'm getting "Bad Request 400" exception when i tried to upload the file to storage ... Container name is created, small letters, so special characters. But I still do not know why i'm getting the exception!
Please help.
Note:
I'm not using any emulator ... Directly testing on the cloud.
All of my containers with "Public Container" access option.
Here is the exception:
An exception of type 'Microsoft.WindowsAzure.Storage.StorageException'
occurred in Microsoft.WindowsAzure.Storage.dll but was not handled in user code
Additional information: The remote server returned an error: (400) Bad Request.
And here is the code:
foreach (var obj in objectsList)
{
var containerName = obj.id.Replace("\"", "").Replace("_", "").Trim();
CloudBlobContainer blobContainer = blobClient.GetContainerReference(containerName);
if (blobContainer.Exists())
{
var fileNamesArr = obj.fileNames.Split(new char[] { '#' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var sora in fileNamesArr)
{
int soraInt = int.Parse(sora.Replace("\"", ""));
String fileName = String.Format("{0}.mp3", soraInt.ToString("000"));
var url = String.Format("http://{0}/{1}/{2}", obj.hostName.Replace("\"", ""), obj.id.Replace("\"", ""), fileName.Replace("\"", "")).ToLower();
var tempFileName = "temp.mp3";
var downloadedFilePath = Path.Combine(Path.GetTempPath(), tempFileName).ToLower();
var webUtil = new WebUtils(url);
await webUtil.DownloadAsync(url, downloadedFilePath).ContinueWith(task =>
{
var blobRef = blobContainer.GetBlockBlobReference(fileName.ToLower());
blobRef.Properties.ContentType = GetMimeType(downloadedFilePath);
using (var fs = new FileStream(downloadedFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
blobRef.UploadFromStream(fs); // <--- Exception
}
});
}
}
else
{
throw new Exception(obj.id.Replace("\"", "") + " Container not exist!");
}
}
Edit: The Storage Exception
Microsoft.WindowsAzure.Storage.StorageException: The remote server returned an error: (400) Bad Request. ---> System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
at System.Net.HttpWebRequest.GetRequestStream()
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand1 cmd, IRetryPolicy policy, OperationContext operationContext)
--- End of inner exception stack trace ---
at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand1 cmd, IRetryPolicy policy, OperationContext operationContext)
at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamHelper(Stream source, Nullable`1 length, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStream(Stream source, AccessCondition accessCondition, BlobRequestOptions options, OperationContext operationContext)
at TelawatAzureUtility.StorageService.<>c__DisplayClass4.b__12(Task task) in \psf\Home\Documents\Visual Studio 14\Projects\Telawat Azure Utility\TelawatAzureUtility\StorageService.cs:line 128
Request Information
RequestID:
RequestDate:Sat, 28 Jun 2014 20:12:14 GMT
StatusMessage:Bad Request
Edit 2: Request Information:
Edit 3: The problem comes from WebUtils .. I replaced it with below code and it works! I will add weUtils code, maybe you can help to know what is the problem with it.
HttpClient client = new HttpClient();
var stream = await client.GetStreamAsync(url);
WebUtils Code:
public class WebUtils
{
private Lazy<IWebProxy> proxy;
public WebUtils(String url)
{
proxy = new Lazy<IWebProxy>(() => string.IsNullOrEmpty(url) ? null : new WebProxy {
Address = new Uri(url), UseDefaultCredentials = true });
}
public IWebProxy Proxy
{
get { return proxy.Value; }
}
public Task DownloadAsync(string requestUri, string filename)
{
if (requestUri == null)
throw new ArgumentNullException("requestUri is missing!");
return DownloadAsync(new Uri(requestUri), filename);
}
public async Task DownloadAsync(Uri requestUri, string filename)
{
if (filename == null)
throw new ArgumentNullException("filename is missing!");
if (Proxy != null)
{
WebRequest.DefaultWebProxy = Proxy;
}
using (var httpClient = new HttpClient())
{
using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri))
{
using (Stream contentStream = await (await httpClient.SendAsync(request)).Content.ReadAsStreamAsync())
{
using (var stream = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
contentStream.CopyTo(stream);
stream.Flush();
stream.Close();
}
contentStream.Close();
}
}
}
}
}
Also when I tried this code ... the 'Wait' will never finish or completed!
webUtil.DownloadAsync(url, downloadedFilePath).Wait()
Have you tried creating a container manually on azure portal? It has some limitations on what name you can give containers.
For example: Container name cannot contain upper case letters.
If you request a container with an invalid name, it will result in (400) Bad Request, which you are getting. So check your "containerName" string.
I had the same problem. I resolved it by changing the TLS version in the configuration of the storage; the new TLS version (1.2) is not compatible with the older version of the storage client. I changed it to the 1.0 and it works.
The configuration of the storage is in the portal of Azure.
Storage -> Configuration -> TLS Version:
I also got this error with the Azure Storage Message Queues.
The Azure Storage Message Queue names must also be all lowercase.
ie: "newqueueitem" name in lowercase.
// Retrieve a reference to a queue.
CloudQueue queue = queueClient.GetQueueReference("newqueueitem");
// Create the queue if it doesn't already exist.
queue.CreateIfNotExists();
If you create a container with an invalid name, it will result in (400) Bad Request. There are some convention for creating container name as below:
Container names must start with a letter or number, and can contain only letters, numbers, and the dash (-) character.
Every dash (-) character must be immediately preceded and followed by a letter or number; consecutive dashes are not permitted in
container names.
All letters in a container name must be lowercase.
Container names must be from 3 through 63 characters long.
Source: https://learn.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata
I had a very different case of bad request message. Posting here for anyone else who may hit the same. In my case, I was just moving around resource across other resource groups . In that shuffling, a bug in azure allowed me to point my storage to location ("South East Asia") which was not available in my region. So all requests against the storage account returned the bad request message. It took me a while to figure this out because I then created another storage account to test, which when creating, azure did not allow me to pick "South East Asia" as a location of choice, so I picked another location ("East Asia") and then everything worked fine.
I know it's been a long time but I was able to fix it for TLS 1.2 with the following line of code:
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
It would be something like this :
public async Task DownloadAsync(Uri requestUri, string filename){
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
... your code...
}
I faced the same issue while creating the queue in Azure with one UpperCase Letter from my C# code. The error was with the Queue Name. All the characters should be lowercase. After changing all the characters to lowercase it worked! :)
//Retrieve a reference to a queue
CloudQueue queue = queueClient.GetQueueReference("myqueue");
//Create a queue if it alredy doen't exists
queue.CreateIfNotExists();

Categories