diff --git a/CHANGELOG.md b/CHANGELOG.md
index e4fe9c89..452e8bd0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,9 +4,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
-## [Unreleased]
+## [3.8.0]
+### Added
+- Nakama: Added `Authoritative` flag to tournaments returned from the server.
+- Nakama: Added `RefundTime` and `UserId` to purchases and subscriptions returned from the server.
+- Nakama: Added raw subscription provider information.
+- Nakama: Added `DeleteAccountAsync` for deleting user accounts.
+- Satori: Added `DeleteIdentityAsync` for deleting user identities.
+
### Changed
-- Nakama: Use `session.Username` wherever outdated state might be returned.
+- Nakama: Used `session.Username` wherever outdated state might be returned.
+
+### Fixed
+- Nakama: Fixed issue where outgoing payloads could include unnecessary JSON.
+
## [3.7.0]
### Added
diff --git a/Nakama/ApiClient.gen.cs b/Nakama/ApiClient.gen.cs
index 37e586ca..ad1c921c 100644
--- a/Nakama/ApiClient.gen.cs
+++ b/Nakama/ApiClient.gen.cs
@@ -7,7 +7,7 @@ namespace Nakama
using System.Text;
using System.Threading;
using System.Threading.Tasks;
- using Nakama.TinyJson;
+ using TinyJson;
///
/// An exception generated for HttpResponse objects don't return a success status.
@@ -134,6 +134,7 @@ internal class GroupUserListGroupUser : IGroupUserListGroupUser
public int State { get; set; }
///
+ [IgnoreDataMember]
public IApiUser User => _user;
[DataMember(Name="user"), Preserve]
public ApiUser _user { get; set; }
@@ -169,6 +170,7 @@ internal class UserGroupListUserGroup : IUserGroupListUserGroup
{
///
+ [IgnoreDataMember]
public IApiGroup Group => _group;
[DataMember(Name="group"), Preserve]
public ApiGroup _group { get; set; }
@@ -222,6 +224,7 @@ internal class WriteLeaderboardRecordRequestLeaderboardRecordWrite : IWriteLeade
public string Metadata { get; set; }
///
+ [IgnoreDataMember]
public ApiOperator Operator => _operator;
[DataMember(Name="operator"), Preserve]
public ApiOperator _operator { get; set; }
@@ -281,6 +284,7 @@ internal class WriteTournamentRecordRequestTournamentRecordWrite : IWriteTournam
public string Metadata { get; set; }
///
+ [IgnoreDataMember]
public ApiOperator Operator => _operator;
[DataMember(Name="operator"), Preserve]
public ApiOperator _operator { get; set; }
@@ -355,6 +359,7 @@ internal class ApiAccount : IApiAccount
public string CustomId { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable Devices => _devices ?? new List(0);
[DataMember(Name="devices"), Preserve]
public List _devices { get; set; }
@@ -368,6 +373,7 @@ internal class ApiAccount : IApiAccount
public string Email { get; set; }
///
+ [IgnoreDataMember]
public IApiUser User => _user;
[DataMember(Name="user"), Preserve]
public ApiUser _user { get; set; }
@@ -420,6 +426,7 @@ internal class ApiAccountApple : IApiAccountApple
public string Token { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Vars => _vars ?? new Dictionary();
[DataMember(Name="vars"), Preserve]
public Dictionary _vars { get; set; }
@@ -465,6 +472,7 @@ internal class ApiAccountCustom : IApiAccountCustom
public string Id { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Vars => _vars ?? new Dictionary();
[DataMember(Name="vars"), Preserve]
public Dictionary _vars { get; set; }
@@ -510,6 +518,7 @@ internal class ApiAccountDevice : IApiAccountDevice
public string Id { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Vars => _vars ?? new Dictionary();
[DataMember(Name="vars"), Preserve]
public Dictionary _vars { get; set; }
@@ -564,6 +573,7 @@ internal class ApiAccountEmail : IApiAccountEmail
public string Password { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Vars => _vars ?? new Dictionary();
[DataMember(Name="vars"), Preserve]
public Dictionary _vars { get; set; }
@@ -610,6 +620,7 @@ internal class ApiAccountFacebook : IApiAccountFacebook
public string Token { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Vars => _vars ?? new Dictionary();
[DataMember(Name="vars"), Preserve]
public Dictionary _vars { get; set; }
@@ -655,6 +666,7 @@ internal class ApiAccountFacebookInstantGame : IApiAccountFacebookInstantGame
public string SignedPlayerInfo { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Vars => _vars ?? new Dictionary();
[DataMember(Name="vars"), Preserve]
public Dictionary _vars { get; set; }
@@ -745,6 +757,7 @@ internal class ApiAccountGameCenter : IApiAccountGameCenter
public string TimestampSeconds { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Vars => _vars ?? new Dictionary();
[DataMember(Name="vars"), Preserve]
public Dictionary _vars { get; set; }
@@ -795,6 +808,7 @@ internal class ApiAccountGoogle : IApiAccountGoogle
public string Token { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Vars => _vars ?? new Dictionary();
[DataMember(Name="vars"), Preserve]
public Dictionary _vars { get; set; }
@@ -840,6 +854,7 @@ internal class ApiAccountSteam : IApiAccountSteam
public string Token { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Vars => _vars ?? new Dictionary();
[DataMember(Name="vars"), Preserve]
public Dictionary _vars { get; set; }
@@ -1043,6 +1058,7 @@ internal class ApiChannelMessageList : IApiChannelMessageList
public string CacheableCursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable Messages => _messages ?? new List(0);
[DataMember(Name="messages"), Preserve]
public List _messages { get; set; }
@@ -1209,6 +1225,7 @@ internal class ApiDeleteStorageObjectsRequest : IApiDeleteStorageObjectsRequest
{
///
+ [IgnoreDataMember]
public IEnumerable ObjectIds => _objectIds ?? new List(0);
[DataMember(Name="object_ids"), Preserve]
public List _objectIds { get; set; }
@@ -1261,6 +1278,7 @@ internal class ApiEvent : IApiEvent
public string Name { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Properties => _properties ?? new Dictionary();
[DataMember(Name="properties"), Preserve]
public Dictionary _properties { get; set; }
@@ -1321,6 +1339,7 @@ internal class ApiFriend : IApiFriend
public string UpdateTime { get; set; }
///
+ [IgnoreDataMember]
public IApiUser User => _user;
[DataMember(Name="user"), Preserve]
public ApiUser _user { get; set; }
@@ -1361,6 +1380,7 @@ internal class ApiFriendList : IApiFriendList
public string Cursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable Friends => _friends ?? new List(0);
[DataMember(Name="friends"), Preserve]
public List _friends { get; set; }
@@ -1538,6 +1558,7 @@ internal class ApiGroupList : IApiGroupList
public string Cursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable Groups => _groups ?? new List(0);
[DataMember(Name="groups"), Preserve]
public List _groups { get; set; }
@@ -1577,6 +1598,7 @@ internal class ApiGroupUserList : IApiGroupUserList
public string Cursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable GroupUsers => _groupUsers ?? new List(0);
[DataMember(Name="group_users"), Preserve]
public List _groupUsers { get; set; }
@@ -1764,6 +1786,7 @@ internal class ApiLeaderboardRecordList : IApiLeaderboardRecordList
public string NextCursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable OwnerRecords => _ownerRecords ?? new List(0);
[DataMember(Name="owner_records"), Preserve]
public List _ownerRecords { get; set; }
@@ -1773,6 +1796,7 @@ internal class ApiLeaderboardRecordList : IApiLeaderboardRecordList
public string PrevCursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable Records => _records ?? new List(0);
[DataMember(Name="records"), Preserve]
public List _records { get; set; }
@@ -1810,6 +1834,7 @@ internal class ApiLinkSteamRequest : IApiLinkSteamRequest
{
///
+ [IgnoreDataMember]
public IApiAccountSteam Account => _account;
[DataMember(Name="account"), Preserve]
public ApiAccountSteam _account { get; set; }
@@ -1960,6 +1985,7 @@ internal class ApiMatchList : IApiMatchList
{
///
+ [IgnoreDataMember]
public IEnumerable Matches => _matches ?? new List(0);
[DataMember(Name="matches"), Preserve]
public List _matches { get; set; }
@@ -2086,6 +2112,7 @@ internal class ApiNotificationList : IApiNotificationList
public string CacheableCursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable Notifications => _notifications ?? new List(0);
[DataMember(Name="notifications"), Preserve]
public List _notifications { get; set; }
@@ -2191,6 +2218,7 @@ internal class ApiReadStorageObjectsRequest : IApiReadStorageObjectsRequest
{
///
+ [IgnoreDataMember]
public IEnumerable ObjectIds => _objectIds ?? new List(0);
[DataMember(Name="object_ids"), Preserve]
public List _objectIds { get; set; }
@@ -2363,6 +2391,7 @@ internal class ApiSessionRefreshRequest : IApiSessionRefreshRequest
public string Token { get; set; }
///
+ [IgnoreDataMember]
public IDictionary Vars => _vars ?? new Dictionary();
[DataMember(Name="vars"), Preserve]
public Dictionary _vars { get; set; }
@@ -2565,6 +2594,7 @@ internal class ApiStorageObjectAcks : IApiStorageObjectAcks
{
///
+ [IgnoreDataMember]
public IEnumerable Acks => _acks ?? new List(0);
[DataMember(Name="acks"), Preserve]
public List _acks { get; set; }
@@ -2603,6 +2633,7 @@ internal class ApiStorageObjectList : IApiStorageObjectList
public string Cursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable Objects => _objects ?? new List(0);
[DataMember(Name="objects"), Preserve]
public List _objects { get; set; }
@@ -2633,6 +2664,7 @@ internal class ApiStorageObjects : IApiStorageObjects
{
///
+ [IgnoreDataMember]
public IEnumerable Objects => _objects ?? new List(0);
[DataMember(Name="objects"), Preserve]
public List _objects { get; set; }
@@ -2718,6 +2750,7 @@ internal class ApiSubscriptionList : IApiSubscriptionList
public string PrevCursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable ValidatedSubscriptions => _validatedSubscriptions ?? new List(0);
[DataMember(Name="validated_subscriptions"), Preserve]
public List _validatedSubscriptions { get; set; }
@@ -2738,6 +2771,11 @@ public override string ToString()
public interface IApiTournament
{
+ ///
+ /// Whether the leaderboard was created authoritatively or not.
+ ///
+ bool Authoritative { get; }
+
///
/// True if the tournament is active and can enter. A computed value.
///
@@ -2838,6 +2876,10 @@ public interface IApiTournament
internal class ApiTournament : IApiTournament
{
+ ///
+ [DataMember(Name="authoritative"), Preserve]
+ public bool Authoritative { get; set; }
+
///
[DataMember(Name="can_enter"), Preserve]
public bool CanEnter { get; set; }
@@ -2887,6 +2929,7 @@ internal class ApiTournament : IApiTournament
public int NextReset { get; set; }
///
+ [IgnoreDataMember]
public ApiOperator Operator => _operator;
[DataMember(Name="operator"), Preserve]
public ApiOperator _operator { get; set; }
@@ -2918,6 +2961,7 @@ internal class ApiTournament : IApiTournament
public override string ToString()
{
var output = "";
+ output = string.Concat(output, "Authoritative: ", Authoritative, ", ");
output = string.Concat(output, "CanEnter: ", CanEnter, ", ");
output = string.Concat(output, "Category: ", Category, ", ");
output = string.Concat(output, "CreateTime: ", CreateTime, ", ");
@@ -2967,6 +3011,7 @@ internal class ApiTournamentList : IApiTournamentList
public string Cursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable Tournaments => _tournaments ?? new List(0);
[DataMember(Name="tournaments"), Preserve]
public List _tournaments { get; set; }
@@ -3016,6 +3061,7 @@ internal class ApiTournamentRecordList : IApiTournamentRecordList
public string NextCursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable OwnerRecords => _ownerRecords ?? new List(0);
[DataMember(Name="owner_records"), Preserve]
public List _ownerRecords { get; set; }
@@ -3025,6 +3071,7 @@ internal class ApiTournamentRecordList : IApiTournamentRecordList
public string PrevCursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable Records => _records ?? new List(0);
[DataMember(Name="records"), Preserve]
public List _records { get; set; }
@@ -3342,6 +3389,7 @@ internal class ApiUserGroupList : IApiUserGroupList
public string Cursor { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable UserGroups => _userGroups ?? new List(0);
[DataMember(Name="user_groups"), Preserve]
public List _userGroups { get; set; }
@@ -3372,6 +3420,7 @@ internal class ApiUsers : IApiUsers
{
///
+ [IgnoreDataMember]
public IEnumerable Users => _users ?? new List(0);
[DataMember(Name="users"), Preserve]
public List _users { get; set; }
@@ -3525,6 +3574,7 @@ internal class ApiValidatePurchaseResponse : IApiValidatePurchaseResponse
{
///
+ [IgnoreDataMember]
public IEnumerable ValidatedPurchases => _validatedPurchases ?? new List(0);
[DataMember(Name="validated_purchases"), Preserve]
public List _validatedPurchases { get; set; }
@@ -3630,6 +3680,7 @@ internal class ApiValidateSubscriptionResponse : IApiValidateSubscriptionRespons
{
///
+ [IgnoreDataMember]
public IApiValidatedSubscription ValidatedSubscription => _validatedSubscription;
[DataMember(Name="validated_subscription"), Preserve]
public ApiValidatedSubscription _validatedSubscription { get; set; }
@@ -3649,7 +3700,7 @@ public interface IApiValidatedPurchase
{
///
- /// UNIX Timestamp when the receipt validation was stored in DB.
+ /// Timestamp when the receipt validation was stored in DB.
///
string CreateTime { get; }
@@ -3669,10 +3720,15 @@ public interface IApiValidatedPurchase
string ProviderResponse { get; }
///
- /// UNIX Timestamp when the purchase was done.
+ /// Timestamp when the purchase was done.
///
string PurchaseTime { get; }
+ ///
+ /// Timestamp when the purchase was refunded. Set to UNIX
+ ///
+ string RefundTime { get; }
+
///
/// Whether the purchase had already been validated by Nakama before.
///
@@ -3689,9 +3745,14 @@ public interface IApiValidatedPurchase
string TransactionId { get; }
///
- /// UNIX Timestamp when the receipt validation was updated in DB.
+ /// Timestamp when the receipt validation was updated in DB.
///
string UpdateTime { get; }
+
+ ///
+ /// Purchase User ID.
+ ///
+ string UserId { get; }
}
///
@@ -3703,6 +3764,7 @@ internal class ApiValidatedPurchase : IApiValidatedPurchase
public string CreateTime { get; set; }
///
+ [IgnoreDataMember]
public ApiStoreEnvironment Environment => _environment;
[DataMember(Name="environment"), Preserve]
public ApiStoreEnvironment _environment { get; set; }
@@ -3719,11 +3781,16 @@ internal class ApiValidatedPurchase : IApiValidatedPurchase
[DataMember(Name="purchase_time"), Preserve]
public string PurchaseTime { get; set; }
+ ///
+ [DataMember(Name="refund_time"), Preserve]
+ public string RefundTime { get; set; }
+
///
[DataMember(Name="seen_before"), Preserve]
public bool SeenBefore { get; set; }
///
+ [IgnoreDataMember]
public ApiStoreProvider Store => _store;
[DataMember(Name="store"), Preserve]
public ApiStoreProvider _store { get; set; }
@@ -3736,6 +3803,10 @@ internal class ApiValidatedPurchase : IApiValidatedPurchase
[DataMember(Name="update_time"), Preserve]
public string UpdateTime { get; set; }
+ ///
+ [DataMember(Name="user_id"), Preserve]
+ public string UserId { get; set; }
+
public override string ToString()
{
var output = "";
@@ -3744,10 +3815,12 @@ public override string ToString()
output = string.Concat(output, "ProductId: ", ProductId, ", ");
output = string.Concat(output, "ProviderResponse: ", ProviderResponse, ", ");
output = string.Concat(output, "PurchaseTime: ", PurchaseTime, ", ");
+ output = string.Concat(output, "RefundTime: ", RefundTime, ", ");
output = string.Concat(output, "SeenBefore: ", SeenBefore, ", ");
output = string.Concat(output, "Store: ", Store, ", ");
output = string.Concat(output, "TransactionId: ", TransactionId, ", ");
output = string.Concat(output, "UpdateTime: ", UpdateTime, ", ");
+ output = string.Concat(output, "UserId: ", UserId, ", ");
return output;
}
}
@@ -3788,11 +3861,26 @@ public interface IApiValidatedSubscription
///
string ProductId { get; }
+ ///
+ /// Raw provider notification body.
+ ///
+ string ProviderNotification { get; }
+
+ ///
+ /// Raw provider validation response body.
+ ///
+ string ProviderResponse { get; }
+
///
/// UNIX Timestamp when the purchase was done.
///
string PurchaseTime { get; }
+ ///
+ /// Subscription refund time. If this time is set, the subscription was refunded.
+ ///
+ string RefundTime { get; }
+
///
/// Store identifier
///
@@ -3802,6 +3890,11 @@ public interface IApiValidatedSubscription
/// UNIX Timestamp when the receipt validation was updated in DB.
///
string UpdateTime { get; }
+
+ ///
+ /// Subscription User ID.
+ ///
+ string UserId { get; }
}
///
@@ -3817,6 +3910,7 @@ internal class ApiValidatedSubscription : IApiValidatedSubscription
public string CreateTime { get; set; }
///
+ [IgnoreDataMember]
public ApiStoreEnvironment Environment => _environment;
[DataMember(Name="environment"), Preserve]
public ApiStoreEnvironment _environment { get; set; }
@@ -3833,11 +3927,24 @@ internal class ApiValidatedSubscription : IApiValidatedSubscription
[DataMember(Name="product_id"), Preserve]
public string ProductId { get; set; }
+ ///
+ [DataMember(Name="provider_notification"), Preserve]
+ public string ProviderNotification { get; set; }
+
+ ///
+ [DataMember(Name="provider_response"), Preserve]
+ public string ProviderResponse { get; set; }
+
///
[DataMember(Name="purchase_time"), Preserve]
public string PurchaseTime { get; set; }
///
+ [DataMember(Name="refund_time"), Preserve]
+ public string RefundTime { get; set; }
+
+ ///
+ [IgnoreDataMember]
public ApiStoreProvider Store => _store;
[DataMember(Name="store"), Preserve]
public ApiStoreProvider _store { get; set; }
@@ -3846,6 +3953,10 @@ internal class ApiValidatedSubscription : IApiValidatedSubscription
[DataMember(Name="update_time"), Preserve]
public string UpdateTime { get; set; }
+ ///
+ [DataMember(Name="user_id"), Preserve]
+ public string UserId { get; set; }
+
public override string ToString()
{
var output = "";
@@ -3855,9 +3966,13 @@ public override string ToString()
output = string.Concat(output, "ExpiryTime: ", ExpiryTime, ", ");
output = string.Concat(output, "OriginalTransactionId: ", OriginalTransactionId, ", ");
output = string.Concat(output, "ProductId: ", ProductId, ", ");
+ output = string.Concat(output, "ProviderNotification: ", ProviderNotification, ", ");
+ output = string.Concat(output, "ProviderResponse: ", ProviderResponse, ", ");
output = string.Concat(output, "PurchaseTime: ", PurchaseTime, ", ");
+ output = string.Concat(output, "RefundTime: ", RefundTime, ", ");
output = string.Concat(output, "Store: ", Store, ", ");
output = string.Concat(output, "UpdateTime: ", UpdateTime, ", ");
+ output = string.Concat(output, "UserId: ", UserId, ", ");
return output;
}
}
@@ -3957,6 +4072,7 @@ internal class ApiWriteStorageObjectsRequest : IApiWriteStorageObjectsRequest
{
///
+ [IgnoreDataMember]
public IEnumerable Objects => _objects ?? new List(0);
[DataMember(Name="objects"), Preserve]
public List _objects { get; set; }
@@ -4028,6 +4144,7 @@ internal class RpcStatus : IRpcStatus
public int Code { get; set; }
///
+ [IgnoreDataMember]
public IEnumerable Details => _details ?? new List(0);
[DataMember(Name="details"), Preserve]
public List _details { get; set; }
@@ -4090,6 +4207,33 @@ public async Task HealthcheckAsync(
await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
}
+ ///
+ /// Delete the current user's account.
+ ///
+ public async Task DeleteAccountAsync(
+ string bearerToken,
+ CancellationToken? cancellationToken)
+ {
+
+ var urlpath = "/v2/account";
+
+ var queryParams = "";
+
+ var uri = new UriBuilder(_baseUri)
+ {
+ Path = urlpath,
+ Query = queryParams
+ }.Uri;
+
+ var method = "DELETE";
+ var headers = new Dictionary();
+ var header = string.Concat("Bearer ", bearerToken);
+ headers.Add("Authorization", header);
+
+ byte[] content = null;
+ await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
+ }
+
///
/// Fetch the current user's account.
///
@@ -4158,14 +4302,14 @@ public async Task UpdateAccountAsync(
public async Task AuthenticateAppleAsync(
string basicAuthUsername,
string basicAuthPassword,
- ApiAccountApple body,
+ ApiAccountApple account,
bool? create,
string username,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/account/authenticate/apple";
@@ -4194,7 +4338,7 @@ public async Task AuthenticateAppleAsync(
}
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -4206,14 +4350,14 @@ public async Task AuthenticateAppleAsync(
public async Task AuthenticateCustomAsync(
string basicAuthUsername,
string basicAuthPassword,
- ApiAccountCustom body,
+ ApiAccountCustom account,
bool? create,
string username,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/account/authenticate/custom";
@@ -4242,7 +4386,7 @@ public async Task AuthenticateCustomAsync(
}
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -4254,14 +4398,14 @@ public async Task AuthenticateCustomAsync(
public async Task AuthenticateDeviceAsync(
string basicAuthUsername,
string basicAuthPassword,
- ApiAccountDevice body,
+ ApiAccountDevice account,
bool? create,
string username,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/account/authenticate/device";
@@ -4290,7 +4434,7 @@ public async Task AuthenticateDeviceAsync(
}
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -4302,14 +4446,14 @@ public async Task AuthenticateDeviceAsync(
public async Task AuthenticateEmailAsync(
string basicAuthUsername,
string basicAuthPassword,
- ApiAccountEmail body,
+ ApiAccountEmail account,
bool? create,
string username,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/account/authenticate/email";
@@ -4338,7 +4482,7 @@ public async Task AuthenticateEmailAsync(
}
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -4350,15 +4494,15 @@ public async Task AuthenticateEmailAsync(
public async Task AuthenticateFacebookAsync(
string basicAuthUsername,
string basicAuthPassword,
- ApiAccountFacebook body,
+ ApiAccountFacebook account,
bool? create,
string username,
bool? sync,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/account/authenticate/facebook";
@@ -4390,7 +4534,7 @@ public async Task AuthenticateFacebookAsync(
}
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -4402,14 +4546,14 @@ public async Task AuthenticateFacebookAsync(
public async Task AuthenticateFacebookInstantGameAsync(
string basicAuthUsername,
string basicAuthPassword,
- ApiAccountFacebookInstantGame body,
+ ApiAccountFacebookInstantGame account,
bool? create,
string username,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/account/authenticate/facebookinstantgame";
@@ -4438,7 +4582,7 @@ public async Task AuthenticateFacebookInstantGameAsync(
}
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -4450,14 +4594,14 @@ public async Task AuthenticateFacebookInstantGameAsync(
public async Task AuthenticateGameCenterAsync(
string basicAuthUsername,
string basicAuthPassword,
- ApiAccountGameCenter body,
+ ApiAccountGameCenter account,
bool? create,
string username,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/account/authenticate/gamecenter";
@@ -4486,7 +4630,7 @@ public async Task AuthenticateGameCenterAsync(
}
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -4498,14 +4642,14 @@ public async Task AuthenticateGameCenterAsync(
public async Task AuthenticateGoogleAsync(
string basicAuthUsername,
string basicAuthPassword,
- ApiAccountGoogle body,
+ ApiAccountGoogle account,
bool? create,
string username,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/account/authenticate/google";
@@ -4534,7 +4678,7 @@ public async Task AuthenticateGoogleAsync(
}
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -4546,15 +4690,15 @@ public async Task AuthenticateGoogleAsync(
public async Task AuthenticateSteamAsync(
string basicAuthUsername,
string basicAuthPassword,
- ApiAccountSteam body,
+ ApiAccountSteam account,
bool? create,
string username,
bool? sync,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/account/authenticate/steam";
@@ -4586,7 +4730,7 @@ public async Task AuthenticateSteamAsync(
}
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -4733,13 +4877,13 @@ public async Task LinkEmailAsync(
///
public async Task LinkFacebookAsync(
string bearerToken,
- ApiAccountFacebook body,
+ ApiAccountFacebook account,
bool? sync,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/account/link/facebook";
@@ -4761,7 +4905,7 @@ public async Task LinkFacebookAsync(
headers.Add("Authorization", header);
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
}
@@ -5484,13 +5628,13 @@ public async Task BlockFriendsAsync(
///
public async Task ImportFacebookFriendsAsync(
string bearerToken,
- ApiAccountFacebook body,
+ ApiAccountFacebook account,
bool? reset,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/friend/facebook";
@@ -5512,7 +5656,7 @@ public async Task ImportFacebookFriendsAsync(
headers.Add("Authorization", header);
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
}
@@ -5522,13 +5666,13 @@ public async Task ImportFacebookFriendsAsync(
///
public async Task ImportSteamFriendsAsync(
string bearerToken,
- ApiAccountSteam body,
+ ApiAccountSteam account,
bool? reset,
CancellationToken? cancellationToken)
{
- if (body == null)
+ if (account == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'account' is required but was null.");
}
var urlpath = "/v2/friend/steam";
@@ -5550,7 +5694,7 @@ public async Task ImportSteamFriendsAsync(
headers.Add("Authorization", header);
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = account.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
}
@@ -6351,16 +6495,16 @@ public async Task ListLeaderboardRecordsAsync(
public async Task WriteLeaderboardRecordAsync(
string bearerToken,
string leaderboardId,
- WriteLeaderboardRecordRequestLeaderboardRecordWrite body,
+ WriteLeaderboardRecordRequestLeaderboardRecordWrite record,
CancellationToken? cancellationToken)
{
if (leaderboardId == null)
{
throw new ArgumentException("'leaderboardId' is required but was null.");
}
- if (body == null)
+ if (record == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'record' is required but was null.");
}
var urlpath = "/v2/leaderboard/{leaderboardId}";
@@ -6380,7 +6524,7 @@ public async Task WriteLeaderboardRecordAsync(
headers.Add("Authorization", header);
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = record.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -6563,6 +6707,8 @@ public async Task ListNotificationsAsync(
///
public async Task RpcFunc2Async(
string bearerToken,
+ string basicAuthUsername,
+ string basicAuthPassword,
string id,
string payload,
string httpKey,
@@ -6597,6 +6743,12 @@ public async Task RpcFunc2Async(
var header = string.Concat("Bearer ", bearerToken);
headers.Add("Authorization", header);
}
+ if (!string.IsNullOrEmpty(basicAuthUsername))
+ {
+ var credentials = Encoding.UTF8.GetBytes(basicAuthUsername + ":" + basicAuthPassword);
+ var header = string.Concat("Basic ", Convert.ToBase64String(credentials));
+ headers.Add("Authorization", header);
+ }
byte[] content = null;
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
@@ -6608,8 +6760,10 @@ public async Task RpcFunc2Async(
///
public async Task RpcFuncAsync(
string bearerToken,
+ string basicAuthUsername,
+ string basicAuthPassword,
string id,
- string body,
+ string payload,
string httpKey,
CancellationToken? cancellationToken)
{
@@ -6617,9 +6771,9 @@ public async Task RpcFuncAsync(
{
throw new ArgumentException("'id' is required but was null.");
}
- if (body == null)
+ if (payload == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'payload' is required but was null.");
}
var urlpath = "/v2/rpc/{id}";
@@ -6643,9 +6797,15 @@ public async Task RpcFuncAsync(
var header = string.Concat("Bearer ", bearerToken);
headers.Add("Authorization", header);
}
+ if (!string.IsNullOrEmpty(basicAuthUsername))
+ {
+ var credentials = Encoding.UTF8.GetBytes(basicAuthUsername + ":" + basicAuthPassword);
+ var header = string.Concat("Basic ", Convert.ToBase64String(credentials));
+ headers.Add("Authorization", header);
+ }
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = payload.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -6992,16 +7152,16 @@ public async Task ListTournamentRecordsAsync(
public async Task WriteTournamentRecord2Async(
string bearerToken,
string tournamentId,
- WriteTournamentRecordRequestTournamentRecordWrite body,
+ WriteTournamentRecordRequestTournamentRecordWrite record,
CancellationToken? cancellationToken)
{
if (tournamentId == null)
{
throw new ArgumentException("'tournamentId' is required but was null.");
}
- if (body == null)
+ if (record == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'record' is required but was null.");
}
var urlpath = "/v2/tournament/{tournamentId}";
@@ -7021,7 +7181,7 @@ public async Task WriteTournamentRecord2Async(
headers.Add("Authorization", header);
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = record.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
@@ -7033,16 +7193,16 @@ public async Task WriteTournamentRecord2Async(
public async Task WriteTournamentRecordAsync(
string bearerToken,
string tournamentId,
- WriteTournamentRecordRequestTournamentRecordWrite body,
+ WriteTournamentRecordRequestTournamentRecordWrite record,
CancellationToken? cancellationToken)
{
if (tournamentId == null)
{
throw new ArgumentException("'tournamentId' is required but was null.");
}
- if (body == null)
+ if (record == null)
{
- throw new ArgumentException("'body' is required but was null.");
+ throw new ArgumentException("'record' is required but was null.");
}
var urlpath = "/v2/tournament/{tournamentId}";
@@ -7062,7 +7222,7 @@ public async Task WriteTournamentRecordAsync(
headers.Add("Authorization", header);
byte[] content = null;
- var jsonBody = body.ToJson();
+ var jsonBody = record.ToJson();
content = Encoding.UTF8.GetBytes(jsonBody);
var contents = await HttpAdapter.SendAsync(method, uri, headers, content, Timeout, cancellationToken);
return contents.FromJson();
diff --git a/Nakama/Client.cs b/Nakama/Client.cs
index 2cdb02f2..47668296 100644
--- a/Nakama/Client.cs
+++ b/Nakama/Client.cs
@@ -331,6 +331,21 @@ public async Task CreateGroupAsync(ISession session, string name, str
}, canceller), new RetryHistory(session, retryConfiguration ?? GlobalRetryConfiguration, canceller));
}
+ ///
+ public async Task DeleteAccountAsync(ISession session, RetryConfiguration retryConfiguration = null,
+ CancellationToken canceller = default)
+ {
+ if (AutoRefreshSession && !string.IsNullOrEmpty(session.RefreshToken) &&
+ session.HasExpired(DateTime.UtcNow.Add(DefaultExpiredTimeSpan)))
+ {
+ await SessionRefreshAsync(session, null, retryConfiguration, canceller);
+ }
+
+ await _retryInvoker.InvokeWithRetry(
+ () => _apiClient.DeleteAccountAsync(session.AuthToken, canceller),
+ new RetryHistory(session, retryConfiguration ?? GlobalRetryConfiguration, canceller));
+ }
+
///
public async Task DeleteFriendsAsync(ISession session, IEnumerable ids,
IEnumerable usernames = null, RetryConfiguration retryConfiguration = null,
@@ -1155,7 +1170,7 @@ public async Task RpcAsync(ISession session, string id, string payload,
}
return await _retryInvoker.InvokeWithRetry(
- () => _apiClient.RpcFuncAsync(session.AuthToken, id, payload, null, canceller),
+ () => _apiClient.RpcFuncAsync(session.AuthToken, string.Empty, string.Empty, id, payload, null, canceller),
new RetryHistory(session, retryConfiguration ?? GlobalRetryConfiguration, canceller));
}
@@ -1170,20 +1185,20 @@ public async Task RpcAsync(ISession session, string id, RetryConfigurat
}
return await _retryInvoker.InvokeWithRetry(
- () => _apiClient.RpcFunc2Async(session.AuthToken, id, null, null, canceller),
+ () => _apiClient.RpcFunc2Async(session.AuthToken, string.Empty, string.Empty, id, null, null, canceller),
new RetryHistory(session, retryConfiguration ?? GlobalRetryConfiguration, canceller));
}
///
public Task RpcAsync(string httpkey, string id, string payload,
RetryConfiguration retryConfiguration = null, CancellationToken canceller = default) =>
- _retryInvoker.InvokeWithRetry(() => _apiClient.RpcFuncAsync(null, id, payload, httpkey, canceller),
+ _retryInvoker.InvokeWithRetry(() => _apiClient.RpcFuncAsync(null, string.Empty, string.Empty, id, payload, httpkey, canceller),
new RetryHistory(id, retryConfiguration ?? GlobalRetryConfiguration, canceller));
///
public Task RpcAsync(string httpkey, string id, RetryConfiguration retryConfiguration = null,
CancellationToken canceller = default) =>
- _retryInvoker.InvokeWithRetry(() => _apiClient.RpcFunc2Async(null, id, null, httpkey, canceller),
+ _retryInvoker.InvokeWithRetry(() => _apiClient.RpcFunc2Async(null, string.Empty, string.Empty, id, null, httpkey, canceller),
new RetryHistory(id, retryConfiguration ?? GlobalRetryConfiguration, canceller));
///
diff --git a/Nakama/IClient.cs b/Nakama/IClient.cs
index f94990d8..23eb5031 100644
--- a/Nakama/IClient.cs
+++ b/Nakama/IClient.cs
@@ -236,6 +236,15 @@ Task AuthenticateSteamAsync(string token, string username = null, bool
Task CreateGroupAsync(ISession session, string name, string description = "",
string avatarUrl = null, string langTag = null, bool open = true, int maxCount = 100, RetryConfiguration retryConfiguration = null, CancellationToken canceller = default);
+ ///
+ /// Delete the current user's account. Note that this will invalidate your session, requiring you to reauthenticate.
+ ///
+ /// The session of the user.
+ /// The retry configuration. See
+ /// The that can be used to cancel the request while mid-flight.
+ /// A task which represents the asynchronous operation.
+ Task DeleteAccountAsync(ISession session, RetryConfiguration retryConfiguration = null, CancellationToken canceller = default);
+
///
/// Delete one more or users by id or username from friends.
///
@@ -796,7 +805,7 @@ Task ListUsersStorageObjectsAsync(ISession session, strin
/// The that can be used to cancel the request while mid-flight.
/// A task to resolve an RPC response.
Task RpcAsync(string httpKey, string id, string payload, RetryConfiguration retryConfiguration = null, CancellationToken canceller = default);
-
+
///
/// Execute a function on the server without a session.
///
diff --git a/codegen/main.go b/codegen/main.go
index 0b8ec4e2..491089c6 100755
--- a/codegen/main.go
+++ b/codegen/main.go
@@ -178,6 +178,7 @@ namespace {{.Namespace}}
[DataMember(Name="{{ $attrDataName }}"), Preserve]
public List {{ $fieldname }} { get; set; }
{{- else}}
+ [IgnoreDataMember]
public IEnumerable {{ $fieldname }} => _{{ $propname | snakeToCamel }} ?? new List<{{ $property.Items.Ref | cleanRef }}>(0);
[DataMember(Name="{{ $attrDataName }}"), Preserve]
public List<{{ $property.Items.Ref | cleanRef }}> _{{ $propname | snakeToCamel }} { get; set; }
@@ -185,35 +186,43 @@ namespace {{.Namespace}}
{{- else if eq $property.Type "object"}}
{{- if eq $property.AdditionalProperties.Type "string"}}
{{- if eq $property.AdditionalProperties.Format "int64" }}
+ [IgnoreDataMember]
public IDictionary {{ $fieldname }} => ApiClient.DeserializeIntProperties(_{{ $propname | snakeToCamel }}) ?? new Dictionary();
[DataMember(Name="{{ $attrDataName }}"), Preserve]
public Dictionary _{{ $propname | snakeToCamel }} { get; set; }
{{- else }}
+ [IgnoreDataMember]
public IDictionary {{ $fieldname }} => _{{ $propname | snakeToCamel }} ?? new Dictionary();
[DataMember(Name="{{ $attrDataName }}"), Preserve]
public Dictionary _{{ $propname | snakeToCamel }} { get; set; }
{{- end }}
{{- else if eq $property.AdditionalProperties.Type "integer"}}
+ [IgnoreDataMember]
public IDictionary {{ $fieldname }} => _{{ $propname | snakeToCamel }} ?? new Dictionary();
[DataMember(Name="{{ $attrDataName }}"), Preserve]
{{- else if eq $property.AdditionalProperties.Type "number"}}
+ [IgnoreDataMember]
public IDictionary {{ $fieldname }} => _{{ $propname | snakeToCamel }} ?? new Dictionary();
[DataMember(Name="{{ $attrDataName }}"), Preserve]
public Dictionary _{{ $propname | snakeToCamel }} { get; set; }
{{- else if eq $property.AdditionalProperties.Type "boolean"}}
+ [IgnoreDataMember]
public IDictionary {{ $fieldname }} => _{{ $propname | snakeToCamel }} ?? new Dictionary();
[DataMember(Name="{{ $attrDataName }}"), Preserve]
public Dictionary _{{ $propname | snakeToCamel }} { get; set; }
{{- else}}
+ [IgnoreDataMember]
public IDictionary {{ $fieldname }} => _{{ $propname | snakeToCamel }} ?? new Dictionary();
[DataMember(Name="{{ $attrDataName }}"), Preserve]
public Dictionary _{{ $propname | snakeToCamel }} { get; set; }
{{- end}}
{{- else if isRefToEnum (cleanRef $property.Ref) }}
+ [IgnoreDataMember]
public {{ $property.Ref | cleanRef }} {{ $fieldname }} => _{{ $propname | snakeToCamel }};
[DataMember(Name="{{ $attrDataName }}"), Preserve]
public {{ $property.Ref | cleanRef }} _{{ $propname | snakeToCamel }} { get; set; }
{{- else }}
+ [IgnoreDataMember]
public I{{ $property.Ref | cleanRef }} {{ $fieldname }} => _{{ $propname | snakeToCamel }};
[DataMember(Name="{{ $attrDataName }}"), Preserve]
public {{ $property.Ref | cleanRef }} _{{ $propname | snakeToCamel }} { get; set; }