I'm using Googles official .NET library to access the reviews of my app (https://developers.google.com/android-publisher/api-ref/reviews/list is the corresponding API)
"Google.Apis.AndroidPublisher.v2": "1.16.0.594"
This is (roughly) my code:
var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer("client_email_from_service_account_json"
{
Scopes = new[] { AndroidPublisherService.Scope.Androidpublisher }
}.FromPrivateKey("private_key_from_service_account_json"));
var service = new AndroidPublisherService(new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = "some_name",
});
var request = service.Reviews.List("my_app_id");
using (var reader = new StreamReader(request.ExecuteAsStream()))
{
var json = reader.ReadToEnd();
// json is only "{}\n"
}
var requestResult = await request.ExecuteAsync();
// requestResult.Reviews is null
I get the same (empty) result when I take the access_token from credential and to the HTTP GET call manually.
There is no error, so access should be working correctly - but I only ever get an empty JSON object.
When I try to access a specific review via its ID, it works fine (again, not pointing to an access problem).
According to https://github.com/google/google-api-nodejs-client/issues/589 the reviews API only returns reviews posted in the last 7 days.
Related
I've recently started working as a junior c# developer. My boss asked me to build methods to CRUD teams in our AAD using the microsoft graph API. I've achieved this with a test application like that:
public async Task<string> createTeam()
{
// readying data from registry
var clientId = "********************"; //application (client) ID
var clientSecret = "********************";
var redirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient";
var authority = "https://login.microsoftonline.com/********************/v2.0";
var cca = ConfidentialClientApplicationBuilder.Create(clientId)
.WithAuthority(authority)
.WithRedirectUri(redirectUri)
.WithClientSecret(clientSecret)
.Build();
List<string> scopes = new List<string>
{
"https://graph.microsoft.com/.default"
};
//
var authenticationProvider = new MsalAuthenticationProvider(cca, scopes.ToArray());
//
GraphServiceClient graphClient = new GraphServiceClient(authenticationProvider);
// Code to create a Team
var team = new Team
{
DisplayName = "0000My Sample Team",
Description = "My Sample Team’s Description",
AdditionalData = new Dictionary<string, object>()
{
{"template#odata.bind", "https://graph.microsoft.com/v1.0/teamsTemplates('standard')"}
}
};
var result = await graphClient.Teams.Request().AddAsync(team);
return result.DisplayName;
}
With that piece of code working, I've created an asp.net web Application (.net framework) and added the class to it. The plan was to deploy it to an IIS server and and publish the methods as web services.
[WebMethod]
public async Task<string> createTeamAsync()
{
//The class where my methods reside
TeamServices ts = new TeamServices();
var result = await ts.createTeam();
return "OK";
}
I registered the app and deployed but when I try to use it, it does not create any Team.
Do you know what I'm doing wrong of what I should learn next get the app working? Im just a few weeks in c# and I'm completely lost in all that .net echosystem
Thanks in advance
I want to tried to get youtube live broadcast id. But I can't get this.
Here is my code:
UserCredential credential;
Response.Write("AAA");
var stream2 = new FileStream("c:/users/gislap/documents/visual studio 2012/Projects/youtube/secrect.json", FileMode.Open, FileAccess.Read);
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream2).Secrets,
new[] { YouTubeService.Scope.Youtube },
"user",
CancellationToken.None,
new FileDataStore(this.GetType().ToString())
);
Response.Write("DDD");
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = this.GetType().ToString()
});
var my_video_request = youtubeService.LiveBroadcasts.ToString();
Label1.Text = my_video_request.ToString();
Or any way to get all videos list?
You may refer on this thread. If you want to retrieve information on another channel's current live broadcasts, you have to use the standard Search/list endpoint:
part -> snippet
channelId -> [channelId of the channel/user with the live event]
eventType -> live
type -> video (required when setting eventType to live)
HTTP GET https://www.googleapis.com/youtube/v3/search?part=snippet&channelId={channelId}&eventType=live&type=video&key={YOUR_API_KEY}
Also, based from this documentation, try to use this HTTP request to return a list of YouTube broadcasts that match the API request parameters.
GET https://www.googleapis.com/youtube/v3/liveBroadcasts
Here are examples which might help:
https://developers.google.com/youtube/v3/live/code_samples/
https://github.com/search?l=C%23&q=LiveBroadcasts&type=Code&utf8=%E2%9C%93
I'm trying to download a caption track using YouTube API v3 (https://developers.google.com/youtube/v3/docs/captions/download) and official .NET SDK nuget package (https://www.nuget.org/packages/Google.Apis.YouTube.v3/, version 1.9.0.1360).
Returned stream contains the following text:
"The OAuth token was received in the query string, which this API forbids for response formats other than JSON or XML. If possible, try sending the OAuth token in the Authorization header instead."
instead of the SRT plain text content which I just uploaded and verified manually through YouTube.com UI.
I found the type of error: lockedDomainCreationFailure
My code:
...
_service = new YTApi.YouTubeService(new BaseClientService.Initializer {
ApplicationName = config.AppName,
ApiKey = config.DeveloperKey
});
...
public Stream CaptionsDownload(
string accessToken,
string trackId
)
{
var request = _service.Captions.Download(trackId);
request.OauthToken = accessToken;
request.Tfmt = YTApi.CaptionsResource.DownloadRequest.TfmtEnum.Srt;
var trackStream = new MemoryStream();
request.Download(trackStream);
trackStream.Position = 0;
return trackStream;
}
I cannot seem to find the way to set any headers on _service.HttpClient, and I guess I shouldn't do it manually. I expect that DownloadRequest (or YouTubeBaseServiceRequest) will put
/// <summary>
/// OAuth 2.0 token for the current user.
/// </summary>
[RequestParameter("oauth_token", RequestParameterType.Query)]
public virtual string OauthToken { get; set; }
into a correct authorization header. I don't see this implemented in the version 1.9.0.1360.
Maybe I'm overlooking something? Any help is greatly appreciated.
Note: I use other caption-related methods with this SDK, and 'download' is the only one I'm having a trouble with.
You initialed the service WITHOUT the user credential (you only used the API key). Take a look in one of the samples in our developers guide, (and pick the right flow... are you using installed application, windows phone, etc.?)
You will have to change the way you create your service to do something like the following:
UserCredential credential;
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { YoutubeService.Scope.<THE_RIGHT_SCOPE_HERE> },
"user", CancellationToken.None);
}
// Create the service.
_service = new YouTubeService(new BaseClientService.Initializer {
ApplicationName = config.AppName,
HttpClientInitializer = credential,
ApplicationName = "Books API Sample",
});
Then, for each request to the youtube service, your OAuth access token will be included as an additional header on the HTTP request itself.
Perhaps I am the only one that thinks Google's API documentation is awful but I've spent more time on this simple task than I wanted.
Currently my project is using a GDATA implementation to connect with the Google Calendar API v2. I followed this guide: http://www.codeproject.com/Articles/565032/Google-Calendar-Integration-in-ASP-NET-Create-ed
But I noticed that Google is deprecating version 2 of their API this fall. I am trying to figure out how I can connect to their version 3 API which appears to be using OAuth2.
After reading their documentation and searching the internet >:( - The problem I keep running into is EVERY sample, tutorial or youtube video I've come across that shows how to implement this involve the Google consent screen where the user clicks "Accept".
I've tried doing the following but honestly not sure if it's even the right direction?
// Register the authenticator. The Client ID and secret have to be copied from the API Access
// tab on the Google APIs Console.
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = "MY_CLIENT_ID";
provider.ClientSecret = "MY_CLIENT_SECRET";
// Create the service. This will automatically call the previously registered authenticator.
var service = new CalendarService();
My application doesn't need the user's account/consent (OAuth), I need to connect like I am currently in my code-behind.
So the question is how do I "upgrade" my current implementation to v3? Do I use OAuth, Service Account? I've found plenty of examples showing the v3 usages for how to retrieve events and insert them... but they all authenticate with a user consent screen on the front end.
Here is my current GData implementation...
public class GoogleGateway : IGoogleGateway
{
private readonly IRepository<UserSetting> _settingsRepository;
private Service _googleService;
private CalendarService _googleCalendar;
private Uri _calendarUri;
public GoogleGateway(IRepository<UserSetting> settingsRepository)
{
_settingsRepository = settingsRepository;
}
public IEnumerable<EventEntry> GetAllEvents(DateTime? startDate)
{
if (!Connect()) return new List<EventEntry>();
// Create the query object:
EventQuery query = new EventQuery();
query.Uri = _calendarUri;
if (startDate != null)
query.StartTime = startDate.Value;
// Tell the service to query:
EventFeed calFeed = _googleCalendar.Query(query);
return calFeed.Entries.Cast<EventEntry>();
}
public bool Connect()
{
var calSettings = _settingsRepository.Get().Where(x => x.Setting == "Calendar");
if (calSettings.Any())
{
var username = calSettings.First(x => x.Meta == "GoogleUsername").Value;
var password = calSettings.First(x => x.Meta == "GooglePassword").Value;
var calendarUri = new Uri(calSettings.First(x => x.Meta == "CalendarFeed").Value);
var applicationName = calSettings.First(x => x.Meta == "ApplicationName").Value;
_calendarUri = calendarUri;
//FeedQuery feedQuery = new FeedQuery();
_googleService = new Service("cl", applicationName);
_googleCalendar = new CalendarService(applicationName);
// Set your credentials:
_googleService.setUserCredentials(username, password);
_googleCalendar.setUserCredentials(username, password);
return true;
}
return false;
}
public void AddEvent(string title, string contents, string location, DateTime startTime, DateTime endTime)
{
if (!Connect()) return;
EventEntry.EVENT_CATEGORY = new AtomCategory("Appointments");
EventEntry entry = new EventEntry
{
Title = { Text = title },
Content = { Content = contents },
};
// Set the title and content of the entry.
// Set a location for the event.
Where eventLocation = new Where();
eventLocation.ValueString = location;
entry.Locations.Add(eventLocation);
When eventTime = new When(startTime, endTime);
entry.Times.Add(eventTime);
Uri postUri = new Uri("http://www.google.com/calendar/feeds/default/private/full");
// Send the request and receive the response:
AtomEntry insertedEntry = _googleCalendar.Insert(postUri, entry);
}
public void DeleteEvent(string eventId)
{
if (!Connect()) return;
var events = GetAllEvents(null);
var appointment = events.First(x => x.EventId == eventId);
_googleService.Delete(appointment);
}
}
I'm growing desperate at this point, any help would be very appreciated. Include your twitter handle in your answer and I'll buy you a coffee!
UPDATED
I currently have the following, but I is still not authenticating... :(
static CalendarService BuildService()
{
String serviceAccountEmail = "xxxxxxxxxxxxx-31xxxxxxxxxxxxxxxxxxx#developer.gserviceaccount.com";
var certPath = HttpContext.Current.Server.MapPath("/xxxxxxxxxxxx.p12");
var certificate = new X509Certificate2(certPath, "notasecret", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { CalendarService.Scope.Calendar }
}.FromCertificate(certificate));
// Create the service.
var service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential, <<<<<< DOES NOT RESOLVE!
ApplicationName = "MyApplication",
});
var test = service.Calendars.Get("xxxxxxxxxxxxxxxxxx#group.calendar.google.com");
return service;
}
The problem is that you are storing credentials in plaintext. In Oauth2 the users won't give you their credentials (thus access to everything) but instead they enable your app to access the data of a specific type / scope.
It's not clear from your description whether you only ever access one calendar fully in your control or you have multiple users. In the first case the answer would be use service account (https://developers.google.com/accounts/docs/OAuth2ServiceAccount). In the second case if you are a calendar app with many users, you will need to go down the user consent road and you should read on :)
For offline access you can specify that the access_type should be offline when retrieving the credentials for the first time. Together with the access token you'll also get a refresh token, which you can use to re-authenticate at any later time without any more user clicks (https://developers.google.com/accounts/docs/OAuth2WebServer#refresh). However, at least one consent screen it is.
In the authorization stage of my application I'm requesting access via:
var req = new Google.Apis.Auth.OAuth2.Requests.GoogleAuthorizationCodeRequestUrl(new Uri(string.Format(Settings.Google.OAuth.Url, "auth")));
req.ClientId = Settings.Google.OAuth.ClientId;
req.ResponseType = "code";
req.Scope = "https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtubepartner";
req.RedirectUri = string.Format(Settings.Integration.HandshakeUrl, "youtube");
req.AccessType = "offline"; // required to get refreshToken.
req.ApprovalPrompt = "force";
req.State = Application.Cryptography.Encrypt(Application.JSON.SerializeToString<State>(new State { UID = userId, PROFILEID = profileId, SUCCESS = request.SuccessUrl, FAIL = request.FailUrl }), Settings.Cryptography.SymetricKey);
// Return the url that the requesting application should redirect to in order to perform the authorization.
return req.Build().ToString();
This successfully gets me an access token and refresh token. Now I wanted to insert a new stream based on the information in the google api docs
var token = new Google.Apis.Auth.OAuth2.Responses.TokenResponse { RefreshToken = refreshToken, AccessToken = accessToken };
var credentials = new UserCredential(new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = "<id>",
ClientSecret = "<secret>",
}
}), string.Empty, token);
var service = new YouTubeService(new BaseClientService.Initializer
{
HttpClientInitializer = credentials
});
var streamResource = new LiveStreamsResource(service);
var result = streamResource.Insert(new LiveStream
{
Snippet = new LiveStreamSnippet
{
Title = "Stream"
},
Cdn = new CdnSettings
{
Format = "1080p",
IngestionType = "rtmp"
}
}, "id, snippet, cdn, status");
var returnedStream = result.Execute();
When this runs Execute() gives the following exception:
Google.Apis.Requests.RequestError
Request is not authorized [403]
Errors [
Message[Request is not authorized] Location[ - ] Reason[insufficientLivePermissions] Domain[youtube.liveStream]
]
I can't figure out what I'm doing wrong in this process. Even the API explorer
Apparently, I was looking at this all wrong (and Google's API documentation should really describe this).
The response isn't that I don't have access to the proper scopes, it's that even though I was authorizing myself for the youtube scope, my youtube account did not have live streams enabled (separate option).
After enabling live streaming on my account this code worked properly.