* LCIMConversation.cs: chore: 完善消息的编解码

* LCObject.cs:
* LCIMClient.cs:
* Program.cs:
* LCIMMessage.cs:
* LCConnection.cs:
* LCIMTextMessage.cs:
* LCIMFileMessage.cs:
* LCIMVideoMessage.cs:
* LCIMTypedMessage.cs:
* LCIMImageMessage.cs:
* LCIMAudioMessage.cs:
* LCApplicationRealtimeExt.cs:
* LCIMBinaryMessage.cs:
* LCHttpClient.cs:
* LCIMLocationMessage.cs:
* LCJsonConverter.cs:
* LCIMConversationQuery.cs:
* LCWebSocketConnection.cs:
oneRain 2020-03-18 16:21:29 +08:00
parent 29a84b8afb
commit 6781d4e94f
19 changed files with 263 additions and 221 deletions

View File

@ -77,7 +77,7 @@ namespace LeanCloud.Realtime {
};
GenericCommand command = client.NewCommand(CommandType.Conv, OpType.Count);
command.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(command);
GenericCommand response = await client.connection.SendRequest(command);
return response.ConvMessage.Count;
}
@ -92,7 +92,7 @@ namespace LeanCloud.Realtime {
};
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Update);
request.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
JsonObjectMessage attr = response.ConvMessage.AttrModified;
// 更新自定义属性
if (attr != null) {
@ -122,7 +122,7 @@ namespace LeanCloud.Realtime {
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Add);
request.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
List<string> allowedIds = response.ConvMessage.AllowedPids.ToList();
List<ErrorCommand> failedIds = response.ConvMessage.FailedPids.ToList();
// TODO 转化为返回
@ -147,7 +147,7 @@ namespace LeanCloud.Realtime {
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove);
request.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
List<string> allowedIds = response.ConvMessage.AllowedPids.ToList();
List<ErrorCommand> failedIds = response.ConvMessage.FailedPids.ToList();
// TODO 转化为返回
@ -180,11 +180,17 @@ namespace LeanCloud.Realtime {
DirectCommand direct = new DirectCommand {
FromPeerId = client.ClientId,
Cid = Id,
Msg = message.Serialize(),
};
if (message is LCIMTypedMessage typedMessage) {
direct.Msg = JsonConvert.SerializeObject(typedMessage.Encode());
} else if (message is LCIMBinaryMessage binaryMessage) {
direct.BinaryMsg = ByteString.CopyFrom(binaryMessage.Data);
} else {
throw new ArgumentException("Message MUST BE LCIMTypedMessage or LCIMBinaryMessage.");
}
GenericCommand command = client.NewDirectCommand();
command.DirectMessage = direct;
GenericCommand response = await client.client.SendRequest(command);
GenericCommand response = await client.connection.SendRequest(command);
// 消息发送应答
AckCommand ack = response.AckMessage;
message.Id = ack.Uid;
@ -202,7 +208,7 @@ namespace LeanCloud.Realtime {
};
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Mute);
request.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
IsMute = true;
return this;
}
@ -217,7 +223,7 @@ namespace LeanCloud.Realtime {
};
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Unmute);
request.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
IsMute = false;
return this;
}
@ -237,7 +243,7 @@ namespace LeanCloud.Realtime {
conv.M.AddRange(clientIds);
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.AddShutup);
request.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids);
}
@ -256,7 +262,7 @@ namespace LeanCloud.Realtime {
conv.M.AddRange(clientIds);
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove);
request.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids);
}
@ -275,7 +281,7 @@ namespace LeanCloud.Realtime {
blacklist.ToPids.AddRange(clientIds);
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Block);
request.BlacklistMessage = blacklist;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids);
}
@ -289,7 +295,7 @@ namespace LeanCloud.Realtime {
blacklist.ToPids.AddRange(clientIds);
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Unblock);
request.BlacklistMessage = blacklist;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids);
}
@ -311,7 +317,7 @@ namespace LeanCloud.Realtime {
patch.Patches.Add(item);
GenericCommand request = client.NewCommand(CommandType.Patch, OpType.Modify);
request.PatchMessage = patch;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
return null;
}
@ -335,11 +341,10 @@ namespace LeanCloud.Realtime {
Timestamp = oldMessage.DeliveredTimestamp,
Recall = false,
};
if (newMessage.GetText() != null) {
item.Data = newMessage.GetText();
}
if (newMessage.GetBytes() != null) {
item.BinaryMsg = ByteString.CopyFrom(newMessage.GetBytes());
if (newMessage is LCIMTypedMessage typedMessage) {
item.Data = JsonConvert.SerializeObject(typedMessage.Encode());
} else if (newMessage is LCIMBinaryMessage binaryMessage) {
item.BinaryMsg = ByteString.CopyFrom(binaryMessage.Data);
}
if (newMessage.MentionList != null) {
item.MentionPids.AddRange(newMessage.MentionList);
@ -350,7 +355,7 @@ namespace LeanCloud.Realtime {
patch.Patches.Add(item);
GenericCommand request = client.NewCommand(CommandType.Patch, OpType.Modify);
request.PatchMessage = patch;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
return null;
}
@ -371,7 +376,7 @@ namespace LeanCloud.Realtime {
};
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.MemberInfoUpdate);
request.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
// TODO 同步 members
return this;
@ -422,7 +427,7 @@ namespace LeanCloud.Realtime {
};
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.QueryShutup);
request.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(request);
GenericCommand response = await client.connection.SendRequest(request);
return new LCIMPageResult {
Results = response.ConvMessage.M.ToList(),
Next = response.ConvMessage.Next

View File

@ -245,7 +245,7 @@ namespace LeanCloud.Realtime {
conv.Where = JsonObjectMessage.Parser.ParseJson(where);
}
command.ConvMessage = conv;
GenericCommand response = await client.client.SendRequest(command);
GenericCommand response = await client.connection.SendRequest(command);
JsonObjectMessage results = response.ConvMessage.Results;
List<LCIMConversation> convList = null;
// TODO 反序列化

View File

@ -1,111 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Net.WebSockets;
using Google.Protobuf;
using LeanCloud.Realtime.Protocol;
using LeanCloud.Storage;
namespace LeanCloud.Realtime.Internal {
internal class LCConnection {
private const int KEEP_ALIVE_INTERVAL = 10;
private const int RECV_BUFFER_SIZE = 1024;
private ClientWebSocket ws;
private volatile int requestI = 1;
private readonly object requestILock = new object();
private readonly Dictionary<int, TaskCompletionSource<GenericCommand>> responses;
internal LCConnection() {
responses = new Dictionary<int, TaskCompletionSource<GenericCommand>>();
}
internal async Task Connect() {
ws = new ClientWebSocket();
ws.Options.AddSubProtocol("lc.protobuf2.3");
ws.Options.KeepAliveInterval = TimeSpan.FromSeconds(KEEP_ALIVE_INTERVAL);
await ws.ConnectAsync(new Uri(""), default);
}
internal async Task SendRequest(GenericCommand request) {
request.I = RequestI;
ArraySegment<byte> bytes = new ArraySegment<byte>(request.ToByteArray());
try {
await ws.SendAsync(bytes, WebSocketMessageType.Binary, true, default);
} catch (Exception e) {
// TODO 发送消息异常
}
}
internal async Task Close() {
await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "1", default);
}
private async Task StartReceive() {
byte[] buffer = new byte[RECV_BUFFER_SIZE];
try {
while (ws.State == WebSocketState.Open) {
byte[] data = new byte[0];
WebSocketReceiveResult result;
do {
result = await ws.ReceiveAsync(new ArraySegment<byte>(buffer), default);
if (result.MessageType == WebSocketMessageType.Close) {
// TODO 区分主动断开和被动断开
return;
}
// 拼合 WebSocket Frame
byte[] oldData = data;
data = new byte[data.Length + result.Count];
Array.Copy(oldData, data, oldData.Length);
Array.Copy(buffer, 0, data, oldData.Length, result.Count);
} while (!result.EndOfMessage);
try {
GenericCommand command = GenericCommand.Parser.ParseFrom(data);
HandleCommand(command);
} catch (Exception e) {
// 解析消息错误
}
}
} catch (Exception e) {
// TODO 连接断开
}
}
private void HandleCommand(GenericCommand command) {
if (command.HasI) {
// 应答
if (responses.TryGetValue(command.I, out TaskCompletionSource<GenericCommand> tcs)) {
if (command.HasErrorMessage) {
// 错误
ErrorCommand error = command.ErrorMessage;
int code = error.Code;
string detail = error.Detail;
// TODO 包装成异常抛出
LCException exception = new LCException(code, detail);
tcs.SetException(exception);
} else {
tcs.SetResult(command);
}
}
} else {
// 通知
}
}
private int RequestI {
get {
lock (requestILock) {
return requestI++;
};
}
}
}
}

View File

@ -9,7 +9,7 @@ using LeanCloud.Common;
using Google.Protobuf;
namespace LeanCloud.Realtime.Internal.WebSocket {
internal class LCWebSocketClient {
internal class LCWebSocketConnection {
private const int KEEP_ALIVE_INTERVAL = 10;
private const int RECV_BUFFER_SIZE = 1024;
@ -25,7 +25,7 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
get; set;
}
internal LCWebSocketClient() {
internal LCWebSocketConnection() {
responses = new Dictionary<int, TaskCompletionSource<GenericCommand>>();
}

View File

@ -5,7 +5,6 @@ using LeanCloud.Realtime.Internal;
namespace LeanCloud {
public static class LCApplicationRealtimeExt {
static LCConnection connection;
public static async Task<LCIMClient> CreateIMClient(this LCApplication application, string clientId) {
if (string.IsNullOrEmpty(clientId)) {

View File

@ -9,7 +9,7 @@ using Newtonsoft.Json;
namespace LeanCloud.Realtime {
public class LCIMClient {
internal LCWebSocketClient client;
internal LCWebSocketConnection connection;
private Dictionary<string, LCIMConversation> conversationDict;
@ -75,6 +75,10 @@ namespace LeanCloud.Realtime {
get; set;
}
public Action<LCIMConversation, LCIMMessage> OnMessageReceived {
get; set;
}
public LCIMClient(string clientId) {
ClientId = clientId;
conversationDict = new Dictionary<string, LCIMConversation>();
@ -85,14 +89,14 @@ namespace LeanCloud.Realtime {
/// </summary>
/// <returns></returns>
public async Task Open() {
client = new LCWebSocketClient {
connection = new LCWebSocketConnection {
OnNotification = OnNotification
};
await client.Connect();
await connection.Connect();
// Open Session
GenericCommand request = NewCommand(CommandType.Session, OpType.Open);
request.SessionMessage = new SessionCommand();
GenericCommand response = await client.SendRequest(request);
GenericCommand response = await connection.SendRequest(request);
SessionToken = response.SessionMessage.St;
}
@ -101,7 +105,7 @@ namespace LeanCloud.Realtime {
/// </summary>
/// <returns></returns>
public async Task Close() {
await client.Close();
await connection.Close();
}
public async Task<LCIMChatRoom> CreateChatRoom(
@ -154,7 +158,7 @@ namespace LeanCloud.Realtime {
};
}
command.ConvMessage = conv;
GenericCommand response = await client.SendRequest(command);
GenericCommand response = await connection.SendRequest(command);
LCIMConversation conversation = GetOrCreateConversation(response.ConvMessage.Cid);
conversation.MergeFrom(response.ConvMessage);
conversationDict[conversation.Id] = conversation;
@ -210,6 +214,9 @@ namespace LeanCloud.Realtime {
case CommandType.Conv:
OnConversationNotification(notification);
break;
case CommandType.Direct:
OnDirectNotification(notification.DirectMessage);
break;
default:
break;
}
@ -270,6 +277,46 @@ namespace LeanCloud.Realtime {
}
}
private void OnDirectNotification(DirectCommand direct) {
LCIMMessage message = null;
if (direct.HasBinaryMsg) {
// 二进制消息
byte[] bytes = direct.BinaryMsg.ToByteArray();
message = new LCIMBinaryMessage(bytes);
} else {
// 文本消息
string messageData = direct.Msg;
Dictionary<string, object> msg = JsonConvert.DeserializeObject<Dictionary<string, object>>(messageData);
int msgType = (int)(long)msg["_lctype"];
switch (msgType) {
case -1:
message = new LCIMTextMessage();
break;
case -2:
message = new LCIMImageMessage();
break;
case -3:
message = new LCIMAudioMessage();
break;
case -4:
message = new LCIMVideoMessage();
break;
case -5:
message = new LCIMLocationMessage();
break;
case -6:
message = new LCIMFileMessage();
break;
default:
break;
}
message.Decode(direct);
}
// TODO 获取对话
OnMessageReceived?.Invoke(null, message);
}
private LCIMConversation GetOrCreateConversation(string convId) {
if (!conversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
conversation = new LCIMConversation(this);

View File

@ -1,17 +1,32 @@
using LeanCloud.Storage;
using System.Collections.Generic;
using LeanCloud.Storage;
namespace LeanCloud.Realtime {
public class LCIMAudioMessage : LCIMFileMessage {
public double Duration {
get {
if (double.TryParse("duration", out double duration)) {
if (double.TryParse(File.MetaData["duration"] as string, out double duration)) {
return duration;
}
return 0;
}
}
public LCIMAudioMessage(LCFile file) : base(file) {
internal LCIMAudioMessage() {
}
public LCIMAudioMessage(LCFile file) : base(file) {
}
internal override Dictionary<string, object> Encode() {
Dictionary<string, object> data = base.Encode();
Dictionary<string, object> fileData = data["_lcfile"] as Dictionary<string, object>;
Dictionary<string, object> metaData = fileData["metaData"] as Dictionary<string, object>;
metaData["duration"] = File.MetaData["duration"];
return data;
}
internal override int MessageType => AudioMessageType;
}
}

View File

@ -1,25 +1,14 @@
using System;
using System.Collections.Generic;
namespace LeanCloud.Realtime {
public class LCIMBinaryMessage : LCIMMessage {
public byte[] Data {
get; set;
get; internal set;
}
public LCIMBinaryMessage(byte[] data) {
Data = data;
}
internal override string Serialize() {
throw new NotImplementedException();
}
internal override string GetText() {
return null;
}
internal override byte[] GetBytes() {
return Data;
}
}
}

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using LeanCloud.Storage;
namespace LeanCloud.Realtime {
@ -30,24 +29,48 @@ namespace LeanCloud.Realtime {
}
}
public LCIMFileMessage(LCFile file) : base(null) {
internal LCIMFileMessage() : base() {
}
public LCIMFileMessage(LCFile file) : base() {
File = file;
}
internal override string Serialize() {
internal override Dictionary<string, object> Encode() {
if (File == null) {
throw new Exception("File MUST NOT be null before sent.");
}
File.MetaData["name"] = File.Name;
File.MetaData["format"] = File.MimeType;
Dictionary<string, object> data = new Dictionary<string, object> {
Dictionary<string, object> fileData = new Dictionary<string, object> {
{ "objId", File.ObjectId },
{ "url", File.Url },
{ "metaData", File.MetaData }
{ "metaData", new Dictionary<string, object> {
{ "name", File.Name },
{ "format", File.MimeType },
{ "size", File.MetaData["size"] }
} }
};
return JsonConvert.SerializeObject(new Dictionary<string, object> {
{ "_lcfile", data }
});
Dictionary<string, object> data = base.Encode();
data["_lcfile"] = fileData;
return data;
}
protected override void DecodeMessageData(Dictionary<string, object> msgData) {
base.DecodeMessageData(msgData);
Dictionary<string, object> fileData = msgData["_lcfile"] as Dictionary<string, object>;
string objectId = fileData["objId"] as string;
File = LCObject.CreateWithoutData(LCFile.CLASS_NAME, objectId) as LCFile;
if (fileData.TryGetValue("name", out object name)) {
File.Name = name as string;
}
if (fileData.TryGetValue("url", out object url)) {
File.Url = url as string;
}
if (fileData.TryGetValue("metaData", out object metaData)) {
File.MetaData = metaData as Dictionary<string, object>;
}
}
internal override int MessageType => FileMessageType;
}
}

View File

@ -1,4 +1,4 @@
using System;
using System.Collections.Generic;
using LeanCloud.Storage;
namespace LeanCloud.Realtime {
@ -21,7 +21,22 @@ namespace LeanCloud.Realtime {
}
}
public LCIMImageMessage(LCFile file) : base(file) {
internal LCIMImageMessage() : base() {
}
public LCIMImageMessage(LCFile file) : base(file) {
}
internal override Dictionary<string, object> Encode() {
Dictionary<string, object> data = base.Encode();
Dictionary<string, object> fileData = data["_lcfile"] as Dictionary<string, object>;
Dictionary<string, object> metaData = fileData["metaData"] as Dictionary<string, object>;
metaData["width"] = File.MetaData["width"];
metaData["height"] = File.MetaData["height"];
return data;
}
internal override int MessageType => ImageMessageType;
}
}

View File

@ -8,18 +8,29 @@ namespace LeanCloud.Realtime {
get; set;
}
internal LCIMLocationMessage() {
}
public LCIMLocationMessage(LCGeoPoint locaction) : base(null) {
Location = locaction;
}
internal override string Serialize() {
Dictionary<string, object> data = new Dictionary<string, object> {
internal override Dictionary<string, object> Encode() {
Dictionary<string, object> data = base.Encode();
Dictionary<string, object> locationData = new Dictionary<string, object> {
{ "longitude", Location.Longitude },
{ "latitude", Location.Latitude }
};
return JsonConvert.SerializeObject(new Dictionary<string, object> {
{ "_lcloc", data }
});
data["_lcloc"] = locationData;
return data;
}
protected override void DecodeMessageData(Dictionary<string, object> msgData) {
base.DecodeMessageData(msgData);
Dictionary<string, object> locationData = msgData["_lcloc"] as Dictionary<string, object>;
Location = new LCGeoPoint((double)locationData["latitude"], (double)locationData["longitude"]);
}
internal override int MessageType => LocationMessageType;
}
}

View File

@ -1,8 +1,16 @@
using System;
using System.Collections.Generic;
using LeanCloud.Realtime.Protocol;
namespace LeanCloud.Realtime {
public abstract class LCIMMessage {
internal const int TextMessageType = -1;
internal const int ImageMessageType = -2;
internal const int AudioMessageType = -3;
internal const int VideoMessageType = -4;
internal const int LocationMessageType = -5;
internal const int FileMessageType = -6;
public string ConversationId {
get; set;
}
@ -71,9 +79,11 @@ namespace LeanCloud.Realtime {
}
internal abstract string Serialize();
internal abstract string GetText();
internal abstract byte[] GetBytes();
internal virtual void Decode(DirectCommand direct) {
ConversationId = direct.Cid;
Id = direct.Id;
FromClientId = direct.FromPeerId;
DeliveredTimestamp = direct.Timestamp;
}
}
}

View File

@ -1,24 +1,33 @@
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
namespace LeanCloud.Realtime {
public class LCIMTextMessage : LCIMTypedMessage {
const int TextMessageType = -1;
public string Text {
get; set;
}
public LCIMTextMessage(string text) : base(TextMessageType) {
internal LCIMTextMessage() {
}
public LCIMTextMessage(string text) : base() {
Text = text;
}
internal override string Serialize() {
return Text;
internal override Dictionary<string, object> Encode() {
Dictionary<string, object> data = base.Encode();
if (!string.IsNullOrEmpty(Text)) {
data["_lctext"] = Text;
}
return data;
}
internal override string GetText() {
return Text;
protected override void DecodeMessageData(Dictionary<string, object> msgData) {
base.DecodeMessageData(msgData);
if (msgData.TryGetValue("_lctext", out object value)) {
Text = value as string;
}
}
internal override int MessageType => TextMessageType;
}
}

View File

@ -1,23 +1,32 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using LeanCloud.Realtime.Protocol;
using LeanCloud.Storage.Internal;
namespace LeanCloud.Realtime {
public class LCIMTypedMessage : LCIMMessage {
protected int type;
public abstract class LCIMTypedMessage : LCIMMessage {
protected LCIMTypedMessage() {
protected LCIMTypedMessage(int type) {
this.type = type;
}
internal override string Serialize() {
throw new NotImplementedException();
internal virtual int MessageType {
get; private set;
}
internal override string GetText() {
return null;
internal virtual Dictionary<string, object> Encode() {
return new Dictionary<string, object> {
{ "_lctype", MessageType }
};
}
internal override byte[] GetBytes() {
return null;
internal override void Decode(DirectCommand direct) {
base.Decode(direct);
Dictionary<string, object> msgData = JsonConvert.DeserializeObject<Dictionary<string, object>>(direct.Msg, new LCJsonConverter());
DecodeMessageData(msgData);
}
protected virtual void DecodeMessageData(Dictionary<string, object> msgData) {
MessageType = (int)msgData["_lctype"];
}
}
}

View File

@ -1,4 +1,5 @@
using LeanCloud.Storage;
using System.Collections.Generic;
using LeanCloud.Storage;
namespace LeanCloud.Realtime {
public class LCIMVideoMessage : LCIMFileMessage {
@ -11,8 +12,23 @@ namespace LeanCloud.Realtime {
}
}
internal LCIMVideoMessage() {
}
public LCIMVideoMessage(LCFile file) : base(file) {
}
internal override Dictionary<string, object> Encode() {
Dictionary<string, object> data = base.Encode();
Dictionary<string, object> fileData = data["_lcfile"] as Dictionary<string, object>;
Dictionary<string, object> metaData = fileData["metaData"] as Dictionary<string, object>;
metaData["width"] = File.MetaData["width"];
metaData["height"] = File.MetaData["height"];
metaData["duration"] = File.MetaData["duration"];
return data;
}
internal override int MessageType => VideoMessageType;
}
}

View File

@ -61,7 +61,7 @@ namespace LeanCloud.Storage.Internal.Http {
LCHttpUtils.PrintResponse(response, resultString);
if (response.IsSuccessStatusCode) {
T ret = JsonConvert.DeserializeObject<T>(resultString, new LeanCloudJsonConverter());
T ret = JsonConvert.DeserializeObject<T>(resultString, new LCJsonConverter());
return ret;
}
throw HandleErrorResponse(response.StatusCode, resultString);
@ -94,7 +94,7 @@ namespace LeanCloud.Storage.Internal.Http {
LCHttpUtils.PrintResponse(response, resultString);
if (response.IsSuccessStatusCode) {
T ret = JsonConvert.DeserializeObject<T>(resultString, new LeanCloudJsonConverter());
T ret = JsonConvert.DeserializeObject<T>(resultString, new LCJsonConverter());
return ret;
}
throw HandleErrorResponse(response.StatusCode, resultString);
@ -127,7 +127,7 @@ namespace LeanCloud.Storage.Internal.Http {
LCHttpUtils.PrintResponse(response, resultString);
if (response.IsSuccessStatusCode) {
T ret = JsonConvert.DeserializeObject<T>(resultString, new LeanCloudJsonConverter());
T ret = JsonConvert.DeserializeObject<T>(resultString, new LCJsonConverter());
return ret;
}
throw HandleErrorResponse(response.StatusCode, resultString);
@ -150,7 +150,7 @@ namespace LeanCloud.Storage.Internal.Http {
LCHttpUtils.PrintResponse(response, resultString);
if (response.IsSuccessStatusCode) {
Dictionary<string, object> ret = JsonConvert.DeserializeObject<Dictionary<string, object>>(resultString, new LeanCloudJsonConverter());
Dictionary<string, object> ret = JsonConvert.DeserializeObject<Dictionary<string, object>>(resultString, new LCJsonConverter());
return;
}
throw HandleErrorResponse(response.StatusCode, resultString);
@ -161,7 +161,7 @@ namespace LeanCloud.Storage.Internal.Http {
string message = responseContent;
try {
// 尝试获取 LeanCloud 返回错误信息
Dictionary<string, object> error = JsonConvert.DeserializeObject<Dictionary<string, object>>(responseContent, new LeanCloudJsonConverter());
Dictionary<string, object> error = JsonConvert.DeserializeObject<Dictionary<string, object>>(responseContent, new LCJsonConverter());
code = (int)error["code"];
message = error["error"].ToString();
} catch (Exception e) {

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using Newtonsoft.Json;
namespace LeanCloud.Storage.Internal {
public class LeanCloudJsonConverter : JsonConverter {
public class LCJsonConverter : JsonConverter {
public override bool CanConvert(Type objectType) {
return objectType == typeof(object);
}

View File

@ -86,7 +86,7 @@ namespace LeanCloud.Storage {
if (string.IsNullOrEmpty(objectId)) {
throw new ArgumentNullException(nameof(objectId));
}
LCObject obj = new LCObject(className);
LCObject obj = Create(className);
obj.data.ObjectId = objectId;
obj.isNew = false;
return obj;

View File

@ -36,26 +36,28 @@ namespace RealtimeConsole {
};
LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com");
LCIMClient client = new LCIMClient("hello123");
LCIMClient hello = new LCIMClient("hello");
try {
await client.Open();
Console.WriteLine($"End {Thread.CurrentThread.ManagedThreadId}");
} catch (Exception e) {
Console.WriteLine(e.Message);
}
await hello.Open();
client.OnInvited = (conv, initBy) => {
hello.OnInvited = (conv, initBy) => {
Console.WriteLine($"on invited: {initBy}");
};
client.OnMembersJoined = (conv, memberList, initBy) => {
hello.OnMembersJoined = (conv, memberList, initBy) => {
Console.WriteLine($"on members joined: {initBy}");
};
List<string> memberIdList = new List<string> { "world", "code" };
string name = Guid.NewGuid().ToString();
LCIMConversation conversation = await client.CreateConversation(memberIdList, name: name, unique: true);
LCIMConversation conversation = await hello.CreateConversation(memberIdList, name: name, unique: true);
LCIMClient world = new LCIMClient("world");
await world.Open();
world.OnMessageReceived = (conv, message) => {
Console.WriteLine(message);
};
//LCIMTextMessage textMessage = new LCIMTextMessage("hello, world");
//await conversation.Send(textMessage);
@ -77,10 +79,13 @@ namespace RealtimeConsole {
//LCIMTextMessage textMessage = new LCIMTextMessage("hello, world");
//await conversation.Send(textMessage);
LCFile file = new LCFile("avatar", "../../../Storage.Test/assets/hello.png");
await file.Save();
LCIMImageMessage imageMessage = new LCIMImageMessage(file);
await conversation.Send(imageMessage);
//LCFile file = new LCFile("avatar", "../../../Storage.Test/assets/hello.png");
//file.MetaData["width"] = 225;
//file.MetaData["height"] = 225;
//file.MetaData["size"] = 1186;
//await file.Save();
//LCIMImageMessage imageMessage = new LCIMImageMessage(file);
//await conversation.Send(imageMessage);
LCGeoPoint location = new LCGeoPoint(11, 12);
LCIMLocationMessage locationMessage = new LCIMLocationMessage(location);