* AWSUploader.cs: chore: await/async
* AVFile.cs: * AVCloud.cs: * AVQuery.cs: * AVLeaderboard.cs: * QiniuUploader.cs: * QCloudUploader.cs:
parent
f3ed814d96
commit
aabd25d2e8
|
@ -8,15 +8,13 @@ using System.Net.Http.Headers;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal {
|
namespace LeanCloud.Storage.Internal {
|
||||||
internal class AWSUploader : IFileUploader {
|
internal class AWSUploader : IFileUploader {
|
||||||
public Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress,
|
public async Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress,
|
||||||
CancellationToken cancellationToken) {
|
CancellationToken cancellationToken) {
|
||||||
var uploadUrl = fileToken["upload_url"].ToString();
|
var uploadUrl = fileToken["upload_url"].ToString();
|
||||||
state.ObjectId = fileToken["objectId"].ToString();
|
state.ObjectId = fileToken["objectId"].ToString();
|
||||||
string url = fileToken["url"] as string;
|
string url = fileToken["url"] as string;
|
||||||
state.Url = new Uri(url, UriKind.Absolute);
|
state.Url = new Uri(url, UriKind.Absolute);
|
||||||
return PutFile(state, uploadUrl, dataStream).OnSuccess(s => {
|
return await PutFile(state, uploadUrl, dataStream);
|
||||||
return s.Result;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<FileState> PutFile(FileState state, string uploadUrl, Stream dataStream) {
|
internal async Task<FileState> PutFile(FileState state, string uploadUrl, Stream dataStream) {
|
||||||
|
|
|
@ -19,26 +19,28 @@ namespace LeanCloud.Storage.Internal {
|
||||||
bool done;
|
bool done;
|
||||||
private long sliceSize = (long)CommonSize.KB512;
|
private long sliceSize = (long)CommonSize.KB512;
|
||||||
|
|
||||||
public Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) {
|
public async Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) {
|
||||||
fileState = state;
|
fileState = state;
|
||||||
data = dataStream;
|
data = dataStream;
|
||||||
uploadUrl = fileToken["upload_url"].ToString();
|
uploadUrl = fileToken["upload_url"].ToString();
|
||||||
token = fileToken["token"].ToString();
|
token = fileToken["token"].ToString();
|
||||||
fileState.ObjectId = fileToken["objectId"].ToString();
|
fileState.ObjectId = fileToken["objectId"].ToString();
|
||||||
bucket = fileToken["bucket"].ToString();
|
bucket = fileToken["bucket"].ToString();
|
||||||
|
var result = await FileSlice(cancellationToken);
|
||||||
return FileSlice(cancellationToken).OnSuccess(t => {
|
if (done) {
|
||||||
if (done) return Task<FileState>.FromResult(state);
|
return state;
|
||||||
var response = t.Result.Item2;
|
}
|
||||||
|
var response = result.Item2;
|
||||||
var resumeData = response["data"] as IDictionary<string, object>;
|
var resumeData = response["data"] as IDictionary<string, object>;
|
||||||
if (resumeData.ContainsKey("access_url")) return Task<FileState>.FromResult(state);
|
if (resumeData.ContainsKey("access_url")) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
var sliceSession = resumeData["session"].ToString();
|
var sliceSession = resumeData["session"].ToString();
|
||||||
var sliceOffset = long.Parse(resumeData["offset"].ToString());
|
var sliceOffset = long.Parse(resumeData["offset"].ToString());
|
||||||
return UploadSlice(sliceSession, sliceOffset, dataStream, progress, cancellationToken);
|
return await UploadSlice(sliceSession, sliceOffset, dataStream, progress, cancellationToken);
|
||||||
}).Unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Task<FileState> UploadSlice(
|
async Task<FileState> UploadSlice(
|
||||||
string sessionId,
|
string sessionId,
|
||||||
long offset,
|
long offset,
|
||||||
Stream dataStream,
|
Stream dataStream,
|
||||||
|
@ -55,21 +57,20 @@ namespace LeanCloud.Storage.Internal {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offset == dataLength) {
|
if (offset == dataLength) {
|
||||||
return Task.FromResult<FileState>(fileState);
|
return fileState;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sliceFile = GetNextBinary(offset, dataStream);
|
var sliceFile = GetNextBinary(offset, dataStream);
|
||||||
return ExcuteUpload(sessionId, offset, sliceFile, cancellationToken).OnSuccess(_ => {
|
var result = await ExcuteUpload(sessionId, offset, sliceFile, cancellationToken);
|
||||||
offset += sliceFile.Length;
|
offset += sliceFile.Length;
|
||||||
if (offset == dataLength) {
|
if (offset == dataLength) {
|
||||||
done = true;
|
done = true;
|
||||||
return Task.FromResult<FileState>(fileState);
|
return fileState;
|
||||||
}
|
}
|
||||||
var response = _.Result.Item2;
|
var response = result.Item2;
|
||||||
var resumeData = response["data"] as IDictionary<string, object>;
|
var resumeData = response["data"] as IDictionary<string, object>;
|
||||||
var sliceSession = resumeData["session"].ToString();
|
var sliceSession = resumeData["session"].ToString();
|
||||||
return UploadSlice(sliceSession, offset, dataStream, progress, cancellationToken);
|
return await UploadSlice(sliceSession, offset, dataStream, progress, cancellationToken);
|
||||||
}).Unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> ExcuteUpload(string sessionId, long offset, byte[] sliceFile, CancellationToken cancellationToken) {
|
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> ExcuteUpload(string sessionId, long offset, byte[] sliceFile, CancellationToken cancellationToken) {
|
||||||
|
@ -81,19 +82,18 @@ namespace LeanCloud.Storage.Internal {
|
||||||
return PostToQCloud(body, sliceFile, cancellationToken);
|
return PostToQCloud(body, sliceFile, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task<Tuple<HttpStatusCode, IDictionary<string, object>>> FileSlice(CancellationToken cancellationToken) {
|
async Task<Tuple<HttpStatusCode, IDictionary<string, object>>> FileSlice(CancellationToken cancellationToken) {
|
||||||
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
|
SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider();
|
||||||
var body = new Dictionary<string, object>();
|
var body = new Dictionary<string, object>();
|
||||||
if (data.Length <= (long)CommonSize.KB512) {
|
if (data.Length <= (long)CommonSize.KB512) {
|
||||||
body.Add("op", "upload");
|
body.Add("op", "upload");
|
||||||
body.Add("sha", HexStringFromBytes(sha1.ComputeHash(data)));
|
body.Add("sha", HexStringFromBytes(sha1.ComputeHash(data)));
|
||||||
var wholeFile = GetNextBinary(0, data);
|
var wholeFile = GetNextBinary(0, data);
|
||||||
return PostToQCloud(body, wholeFile, cancellationToken).OnSuccess(_ => {
|
var result = await PostToQCloud(body, wholeFile, cancellationToken);
|
||||||
if (_.Result.Item1 == HttpStatusCode.OK) {
|
if (result.Item1 == HttpStatusCode.OK) {
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
return _.Result;
|
return result;
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
body.Add("op", "upload_slice");
|
body.Add("op", "upload_slice");
|
||||||
body.Add("filesize", data.Length);
|
body.Add("filesize", data.Length);
|
||||||
|
@ -101,7 +101,7 @@ namespace LeanCloud.Storage.Internal {
|
||||||
body.Add("slice_size", (long)CommonSize.KB512);
|
body.Add("slice_size", (long)CommonSize.KB512);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PostToQCloud(body, null, cancellationToken);
|
return await PostToQCloud(body, null, cancellationToken);
|
||||||
}
|
}
|
||||||
public static string HexStringFromBytes(byte[] bytes) {
|
public static string HexStringFromBytes(byte[] bytes) {
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
|
@ -22,16 +22,15 @@ namespace LeanCloud.Storage.Internal {
|
||||||
internal static string UP_HOST = "https://up.qbox.me";
|
internal static string UP_HOST = "https://up.qbox.me";
|
||||||
private readonly object mutex = new object();
|
private readonly object mutex = new object();
|
||||||
|
|
||||||
public Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) {
|
public async Task<FileState> Upload(FileState state, Stream dataStream, IDictionary<string, object> fileToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) {
|
||||||
state.frozenData = dataStream;
|
state.frozenData = dataStream;
|
||||||
state.CloudName = fileToken["key"] as string;
|
state.CloudName = fileToken["key"] as string;
|
||||||
MergeFromJSON(state, fileToken);
|
MergeFromJSON(state, fileToken);
|
||||||
return UploadNextChunk(state, dataStream, string.Empty, 0, progress).OnSuccess(_ => {
|
await UploadNextChunk(state, dataStream, string.Empty, 0, progress);
|
||||||
return state;
|
return state;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Task UploadNextChunk(FileState state, Stream dataStream, string context, long offset, IProgress<AVUploadProgressEventArgs> progress) {
|
async Task UploadNextChunk(FileState state, Stream dataStream, string context, long offset, IProgress<AVUploadProgressEventArgs> progress) {
|
||||||
var totalSize = dataStream.Length;
|
var totalSize = dataStream.Length;
|
||||||
var remainingSize = totalSize - state.completed;
|
var remainingSize = totalSize - state.completed;
|
||||||
|
|
||||||
|
@ -43,14 +42,13 @@ namespace LeanCloud.Storage.Internal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state.completed == totalSize) {
|
if (state.completed == totalSize) {
|
||||||
return QiniuMakeFile(state, state.frozenData, state.token, state.CloudName, totalSize, state.block_ctxes.ToArray(), CancellationToken.None);
|
await QiniuMakeFile(state, state.frozenData, state.token, state.CloudName, totalSize, state.block_ctxes.ToArray(), CancellationToken.None);
|
||||||
}
|
} else if (state.completed % BLOCKSIZE == 0) {
|
||||||
if (state.completed % BLOCKSIZE == 0) {
|
|
||||||
var firstChunkBinary = GetChunkBinary(state.completed, dataStream);
|
var firstChunkBinary = GetChunkBinary(state.completed, dataStream);
|
||||||
|
|
||||||
var blockSize = remainingSize > BLOCKSIZE ? BLOCKSIZE : remainingSize;
|
var blockSize = remainingSize > BLOCKSIZE ? BLOCKSIZE : remainingSize;
|
||||||
return MakeBlock(state, firstChunkBinary, blockSize).OnSuccess(t => {
|
var result = await MakeBlock(state, firstChunkBinary, blockSize);
|
||||||
var dict = t.Result;
|
var dict = result;
|
||||||
var ctx = dict["ctx"].ToString();
|
var ctx = dict["ctx"].ToString();
|
||||||
offset = long.Parse(dict["offset"].ToString());
|
offset = long.Parse(dict["offset"].ToString());
|
||||||
var host = dict["host"].ToString();
|
var host = dict["host"].ToString();
|
||||||
|
@ -60,12 +58,11 @@ namespace LeanCloud.Storage.Internal {
|
||||||
state.block_ctxes.Add(ctx);
|
state.block_ctxes.Add(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return UploadNextChunk(state, dataStream, ctx, offset, progress);
|
await UploadNextChunk(state, dataStream, ctx, offset, progress);
|
||||||
}).Unwrap();
|
} else {
|
||||||
}
|
|
||||||
var chunkBinary = GetChunkBinary(state.completed, dataStream);
|
var chunkBinary = GetChunkBinary(state.completed, dataStream);
|
||||||
return PutChunk(state, chunkBinary, context, offset).OnSuccess(t => {
|
var result = await PutChunk(state, chunkBinary, context, offset);
|
||||||
var dict = t.Result;
|
var dict = result;
|
||||||
var ctx = dict["ctx"].ToString();
|
var ctx = dict["ctx"].ToString();
|
||||||
|
|
||||||
offset = long.Parse(dict["offset"].ToString());
|
offset = long.Parse(dict["offset"].ToString());
|
||||||
|
@ -74,9 +71,8 @@ namespace LeanCloud.Storage.Internal {
|
||||||
if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) {
|
if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) {
|
||||||
state.block_ctxes.Add(ctx);
|
state.block_ctxes.Add(ctx);
|
||||||
}
|
}
|
||||||
|
await UploadNextChunk(state, dataStream, ctx, offset, progress);
|
||||||
return UploadNextChunk(state, dataStream, ctx, offset, progress);
|
}
|
||||||
}).Unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] GetChunkBinary(long completed, Stream dataStream) {
|
byte[] GetChunkBinary(long completed, Stream dataStream) {
|
||||||
|
|
|
@ -220,19 +220,18 @@ namespace LeanCloud {
|
||||||
/// <param name="height">captcha image height.</param>
|
/// <param name="height">captcha image height.</param>
|
||||||
/// <param name="cancellationToken">CancellationToken.</param>
|
/// <param name="cancellationToken">CancellationToken.</param>
|
||||||
/// <returns>an instance of Captcha.</returns>
|
/// <returns>an instance of Captcha.</returns>
|
||||||
public static Task<Captcha> RequestCaptchaAsync(int width = 85, int height = 30, CancellationToken cancellationToken = default) {
|
public static async Task<Captcha> RequestCaptchaAsync(int width = 85, int height = 30, CancellationToken cancellationToken = default) {
|
||||||
var path = string.Format("requestCaptcha?width={0}&height={1}", width, height);
|
var path = string.Format("requestCaptcha?width={0}&height={1}", width, height);
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = $"requestCaptcha?width={width}&height={height}",
|
Path = $"requestCaptcha?width={width}&height={height}",
|
||||||
Method = HttpMethod.Get
|
Method = HttpMethod.Get
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).OnSuccess(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
var decoded = AVDecoder.Instance.Decode(t.Result.Item2) as IDictionary<string, object>;
|
var decoded = AVDecoder.Instance.Decode(result.Item2) as IDictionary<string, object>;
|
||||||
return new Captcha() {
|
return new Captcha {
|
||||||
Token = decoded["captcha_token"] as string,
|
Token = decoded["captcha_token"] as string,
|
||||||
Url = decoded["captcha_url"] as string,
|
Url = decoded["captcha_url"] as string,
|
||||||
};
|
};
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -242,7 +241,7 @@ namespace LeanCloud {
|
||||||
/// <param name="code">User's input of this captcha.</param>
|
/// <param name="code">User's input of this captcha.</param>
|
||||||
/// <param name="cancellationToken">CancellationToken.</param>
|
/// <param name="cancellationToken">CancellationToken.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Task<string> VerifyCaptchaAsync(string code, string token, CancellationToken cancellationToken = default) {
|
public static async Task<string> VerifyCaptchaAsync(string code, string token, CancellationToken cancellationToken = default) {
|
||||||
var data = new Dictionary<string, object> {
|
var data = new Dictionary<string, object> {
|
||||||
{ "captcha_token", token },
|
{ "captcha_token", token },
|
||||||
{ "captcha_code", code },
|
{ "captcha_code", code },
|
||||||
|
@ -252,11 +251,11 @@ namespace LeanCloud {
|
||||||
Method = HttpMethod.Post,
|
Method = HttpMethod.Post,
|
||||||
Content = data
|
Content = data
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).ContinueWith(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
if (!t.Result.Item2.ContainsKey("validate_token"))
|
if (result.Item2.TryGetValue("validate_token", out object tokenObj)) {
|
||||||
|
return tokenObj as string;
|
||||||
|
}
|
||||||
throw new KeyNotFoundException("validate_token");
|
throw new KeyNotFoundException("validate_token");
|
||||||
return t.Result.Item2["validate_token"] as string;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -264,16 +263,15 @@ namespace LeanCloud {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Task<IDictionary<string, object>> GetCustomParametersAsync(CancellationToken cancellationToken = default) {
|
public static async Task<IDictionary<string, object>> GetCustomParametersAsync(CancellationToken cancellationToken = default) {
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = $"statistics/apps/{AVClient.CurrentConfiguration.ApplicationId}/sendPolicy",
|
Path = $"statistics/apps/{AVClient.CurrentConfiguration.ApplicationId}/sendPolicy",
|
||||||
Method = HttpMethod.Get
|
Method = HttpMethod.Get
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).OnSuccess(t => {
|
var data = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
var settings = t.Result.Item2;
|
var settings = data.Item2;
|
||||||
var CloudParameters = settings["parameters"] as IDictionary<string, object>;
|
var CloudParameters = settings["parameters"] as IDictionary<string, object>;
|
||||||
return CloudParameters;
|
return CloudParameters;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RealtimeSignature {
|
public class RealtimeSignature {
|
||||||
|
@ -283,7 +281,7 @@ namespace LeanCloud {
|
||||||
public string Signature { internal set; get; }
|
public string Signature { internal set; get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Task<RealtimeSignature> RequestRealtimeSignatureAsync(CancellationToken cancellationToken = default) {
|
public static async Task<RealtimeSignature> RequestRealtimeSignatureAsync(CancellationToken cancellationToken = default) {
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = "rtm/sign",
|
Path = "rtm/sign",
|
||||||
Method = HttpMethod.Post,
|
Method = HttpMethod.Post,
|
||||||
|
@ -291,15 +289,14 @@ namespace LeanCloud {
|
||||||
{ "session_token", AVUser.CurrentUser?.SessionToken }
|
{ "session_token", AVUser.CurrentUser?.SessionToken }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken).OnSuccess(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken);
|
||||||
var body = t.Result.Item2;
|
var body = result.Item2;
|
||||||
return new RealtimeSignature() {
|
return new RealtimeSignature() {
|
||||||
Nonce = body["nonce"] as string,
|
Nonce = body["nonce"] as string,
|
||||||
Timestamp = (long)body["timestamp"],
|
Timestamp = (long)body["timestamp"],
|
||||||
ClientId = body["client_id"] as string,
|
ClientId = body["client_id"] as string,
|
||||||
Signature = body["signature"] as string,
|
Signature = body["signature"] as string,
|
||||||
};
|
};
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -265,11 +265,8 @@ namespace LeanCloud {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="progress">The progress callback.</param>
|
/// <param name="progress">The progress callback.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
public Task SaveAsync(IProgress<AVUploadProgressEventArgs> progress = null, CancellationToken cancellationToken = default) {
|
public async Task SaveAsync(IProgress<AVUploadProgressEventArgs> progress = null, CancellationToken cancellationToken = default) {
|
||||||
return FileController.SaveAsync(state, dataStream, progress, cancellationToken)
|
state = await FileController.SaveAsync(state, dataStream, progress, cancellationToken);
|
||||||
.OnSuccess(t => {
|
|
||||||
state = t.Result;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -320,11 +317,9 @@ namespace LeanCloud {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>获取之后并没有实际执行下载,只是加载了文件的元信息以及物理地址(Url)
|
/// <remarks>获取之后并没有实际执行下载,只是加载了文件的元信息以及物理地址(Url)
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static Task<AVFile> GetFileWithObjectIdAsync(string objectId, CancellationToken cancellationToken = default) {
|
public static async Task<AVFile> GetFileWithObjectIdAsync(string objectId, CancellationToken cancellationToken = default) {
|
||||||
return FileController.GetAsync(objectId, cancellationToken).OnSuccess(_ => {
|
var fileState = await FileController.GetAsync(objectId, cancellationToken);
|
||||||
var filestate = _.Result;
|
return new AVFile(fileState);
|
||||||
return new AVFile(filestate);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AVFile CreateWithoutData(string objectId) {
|
public static AVFile CreateWithoutData(string objectId) {
|
||||||
|
|
|
@ -10,8 +10,7 @@ using System.Text.RegularExpressions;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using LeanCloud.Storage.Internal;
|
using LeanCloud.Storage.Internal;
|
||||||
|
|
||||||
namespace LeanCloud
|
namespace LeanCloud {
|
||||||
{
|
|
||||||
public class AVQuery<T> where T : AVObject {
|
public class AVQuery<T> where T : AVObject {
|
||||||
public string ClassName {
|
public string ClassName {
|
||||||
get; internal set;
|
get; internal set;
|
||||||
|
@ -24,7 +23,8 @@ namespace LeanCloud
|
||||||
return $"classes/{Uri.EscapeDataString(ClassName)}";
|
return $"classes/{Uri.EscapeDataString(ClassName)}";
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
} set {
|
}
|
||||||
|
set {
|
||||||
path = value;
|
path = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,56 +202,41 @@ namespace LeanCloud
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IEnumerable<T>> FindAsync(CancellationToken cancellationToken = default)
|
public async Task<IEnumerable<T>> FindAsync(CancellationToken cancellationToken = default) {
|
||||||
{
|
IEnumerable<IObjectState> states = await QueryController.FindAsync(this, AVUser.CurrentUser, cancellationToken);
|
||||||
return QueryController.FindAsync<T>(this, AVUser.CurrentUser, cancellationToken).OnSuccess(t => {
|
|
||||||
IEnumerable<IObjectState> states = t.Result;
|
|
||||||
return (from state in states
|
return (from state in states
|
||||||
select AVObject.FromState<T>(state, ClassName));
|
select AVObject.FromState<T>(state, ClassName));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<T> FirstOrDefaultAsync(CancellationToken cancellationToken = default)
|
public async Task<T> FirstOrDefaultAsync(CancellationToken cancellationToken = default) {
|
||||||
{
|
IObjectState state = await QueryController.FirstAsync<T>(this, AVUser.CurrentUser, cancellationToken);
|
||||||
return QueryController.FirstAsync<T>(this, AVUser.CurrentUser, cancellationToken).OnSuccess(t => {
|
|
||||||
IObjectState state = t.Result;
|
|
||||||
return state == null ? default : AVObject.FromState<T>(state, ClassName);
|
return state == null ? default : AVObject.FromState<T>(state, ClassName);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<T> FirstAsync(CancellationToken cancellationToken = default)
|
public async Task<T> FirstAsync(CancellationToken cancellationToken = default) {
|
||||||
{
|
var result = await FirstOrDefaultAsync(cancellationToken);
|
||||||
return FirstOrDefaultAsync(cancellationToken).OnSuccess(t =>
|
if (result == null) {
|
||||||
{
|
|
||||||
if (t.Result == null)
|
|
||||||
{
|
|
||||||
throw new AVException(AVException.ErrorCode.ObjectNotFound,
|
throw new AVException(AVException.ErrorCode.ObjectNotFound,
|
||||||
"No results matched the query.");
|
"No results matched the query.");
|
||||||
}
|
}
|
||||||
return t.Result;
|
return result;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<int> CountAsync(CancellationToken cancellationToken = default)
|
public Task<int> CountAsync(CancellationToken cancellationToken = default) {
|
||||||
{
|
|
||||||
return QueryController.CountAsync(this, AVUser.CurrentUser, cancellationToken);
|
return QueryController.CountAsync(this, AVUser.CurrentUser, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<T> GetAsync(string objectId, CancellationToken cancellationToken)
|
public async Task<T> GetAsync(string objectId, CancellationToken cancellationToken) {
|
||||||
{
|
|
||||||
AVQuery<T> singleItemQuery = new AVQuery<T>(ClassName)
|
AVQuery<T> singleItemQuery = new AVQuery<T>(ClassName)
|
||||||
.WhereEqualTo("objectId", objectId);
|
.WhereEqualTo("objectId", objectId);
|
||||||
singleItemQuery = new AVQuery<T>(singleItemQuery, includes: this.includes, selectedKeys: this.selectedKeys, limit: 1);
|
singleItemQuery = new AVQuery<T>(singleItemQuery, includes: this.includes, selectedKeys: this.selectedKeys, limit: 1);
|
||||||
return singleItemQuery.FindAsync(cancellationToken).OnSuccess(t =>
|
var result = await singleItemQuery.FindAsync(cancellationToken);
|
||||||
{
|
var first = result.FirstOrDefault();
|
||||||
var result = t.Result.FirstOrDefault();
|
if (first == null) {
|
||||||
if (result == null)
|
|
||||||
{
|
|
||||||
throw new AVException(AVException.ErrorCode.ObjectNotFound,
|
throw new AVException(AVException.ErrorCode.ObjectNotFound,
|
||||||
"Object with the given objectId not found.");
|
"Object with the given objectId not found.");
|
||||||
}
|
}
|
||||||
return result;
|
return first;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region CQL
|
#region CQL
|
||||||
|
@ -289,22 +274,20 @@ namespace LeanCloud
|
||||||
return RebuildObjectFromCloudQueryResult(queryString);
|
return RebuildObjectFromCloudQueryResult(queryString);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static Task<IEnumerable<T>> RebuildObjectFromCloudQueryResult(string queryString) {
|
internal static async Task<IEnumerable<T>> RebuildObjectFromCloudQueryResult(string queryString) {
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = queryString,
|
Path = queryString,
|
||||||
Method = HttpMethod.Get
|
Method = HttpMethod.Get
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, cancellationToken: CancellationToken.None).OnSuccess(t =>
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command, CancellationToken.None);
|
||||||
{
|
var items = result.Item2["results"] as IList<object>;
|
||||||
var items = t.Result.Item2["results"] as IList<object>;
|
var className = result.Item2["className"].ToString();
|
||||||
var className = t.Result.Item2["className"].ToString();
|
|
||||||
|
|
||||||
IEnumerable<IObjectState> states = (from item in items
|
IEnumerable<IObjectState> states = (from item in items
|
||||||
select AVObjectCoder.Instance.Decode(item as IDictionary<string, object>, AVDecoder.Instance));
|
select AVObjectCoder.Instance.Decode(item as IDictionary<string, object>, AVDecoder.Instance));
|
||||||
|
|
||||||
return (from state in states
|
return from state in states
|
||||||
select AVObject.FromState<T>(state, className));
|
select AVObject.FromState<T>(state, className);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -138,7 +138,7 @@ namespace LeanCloud {
|
||||||
/// <param name="order">排序方式</param>
|
/// <param name="order">排序方式</param>
|
||||||
/// <param name="versionChangeInterval">版本更新频率</param>
|
/// <param name="versionChangeInterval">版本更新频率</param>
|
||||||
/// <param name="updateStrategy">成绩更新策略</param>
|
/// <param name="updateStrategy">成绩更新策略</param>
|
||||||
public static Task<AVLeaderboard> CreateLeaderboard(string statisticName,
|
public static async Task<AVLeaderboard> CreateLeaderboard(string statisticName,
|
||||||
AVLeaderboardOrder order = AVLeaderboardOrder.DESCENDING,
|
AVLeaderboardOrder order = AVLeaderboardOrder.DESCENDING,
|
||||||
AVLeaderboardUpdateStrategy updateStrategy = AVLeaderboardUpdateStrategy.BETTER,
|
AVLeaderboardUpdateStrategy updateStrategy = AVLeaderboardUpdateStrategy.BETTER,
|
||||||
AVLeaderboardVersionChangeInterval versionChangeInterval = AVLeaderboardVersionChangeInterval.WEEK) {
|
AVLeaderboardVersionChangeInterval versionChangeInterval = AVLeaderboardVersionChangeInterval.WEEK) {
|
||||||
|
@ -157,14 +157,13 @@ namespace LeanCloud {
|
||||||
Method = HttpMethod.Post,
|
Method = HttpMethod.Post,
|
||||||
Content = data
|
Content = data
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
try {
|
try {
|
||||||
var leaderboard = Parse(t.Result.Item2);
|
var leaderboard = Parse(result.Item2);
|
||||||
return leaderboard;
|
return leaderboard;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -195,7 +194,7 @@ namespace LeanCloud {
|
||||||
/// <param name="user">用户</param>
|
/// <param name="user">用户</param>
|
||||||
/// <param name="statistics">成绩</param>
|
/// <param name="statistics">成绩</param>
|
||||||
/// <param name="overwrite">是否强行覆盖</param>
|
/// <param name="overwrite">是否强行覆盖</param>
|
||||||
public static Task<List<AVStatistic>> UpdateStatistics(AVUser user, Dictionary<string, double> statistics, bool overwrite = false) {
|
public static async Task<List<AVStatistic>> UpdateStatistics(AVUser user, Dictionary<string, double> statistics, bool overwrite = false) {
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new ArgumentNullException(nameof(user));
|
throw new ArgumentNullException(nameof(user));
|
||||||
}
|
}
|
||||||
|
@ -219,10 +218,10 @@ namespace LeanCloud {
|
||||||
Method = HttpMethod.Post,
|
Method = HttpMethod.Post,
|
||||||
Content = data
|
Content = data
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
try {
|
try {
|
||||||
List<AVStatistic> statisticList = new List<AVStatistic>();
|
List<AVStatistic> statisticList = new List<AVStatistic>();
|
||||||
List<object> list = t.Result.Item2["results"] as List<object>;
|
List<object> list = result.Item2["results"] as List<object>;
|
||||||
foreach (object obj in list) {
|
foreach (object obj in list) {
|
||||||
statisticList.Add(AVStatistic.Parse(obj as IDictionary<string, object>));
|
statisticList.Add(AVStatistic.Parse(obj as IDictionary<string, object>));
|
||||||
}
|
}
|
||||||
|
@ -230,7 +229,6 @@ namespace LeanCloud {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -239,7 +237,7 @@ namespace LeanCloud {
|
||||||
/// <returns>成绩列表</returns>
|
/// <returns>成绩列表</returns>
|
||||||
/// <param name="user">用户</param>
|
/// <param name="user">用户</param>
|
||||||
/// <param name="statisticNames">名称列表</param>
|
/// <param name="statisticNames">名称列表</param>
|
||||||
public static Task<List<AVStatistic>> GetStatistics(AVUser user, List<string> statisticNames = null) {
|
public static async Task<List<AVStatistic>> GetStatistics(AVUser user, List<string> statisticNames = null) {
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new ArgumentNullException(nameof(user));
|
throw new ArgumentNullException(nameof(user));
|
||||||
}
|
}
|
||||||
|
@ -252,10 +250,10 @@ namespace LeanCloud {
|
||||||
Path = path,
|
Path = path,
|
||||||
Method = HttpMethod.Post
|
Method = HttpMethod.Post
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
try {
|
try {
|
||||||
List<AVStatistic> statisticList = new List<AVStatistic>();
|
List<AVStatistic> statisticList = new List<AVStatistic>();
|
||||||
List<object> list = t.Result.Item2["results"] as List<object>;
|
List<object> list = result.Item2["results"] as List<object>;
|
||||||
foreach (object obj in list) {
|
foreach (object obj in list) {
|
||||||
statisticList.Add(AVStatistic.Parse(obj as IDictionary<string, object>));
|
statisticList.Add(AVStatistic.Parse(obj as IDictionary<string, object>));
|
||||||
}
|
}
|
||||||
|
@ -263,7 +261,6 @@ namespace LeanCloud {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -271,7 +268,7 @@ namespace LeanCloud {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user">用户</param>
|
/// <param name="user">用户</param>
|
||||||
/// <param name="statisticNames">名称列表</param>
|
/// <param name="statisticNames">名称列表</param>
|
||||||
public static Task DeleteStatistics(AVUser user, List<string> statisticNames) {
|
public static async Task DeleteStatistics(AVUser user, List<string> statisticNames) {
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
throw new ArgumentNullException(nameof(user));
|
throw new ArgumentNullException(nameof(user));
|
||||||
}
|
}
|
||||||
|
@ -285,7 +282,7 @@ namespace LeanCloud {
|
||||||
Path = path,
|
Path = path,
|
||||||
Method = HttpMethod.Delete,
|
Method = HttpMethod.Delete,
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -294,21 +291,20 @@ namespace LeanCloud {
|
||||||
/// <returns>排行榜归档列表</returns>
|
/// <returns>排行榜归档列表</returns>
|
||||||
/// <param name="skip">跳过数量</param>
|
/// <param name="skip">跳过数量</param>
|
||||||
/// <param name="limit">分页数量</param>
|
/// <param name="limit">分页数量</param>
|
||||||
public Task<List<AVLeaderboardArchive>> GetArchives(int skip = 0, int limit = 10) {
|
public async Task<List<AVLeaderboardArchive>> GetArchives(int skip = 0, int limit = 10) {
|
||||||
var path = string.Format("leaderboard/leaderboards/{0}/archives", StatisticName);
|
var path = string.Format("leaderboard/leaderboards/{0}/archives", StatisticName);
|
||||||
path = string.Format("{0}?skip={1}&limit={2}", path, skip, limit);
|
path = string.Format("{0}?skip={1}&limit={2}", path, skip, limit);
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = path,
|
Path = path,
|
||||||
Method = HttpMethod.Get
|
Method = HttpMethod.Get
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
List<AVLeaderboardArchive> archives = new List<AVLeaderboardArchive>();
|
List<AVLeaderboardArchive> archives = new List<AVLeaderboardArchive>();
|
||||||
List<object> list = t.Result.Item2["results"] as List<object>;
|
List<object> list = result.Item2["results"] as List<object>;
|
||||||
foreach (object obj in list) {
|
foreach (object obj in list) {
|
||||||
archives.Add(AVLeaderboardArchive.Parse(obj as IDictionary<string, object>));
|
archives.Add(AVLeaderboardArchive.Parse(obj as IDictionary<string, object>));
|
||||||
}
|
}
|
||||||
return archives;
|
return archives;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -336,7 +332,7 @@ namespace LeanCloud {
|
||||||
return GetResults(AVUser.CurrentUser, version, skip, limit, selectUserKeys, includeStatistics);
|
return GetResults(AVUser.CurrentUser, version, skip, limit, selectUserKeys, includeStatistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task<List<AVRanking>> GetResults(AVUser user,
|
async Task<List<AVRanking>> GetResults(AVUser user,
|
||||||
int version, int skip, int limit,
|
int version, int skip, int limit,
|
||||||
List<string> selectUserKeys,
|
List<string> selectUserKeys,
|
||||||
List<string> includeStatistics) {
|
List<string> includeStatistics) {
|
||||||
|
@ -361,10 +357,10 @@ namespace LeanCloud {
|
||||||
Path = path,
|
Path = path,
|
||||||
Method = HttpMethod.Get
|
Method = HttpMethod.Get
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
try {
|
try {
|
||||||
List<AVRanking> rankingList = new List<AVRanking>();
|
List<AVRanking> rankingList = new List<AVRanking>();
|
||||||
List<object> list = t.Result.Item2["results"] as List<object>;
|
List<object> list = result.Item2["results"] as List<object>;
|
||||||
foreach (object obj in list) {
|
foreach (object obj in list) {
|
||||||
rankingList.Add(AVRanking.Parse(obj as IDictionary<string, object>));
|
rankingList.Add(AVRanking.Parse(obj as IDictionary<string, object>));
|
||||||
}
|
}
|
||||||
|
@ -372,7 +368,6 @@ namespace LeanCloud {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -380,14 +375,13 @@ namespace LeanCloud {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>排行榜对象</returns>
|
/// <returns>排行榜对象</returns>
|
||||||
/// <param name="updateStrategy">更新策略</param>
|
/// <param name="updateStrategy">更新策略</param>
|
||||||
public Task<AVLeaderboard> UpdateUpdateStrategy(AVLeaderboardUpdateStrategy updateStrategy) {
|
public async Task<AVLeaderboard> UpdateUpdateStrategy(AVLeaderboardUpdateStrategy updateStrategy) {
|
||||||
var data = new Dictionary<string, object> {
|
var data = new Dictionary<string, object> {
|
||||||
{ "updateStrategy", updateStrategy.ToString().ToLower() }
|
{ "updateStrategy", updateStrategy.ToString().ToLower() }
|
||||||
};
|
};
|
||||||
return Update(data).OnSuccess(t => {
|
var result = await Update(data);
|
||||||
UpdateStrategy = (AVLeaderboardUpdateStrategy)Enum.Parse(typeof(AVLeaderboardUpdateStrategy), t.Result["updateStrategy"].ToString().ToUpper());
|
UpdateStrategy = (AVLeaderboardUpdateStrategy)Enum.Parse(typeof(AVLeaderboardUpdateStrategy), result["updateStrategy"].ToString().ToUpper());
|
||||||
return this;
|
return this;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -395,67 +389,63 @@ namespace LeanCloud {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>排行榜对象</returns>
|
/// <returns>排行榜对象</returns>
|
||||||
/// <param name="versionChangeInterval">版本更新频率</param>
|
/// <param name="versionChangeInterval">版本更新频率</param>
|
||||||
public Task<AVLeaderboard> UpdateVersionChangeInterval(AVLeaderboardVersionChangeInterval versionChangeInterval) {
|
public async Task<AVLeaderboard> UpdateVersionChangeInterval(AVLeaderboardVersionChangeInterval versionChangeInterval) {
|
||||||
var data = new Dictionary<string, object> {
|
var data = new Dictionary<string, object> {
|
||||||
{ "versionChangeInterval", versionChangeInterval.ToString().ToLower() }
|
{ "versionChangeInterval", versionChangeInterval.ToString().ToLower() }
|
||||||
};
|
};
|
||||||
return Update(data).OnSuccess(t => {
|
var result = await Update(data);
|
||||||
VersionChangeInterval = (AVLeaderboardVersionChangeInterval)Enum.Parse(typeof(AVLeaderboardVersionChangeInterval), t.Result["versionChangeInterval"].ToString().ToUpper());
|
VersionChangeInterval = (AVLeaderboardVersionChangeInterval)Enum.Parse(typeof(AVLeaderboardVersionChangeInterval), result["versionChangeInterval"].ToString().ToUpper());
|
||||||
return this;
|
return this;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Task<IDictionary<string,object>> Update(Dictionary<string, object> data) {
|
async Task<IDictionary<string,object>> Update(Dictionary<string, object> data) {
|
||||||
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
|
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = path,
|
Path = path,
|
||||||
Method = HttpMethod.Put,
|
Method = HttpMethod.Put,
|
||||||
Content = data
|
Content = data
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
return t.Result.Item2;
|
return result.Item2;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 拉取排行榜数据
|
/// 拉取排行榜数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>排行榜对象</returns>
|
/// <returns>排行榜对象</returns>
|
||||||
public Task<AVLeaderboard> Fetch() {
|
public async Task<AVLeaderboard> Fetch() {
|
||||||
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
|
var path = string.Format("leaderboard/leaderboards/{0}", StatisticName);
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = path,
|
Path = path,
|
||||||
Method = HttpMethod.Get
|
Method = HttpMethod.Get
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
try {
|
try {
|
||||||
// 反序列化 Leaderboard 对象
|
// 反序列化 Leaderboard 对象
|
||||||
var leaderboard = Parse(t.Result.Item2);
|
var leaderboard = Parse(result.Item2);
|
||||||
return leaderboard;
|
return leaderboard;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 重置排行榜
|
/// 重置排行榜
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>排行榜对象</returns>
|
/// <returns>排行榜对象</returns>
|
||||||
public Task<AVLeaderboard> Reset() {
|
public async Task<AVLeaderboard> Reset() {
|
||||||
var path = string.Format("leaderboard/leaderboards/{0}/incrementVersion", StatisticName);
|
var path = string.Format("leaderboard/leaderboards/{0}/incrementVersion", StatisticName);
|
||||||
var command = new AVCommand {
|
var command = new AVCommand {
|
||||||
Path = path,
|
Path = path,
|
||||||
Method = HttpMethod.Put
|
Method = HttpMethod.Put
|
||||||
};
|
};
|
||||||
return AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command).OnSuccess(t => {
|
var result = await AVPlugins.Instance.CommandRunner.RunCommandAsync<IDictionary<string, object>>(command);
|
||||||
try {
|
try {
|
||||||
Init(t.Result.Item2);
|
Init(result.Item2);
|
||||||
return this;
|
return this;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
throw new AVException(AVException.ErrorCode.InvalidJSON, e.Message);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
Loading…
Reference in New Issue