Skip to content
This repository has been archived by the owner on Apr 8, 2024. It is now read-only.

Commit

Permalink
Merge pull request #318 from aspriddell/update-dragonfruit-data
Browse files Browse the repository at this point in the history
Update data library
  • Loading branch information
aspriddell authored Jul 2, 2022
2 parents 741cf0b + 1c32928 commit 050c575
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@

using DragonFruit.Data;
using DragonFruit.Data.Extensions;
using DragonFruit.Data.Requests;
using DragonFruit.Six.Api.Enums;

namespace DragonFruit.Six.Api.Accounts.Requests
{
public class UbisoftGeolocationRequest : ApiRequest
public class UbisoftGeolocationRequest : ApiRequest, IRequestExecutingCallback
{
public override string Path => $"{Endpoints.BaseEndpoint}/v2/profiles/me/iplocation";

protected override void OnRequestExecuting(ApiClient client)
void IRequestExecutingCallback.OnRequestExecuting(ApiClient client)
{
if (client is not Dragon6Client)
{
Expand Down
14 changes: 8 additions & 6 deletions DragonFruit.Six.Api/Dragon6Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
using DragonFruit.Six.Api.Enums;
using DragonFruit.Six.Api.Exceptions;
using DragonFruit.Six.Api.Legacy.Utils;
using Nito.AsyncEx;

namespace DragonFruit.Six.Api
{
public abstract class Dragon6Client : ApiClient<ApiJsonSerializer>
{
private ClientAccessToken _access;
private readonly object _accessSync = new();
private readonly AsyncLock _accessSync = new();

protected Dragon6Client(string userAgent = null, UbisoftService app = UbisoftService.RainbowSix)
{
Expand All @@ -38,7 +39,7 @@ static Dragon6Client()
/// <remarks>
/// It is recommended to store the token to a file and try to retrieve from there before resorting to the online systems, as accounts can be blocked due to rate-limits
/// </remarks>
protected abstract IUbisoftToken GetToken();
protected abstract ValueTask<IUbisoftToken> GetToken();

/// <summary>
/// Updates the Ubi-AppId header to be supplied to each request.
Expand All @@ -64,19 +65,20 @@ static Dragon6Client()
_ => base.ValidateAndProcess<T>(response)
};

protected internal ClientAccessToken RequestAccessToken()
protected internal async ValueTask<ClientAccessToken> RequestAccessToken()
{
if (_access?.Expired is false)
{
return _access;
}

lock (_accessSync)
using (await _accessSync.LockAsync().ConfigureAwait(false))
{
// check again in case of a backlog of requests
// check again in case of a backlog
if (_access?.Expired is not false)
{
_access = new ClientAccessToken(GetToken());
var token = await GetToken().ConfigureAwait(false);
_access = new ClientAccessToken(token);
}

return _access;
Expand Down
5 changes: 3 additions & 2 deletions DragonFruit.Six.Api/DragonFruit.Six.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="DragonFruit.Data" Version="2022.324.0" />
<PackageReference Include="DragonFruit.Data.Serializers.Newtonsoft" Version="2022.324.0" />
<PackageReference Include="DragonFruit.Data" Version="2022.702.0" />
<PackageReference Include="DragonFruit.Data.Serializers.Newtonsoft" Version="2022.702.0" />
<PackageReference Include="JetBrains.Annotations" Version="2022.1.0" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
// Dragon6 API Copyright DragonFruit Network <[email protected]>
// Licensed under Apache-2. Refer to the LICENSE file for more info

using System.Threading.Tasks;
using DragonFruit.Data;
using DragonFruit.Data.Extensions;
using DragonFruit.Data.Requests;

namespace DragonFruit.Six.Api.Services.Developer
{
public abstract class Dragon6DeveloperApiRequest : ApiRequest
public abstract class Dragon6DeveloperApiRequest : ApiRequest, IAsyncRequestExecutingCallback
{
protected override bool RequireAuth => true;

protected override void OnRequestExecuting(ApiClient client)
async ValueTask IAsyncRequestExecutingCallback.OnRequestExecutingAsync(ApiClient client)
{
// get access token if using a developer client
if (client is Dragon6DeveloperClient devClient)
{
this.WithAuthHeader($"Bearer {devClient.RequestDragonFruitAccessToken().AccessToken}");
var token = await devClient.RequestDragonFruitAccessToken().ConfigureAwait(false);
this.WithAuthHeader($"Bearer {token.AccessToken}");
}
}
}
Expand Down
20 changes: 14 additions & 6 deletions DragonFruit.Six.Api/Services/Developer/Dragon6DeveloperClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
// Licensed under Apache-2. Refer to the LICENSE file for more info

using System;
using System.Threading.Tasks;
using DragonFruit.Six.Api.Authentication.Entities;
using Nito.AsyncEx;

namespace DragonFruit.Six.Api.Services.Developer
{
public class Dragon6DeveloperClient : Dragon6Client
{
private readonly object _accessSync = new();
private DragonFruitClientCredentials _access;

private readonly AsyncLock _accessSync = new();
private readonly string _clientId, _clientSecret, _scopes;

public Dragon6DeveloperClient(string clientId, string clientSecret, string scopes)
Expand All @@ -19,25 +22,30 @@ public Dragon6DeveloperClient(string clientId, string clientSecret, string scope
_scopes = scopes;
}

protected override IUbisoftToken GetToken() => Perform<Dragon6Token>(new Dragon6TokenRequest());
protected override async ValueTask<IUbisoftToken> GetToken()
{
return await PerformAsync<Dragon6Token>(new Dragon6TokenRequest()).ConfigureAwait(false);
}

internal DragonFruitClientCredentials RequestDragonFruitAccessToken()
internal async ValueTask<DragonFruitClientCredentials> RequestDragonFruitAccessToken()
{
if (_access?.ExpiresUtc > DateTime.UtcNow)
{
return _access;
}

lock (_accessSync)
using (await _accessSync.LockAsync().ConfigureAwait(false))
{
if (_access is null || _access.ExpiresUtc <= DateTime.UtcNow)
{
_access = Perform<DragonFruitClientCredentials>(new DragonFruitClientCredentialsRequest
var request = new DragonFruitClientCredentialsRequest
{
ClientId = _clientId,
ClientSecret = _clientSecret,
Scopes = _scopes
});
};

_access = await PerformAsync<DragonFruitClientCredentials>(request).ConfigureAwait(false);
}

return _access;
Expand Down
12 changes: 9 additions & 3 deletions DragonFruit.Six.Api/UbiApiRequest.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Dragon6 API Copyright DragonFruit Network <[email protected]>
// Licensed under Apache-2. Refer to the LICENSE file for more info

using System.Threading.Tasks;
using DragonFruit.Data;
using DragonFruit.Data.Requests;

#nullable enable

Expand All @@ -11,15 +13,19 @@ namespace DragonFruit.Six.Api
/// Represents a Ubisoft API request that requires authentication.
/// Supports header injection via a <see cref="Dragon6Client"/>
/// </summary>
public abstract class UbiApiRequest : ApiRequest
public abstract class UbiApiRequest : ApiRequest, IAsyncRequestExecutingCallback
{
protected override bool RequireAuth => true;

protected override void OnRequestExecuting(ApiClient client)
async ValueTask IAsyncRequestExecutingCallback.OnRequestExecutingAsync(ApiClient client)
{
// all ubisoft api requests need authentication
// the Dragon6Client caches auth tokens and allows the headers to be injected
(client as Dragon6Client)?.RequestAccessToken().Inject(this);
if (client is Dragon6Client d6Client)
{
var token = await d6Client.RequestAccessToken().ConfigureAwait(false);
token.Inject(this);
}
}
}
}

0 comments on commit 050c575

Please sign in to comment.