* 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:
parent
29a84b8afb
commit
6781d4e94f
|
@ -77,7 +77,7 @@ namespace LeanCloud.Realtime {
|
||||||
};
|
};
|
||||||
GenericCommand command = client.NewCommand(CommandType.Conv, OpType.Count);
|
GenericCommand command = client.NewCommand(CommandType.Conv, OpType.Count);
|
||||||
command.ConvMessage = conv;
|
command.ConvMessage = conv;
|
||||||
GenericCommand response = await client.client.SendRequest(command);
|
GenericCommand response = await client.connection.SendRequest(command);
|
||||||
return response.ConvMessage.Count;
|
return response.ConvMessage.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ namespace LeanCloud.Realtime {
|
||||||
};
|
};
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Update);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Update);
|
||||||
request.ConvMessage = conv;
|
request.ConvMessage = conv;
|
||||||
GenericCommand response = await client.client.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
JsonObjectMessage attr = response.ConvMessage.AttrModified;
|
JsonObjectMessage attr = response.ConvMessage.AttrModified;
|
||||||
// 更新自定义属性
|
// 更新自定义属性
|
||||||
if (attr != null) {
|
if (attr != null) {
|
||||||
|
@ -122,7 +122,7 @@ namespace LeanCloud.Realtime {
|
||||||
|
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Add);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Add);
|
||||||
request.ConvMessage = conv;
|
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<string> allowedIds = response.ConvMessage.AllowedPids.ToList();
|
||||||
List<ErrorCommand> failedIds = response.ConvMessage.FailedPids.ToList();
|
List<ErrorCommand> failedIds = response.ConvMessage.FailedPids.ToList();
|
||||||
// TODO 转化为返回
|
// TODO 转化为返回
|
||||||
|
@ -147,7 +147,7 @@ namespace LeanCloud.Realtime {
|
||||||
|
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove);
|
||||||
request.ConvMessage = conv;
|
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<string> allowedIds = response.ConvMessage.AllowedPids.ToList();
|
||||||
List<ErrorCommand> failedIds = response.ConvMessage.FailedPids.ToList();
|
List<ErrorCommand> failedIds = response.ConvMessage.FailedPids.ToList();
|
||||||
// TODO 转化为返回
|
// TODO 转化为返回
|
||||||
|
@ -180,11 +180,17 @@ namespace LeanCloud.Realtime {
|
||||||
DirectCommand direct = new DirectCommand {
|
DirectCommand direct = new DirectCommand {
|
||||||
FromPeerId = client.ClientId,
|
FromPeerId = client.ClientId,
|
||||||
Cid = Id,
|
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();
|
GenericCommand command = client.NewDirectCommand();
|
||||||
command.DirectMessage = direct;
|
command.DirectMessage = direct;
|
||||||
GenericCommand response = await client.client.SendRequest(command);
|
GenericCommand response = await client.connection.SendRequest(command);
|
||||||
// 消息发送应答
|
// 消息发送应答
|
||||||
AckCommand ack = response.AckMessage;
|
AckCommand ack = response.AckMessage;
|
||||||
message.Id = ack.Uid;
|
message.Id = ack.Uid;
|
||||||
|
@ -202,7 +208,7 @@ namespace LeanCloud.Realtime {
|
||||||
};
|
};
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Mute);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Mute);
|
||||||
request.ConvMessage = conv;
|
request.ConvMessage = conv;
|
||||||
GenericCommand response = await client.client.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
IsMute = true;
|
IsMute = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +223,7 @@ namespace LeanCloud.Realtime {
|
||||||
};
|
};
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Unmute);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Unmute);
|
||||||
request.ConvMessage = conv;
|
request.ConvMessage = conv;
|
||||||
GenericCommand response = await client.client.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
IsMute = false;
|
IsMute = false;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -237,7 +243,7 @@ namespace LeanCloud.Realtime {
|
||||||
conv.M.AddRange(clientIds);
|
conv.M.AddRange(clientIds);
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.AddShutup);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.AddShutup);
|
||||||
request.ConvMessage = conv;
|
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);
|
return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +262,7 @@ namespace LeanCloud.Realtime {
|
||||||
conv.M.AddRange(clientIds);
|
conv.M.AddRange(clientIds);
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove);
|
||||||
request.ConvMessage = conv;
|
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);
|
return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +281,7 @@ namespace LeanCloud.Realtime {
|
||||||
blacklist.ToPids.AddRange(clientIds);
|
blacklist.ToPids.AddRange(clientIds);
|
||||||
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Block);
|
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Block);
|
||||||
request.BlacklistMessage = blacklist;
|
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);
|
return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +295,7 @@ namespace LeanCloud.Realtime {
|
||||||
blacklist.ToPids.AddRange(clientIds);
|
blacklist.ToPids.AddRange(clientIds);
|
||||||
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Unblock);
|
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Unblock);
|
||||||
request.BlacklistMessage = blacklist;
|
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);
|
return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +317,7 @@ namespace LeanCloud.Realtime {
|
||||||
patch.Patches.Add(item);
|
patch.Patches.Add(item);
|
||||||
GenericCommand request = client.NewCommand(CommandType.Patch, OpType.Modify);
|
GenericCommand request = client.NewCommand(CommandType.Patch, OpType.Modify);
|
||||||
request.PatchMessage = patch;
|
request.PatchMessage = patch;
|
||||||
GenericCommand response = await client.client.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,11 +341,10 @@ namespace LeanCloud.Realtime {
|
||||||
Timestamp = oldMessage.DeliveredTimestamp,
|
Timestamp = oldMessage.DeliveredTimestamp,
|
||||||
Recall = false,
|
Recall = false,
|
||||||
};
|
};
|
||||||
if (newMessage.GetText() != null) {
|
if (newMessage is LCIMTypedMessage typedMessage) {
|
||||||
item.Data = newMessage.GetText();
|
item.Data = JsonConvert.SerializeObject(typedMessage.Encode());
|
||||||
}
|
} else if (newMessage is LCIMBinaryMessage binaryMessage) {
|
||||||
if (newMessage.GetBytes() != null) {
|
item.BinaryMsg = ByteString.CopyFrom(binaryMessage.Data);
|
||||||
item.BinaryMsg = ByteString.CopyFrom(newMessage.GetBytes());
|
|
||||||
}
|
}
|
||||||
if (newMessage.MentionList != null) {
|
if (newMessage.MentionList != null) {
|
||||||
item.MentionPids.AddRange(newMessage.MentionList);
|
item.MentionPids.AddRange(newMessage.MentionList);
|
||||||
|
@ -350,7 +355,7 @@ namespace LeanCloud.Realtime {
|
||||||
patch.Patches.Add(item);
|
patch.Patches.Add(item);
|
||||||
GenericCommand request = client.NewCommand(CommandType.Patch, OpType.Modify);
|
GenericCommand request = client.NewCommand(CommandType.Patch, OpType.Modify);
|
||||||
request.PatchMessage = patch;
|
request.PatchMessage = patch;
|
||||||
GenericCommand response = await client.client.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,7 +376,7 @@ namespace LeanCloud.Realtime {
|
||||||
};
|
};
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.MemberInfoUpdate);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.MemberInfoUpdate);
|
||||||
request.ConvMessage = conv;
|
request.ConvMessage = conv;
|
||||||
GenericCommand response = await client.client.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
// TODO 同步 members
|
// TODO 同步 members
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
@ -422,7 +427,7 @@ namespace LeanCloud.Realtime {
|
||||||
};
|
};
|
||||||
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.QueryShutup);
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.QueryShutup);
|
||||||
request.ConvMessage = conv;
|
request.ConvMessage = conv;
|
||||||
GenericCommand response = await client.client.SendRequest(request);
|
GenericCommand response = await client.connection.SendRequest(request);
|
||||||
return new LCIMPageResult {
|
return new LCIMPageResult {
|
||||||
Results = response.ConvMessage.M.ToList(),
|
Results = response.ConvMessage.M.ToList(),
|
||||||
Next = response.ConvMessage.Next
|
Next = response.ConvMessage.Next
|
||||||
|
|
|
@ -245,7 +245,7 @@ namespace LeanCloud.Realtime {
|
||||||
conv.Where = JsonObjectMessage.Parser.ParseJson(where);
|
conv.Where = JsonObjectMessage.Parser.ParseJson(where);
|
||||||
}
|
}
|
||||||
command.ConvMessage = conv;
|
command.ConvMessage = conv;
|
||||||
GenericCommand response = await client.client.SendRequest(command);
|
GenericCommand response = await client.connection.SendRequest(command);
|
||||||
JsonObjectMessage results = response.ConvMessage.Results;
|
JsonObjectMessage results = response.ConvMessage.Results;
|
||||||
List<LCIMConversation> convList = null;
|
List<LCIMConversation> convList = null;
|
||||||
// TODO 反序列化
|
// TODO 反序列化
|
||||||
|
|
|
@ -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++;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,7 +9,7 @@ using LeanCloud.Common;
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime.Internal.WebSocket {
|
namespace LeanCloud.Realtime.Internal.WebSocket {
|
||||||
internal class LCWebSocketClient {
|
internal class LCWebSocketConnection {
|
||||||
private const int KEEP_ALIVE_INTERVAL = 10;
|
private const int KEEP_ALIVE_INTERVAL = 10;
|
||||||
private const int RECV_BUFFER_SIZE = 1024;
|
private const int RECV_BUFFER_SIZE = 1024;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace LeanCloud.Realtime.Internal.WebSocket {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal LCWebSocketClient() {
|
internal LCWebSocketConnection() {
|
||||||
responses = new Dictionary<int, TaskCompletionSource<GenericCommand>>();
|
responses = new Dictionary<int, TaskCompletionSource<GenericCommand>>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ using LeanCloud.Realtime.Internal;
|
||||||
|
|
||||||
namespace LeanCloud {
|
namespace LeanCloud {
|
||||||
public static class LCApplicationRealtimeExt {
|
public static class LCApplicationRealtimeExt {
|
||||||
static LCConnection connection;
|
|
||||||
|
|
||||||
public static async Task<LCIMClient> CreateIMClient(this LCApplication application, string clientId) {
|
public static async Task<LCIMClient> CreateIMClient(this LCApplication application, string clientId) {
|
||||||
if (string.IsNullOrEmpty(clientId)) {
|
if (string.IsNullOrEmpty(clientId)) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
public class LCIMClient {
|
public class LCIMClient {
|
||||||
internal LCWebSocketClient client;
|
internal LCWebSocketConnection connection;
|
||||||
|
|
||||||
private Dictionary<string, LCIMConversation> conversationDict;
|
private Dictionary<string, LCIMConversation> conversationDict;
|
||||||
|
|
||||||
|
@ -75,6 +75,10 @@ namespace LeanCloud.Realtime {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Action<LCIMConversation, LCIMMessage> OnMessageReceived {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
public LCIMClient(string clientId) {
|
public LCIMClient(string clientId) {
|
||||||
ClientId = clientId;
|
ClientId = clientId;
|
||||||
conversationDict = new Dictionary<string, LCIMConversation>();
|
conversationDict = new Dictionary<string, LCIMConversation>();
|
||||||
|
@ -85,14 +89,14 @@ namespace LeanCloud.Realtime {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task Open() {
|
public async Task Open() {
|
||||||
client = new LCWebSocketClient {
|
connection = new LCWebSocketConnection {
|
||||||
OnNotification = OnNotification
|
OnNotification = OnNotification
|
||||||
};
|
};
|
||||||
await client.Connect();
|
await connection.Connect();
|
||||||
// Open Session
|
// Open Session
|
||||||
GenericCommand request = NewCommand(CommandType.Session, OpType.Open);
|
GenericCommand request = NewCommand(CommandType.Session, OpType.Open);
|
||||||
request.SessionMessage = new SessionCommand();
|
request.SessionMessage = new SessionCommand();
|
||||||
GenericCommand response = await client.SendRequest(request);
|
GenericCommand response = await connection.SendRequest(request);
|
||||||
SessionToken = response.SessionMessage.St;
|
SessionToken = response.SessionMessage.St;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +105,7 @@ namespace LeanCloud.Realtime {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task Close() {
|
public async Task Close() {
|
||||||
await client.Close();
|
await connection.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LCIMChatRoom> CreateChatRoom(
|
public async Task<LCIMChatRoom> CreateChatRoom(
|
||||||
|
@ -154,7 +158,7 @@ namespace LeanCloud.Realtime {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
command.ConvMessage = conv;
|
command.ConvMessage = conv;
|
||||||
GenericCommand response = await client.SendRequest(command);
|
GenericCommand response = await connection.SendRequest(command);
|
||||||
LCIMConversation conversation = GetOrCreateConversation(response.ConvMessage.Cid);
|
LCIMConversation conversation = GetOrCreateConversation(response.ConvMessage.Cid);
|
||||||
conversation.MergeFrom(response.ConvMessage);
|
conversation.MergeFrom(response.ConvMessage);
|
||||||
conversationDict[conversation.Id] = conversation;
|
conversationDict[conversation.Id] = conversation;
|
||||||
|
@ -210,6 +214,9 @@ namespace LeanCloud.Realtime {
|
||||||
case CommandType.Conv:
|
case CommandType.Conv:
|
||||||
OnConversationNotification(notification);
|
OnConversationNotification(notification);
|
||||||
break;
|
break;
|
||||||
|
case CommandType.Direct:
|
||||||
|
OnDirectNotification(notification.DirectMessage);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
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) {
|
private LCIMConversation GetOrCreateConversation(string convId) {
|
||||||
if (!conversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
|
if (!conversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
|
||||||
conversation = new LCIMConversation(this);
|
conversation = new LCIMConversation(this);
|
||||||
|
|
|
@ -1,17 +1,32 @@
|
||||||
using LeanCloud.Storage;
|
using System.Collections.Generic;
|
||||||
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
public class LCIMAudioMessage : LCIMFileMessage {
|
public class LCIMAudioMessage : LCIMFileMessage {
|
||||||
public double Duration {
|
public double Duration {
|
||||||
get {
|
get {
|
||||||
if (double.TryParse("duration", out double duration)) {
|
if (double.TryParse(File.MetaData["duration"] as string, out double duration)) {
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal LCIMAudioMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
public LCIMAudioMessage(LCFile file) : base(file) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
public class LCIMBinaryMessage : LCIMMessage {
|
public class LCIMBinaryMessage : LCIMMessage {
|
||||||
public byte[] Data {
|
public byte[] Data {
|
||||||
get; set;
|
get; internal set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LCIMBinaryMessage(byte[] data) {
|
public LCIMBinaryMessage(byte[] data) {
|
||||||
Data = data;
|
Data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string Serialize() {
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override string GetText() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override byte[] GetBytes() {
|
|
||||||
return Data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using LeanCloud.Storage;
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
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;
|
File = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string Serialize() {
|
internal override Dictionary<string, object> Encode() {
|
||||||
if (File == null) {
|
if (File == null) {
|
||||||
throw new Exception("File MUST NOT be null before sent.");
|
throw new Exception("File MUST NOT be null before sent.");
|
||||||
}
|
}
|
||||||
File.MetaData["name"] = File.Name;
|
Dictionary<string, object> fileData = new Dictionary<string, object> {
|
||||||
File.MetaData["format"] = File.MimeType;
|
|
||||||
Dictionary<string, object> data = new Dictionary<string, object> {
|
|
||||||
{ "objId", File.ObjectId },
|
{ "objId", File.ObjectId },
|
||||||
{ "url", File.Url },
|
{ "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> {
|
Dictionary<string, object> data = base.Encode();
|
||||||
{ "_lcfile", data }
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using LeanCloud.Storage;
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
|
@ -21,7 +21,22 @@ namespace LeanCloud.Realtime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal LCIMImageMessage() : base() {
|
||||||
|
}
|
||||||
|
|
||||||
public LCIMImageMessage(LCFile file) : base(file) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,18 +8,29 @@ namespace LeanCloud.Realtime {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal LCIMLocationMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
public LCIMLocationMessage(LCGeoPoint locaction) : base(null) {
|
public LCIMLocationMessage(LCGeoPoint locaction) : base(null) {
|
||||||
Location = locaction;
|
Location = locaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string Serialize() {
|
internal override Dictionary<string, object> Encode() {
|
||||||
Dictionary<string, object> data = new Dictionary<string, object> {
|
Dictionary<string, object> data = base.Encode();
|
||||||
|
Dictionary<string, object> locationData = new Dictionary<string, object> {
|
||||||
{ "longitude", Location.Longitude },
|
{ "longitude", Location.Longitude },
|
||||||
{ "latitude", Location.Latitude }
|
{ "latitude", Location.Latitude }
|
||||||
};
|
};
|
||||||
return JsonConvert.SerializeObject(new Dictionary<string, object> {
|
data["_lcloc"] = locationData;
|
||||||
{ "_lcloc", data }
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using LeanCloud.Realtime.Protocol;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
public abstract class LCIMMessage {
|
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 {
|
public string ConversationId {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
@ -71,9 +79,11 @@ namespace LeanCloud.Realtime {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract string Serialize();
|
internal virtual void Decode(DirectCommand direct) {
|
||||||
|
ConversationId = direct.Cid;
|
||||||
internal abstract string GetText();
|
Id = direct.Id;
|
||||||
internal abstract byte[] GetBytes();
|
FromClientId = direct.FromPeerId;
|
||||||
|
DeliveredTimestamp = direct.Timestamp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,33 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
public class LCIMTextMessage : LCIMTypedMessage {
|
public class LCIMTextMessage : LCIMTypedMessage {
|
||||||
const int TextMessageType = -1;
|
|
||||||
|
|
||||||
public string Text {
|
public string Text {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LCIMTextMessage(string text) : base(TextMessageType) {
|
internal LCIMTextMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public LCIMTextMessage(string text) : base() {
|
||||||
Text = text;
|
Text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string Serialize() {
|
internal override Dictionary<string, object> Encode() {
|
||||||
return Text;
|
Dictionary<string, object> data = base.Encode();
|
||||||
|
if (!string.IsNullOrEmpty(Text)) {
|
||||||
|
data["_lctext"] = Text;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string GetText() {
|
protected override void DecodeMessageData(Dictionary<string, object> msgData) {
|
||||||
return Text;
|
base.DecodeMessageData(msgData);
|
||||||
|
if (msgData.TryGetValue("_lctext", out object value)) {
|
||||||
|
Text = value as string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal override int MessageType => TextMessageType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,32 @@
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using LeanCloud.Realtime.Protocol;
|
||||||
|
using LeanCloud.Storage.Internal;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
public class LCIMTypedMessage : LCIMMessage {
|
public abstract class LCIMTypedMessage : LCIMMessage {
|
||||||
protected int type;
|
protected LCIMTypedMessage() {
|
||||||
|
|
||||||
protected LCIMTypedMessage(int type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string Serialize() {
|
internal virtual int MessageType {
|
||||||
throw new NotImplementedException();
|
get; private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override string GetText() {
|
internal virtual Dictionary<string, object> Encode() {
|
||||||
return null;
|
return new Dictionary<string, object> {
|
||||||
|
{ "_lctype", MessageType }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override byte[] GetBytes() {
|
internal override void Decode(DirectCommand direct) {
|
||||||
return null;
|
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"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using LeanCloud.Storage;
|
using System.Collections.Generic;
|
||||||
|
using LeanCloud.Storage;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
public class LCIMVideoMessage : LCIMFileMessage {
|
public class LCIMVideoMessage : LCIMFileMessage {
|
||||||
|
@ -11,8 +12,23 @@ namespace LeanCloud.Realtime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal LCIMVideoMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
public LCIMVideoMessage(LCFile file) : base(file) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace LeanCloud.Storage.Internal.Http {
|
||||||
LCHttpUtils.PrintResponse(response, resultString);
|
LCHttpUtils.PrintResponse(response, resultString);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode) {
|
if (response.IsSuccessStatusCode) {
|
||||||
T ret = JsonConvert.DeserializeObject<T>(resultString, new LeanCloudJsonConverter());
|
T ret = JsonConvert.DeserializeObject<T>(resultString, new LCJsonConverter());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
throw HandleErrorResponse(response.StatusCode, resultString);
|
throw HandleErrorResponse(response.StatusCode, resultString);
|
||||||
|
@ -94,7 +94,7 @@ namespace LeanCloud.Storage.Internal.Http {
|
||||||
LCHttpUtils.PrintResponse(response, resultString);
|
LCHttpUtils.PrintResponse(response, resultString);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode) {
|
if (response.IsSuccessStatusCode) {
|
||||||
T ret = JsonConvert.DeserializeObject<T>(resultString, new LeanCloudJsonConverter());
|
T ret = JsonConvert.DeserializeObject<T>(resultString, new LCJsonConverter());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
throw HandleErrorResponse(response.StatusCode, resultString);
|
throw HandleErrorResponse(response.StatusCode, resultString);
|
||||||
|
@ -127,7 +127,7 @@ namespace LeanCloud.Storage.Internal.Http {
|
||||||
LCHttpUtils.PrintResponse(response, resultString);
|
LCHttpUtils.PrintResponse(response, resultString);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode) {
|
if (response.IsSuccessStatusCode) {
|
||||||
T ret = JsonConvert.DeserializeObject<T>(resultString, new LeanCloudJsonConverter());
|
T ret = JsonConvert.DeserializeObject<T>(resultString, new LCJsonConverter());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
throw HandleErrorResponse(response.StatusCode, resultString);
|
throw HandleErrorResponse(response.StatusCode, resultString);
|
||||||
|
@ -150,7 +150,7 @@ namespace LeanCloud.Storage.Internal.Http {
|
||||||
LCHttpUtils.PrintResponse(response, resultString);
|
LCHttpUtils.PrintResponse(response, resultString);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
throw HandleErrorResponse(response.StatusCode, resultString);
|
throw HandleErrorResponse(response.StatusCode, resultString);
|
||||||
|
@ -161,7 +161,7 @@ namespace LeanCloud.Storage.Internal.Http {
|
||||||
string message = responseContent;
|
string message = responseContent;
|
||||||
try {
|
try {
|
||||||
// 尝试获取 LeanCloud 返回错误信息
|
// 尝试获取 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"];
|
code = (int)error["code"];
|
||||||
message = error["error"].ToString();
|
message = error["error"].ToString();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal {
|
namespace LeanCloud.Storage.Internal {
|
||||||
public class LeanCloudJsonConverter : JsonConverter {
|
public class LCJsonConverter : JsonConverter {
|
||||||
public override bool CanConvert(Type objectType) {
|
public override bool CanConvert(Type objectType) {
|
||||||
return objectType == typeof(object);
|
return objectType == typeof(object);
|
||||||
}
|
}
|
|
@ -86,7 +86,7 @@ namespace LeanCloud.Storage {
|
||||||
if (string.IsNullOrEmpty(objectId)) {
|
if (string.IsNullOrEmpty(objectId)) {
|
||||||
throw new ArgumentNullException(nameof(objectId));
|
throw new ArgumentNullException(nameof(objectId));
|
||||||
}
|
}
|
||||||
LCObject obj = new LCObject(className);
|
LCObject obj = Create(className);
|
||||||
obj.data.ObjectId = objectId;
|
obj.data.ObjectId = objectId;
|
||||||
obj.isNew = false;
|
obj.isNew = false;
|
||||||
return obj;
|
return obj;
|
||||||
|
|
|
@ -36,26 +36,28 @@ namespace RealtimeConsole {
|
||||||
};
|
};
|
||||||
LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com");
|
LCApplication.Initialize("ikGGdRE2YcVOemAaRbgp1xGJ-gzGzoHsz", "NUKmuRbdAhg1vrb2wexYo1jo", "https://ikggdre2.lc-cn-n1-shared.com");
|
||||||
|
|
||||||
LCIMClient client = new LCIMClient("hello123");
|
LCIMClient hello = new LCIMClient("hello");
|
||||||
|
|
||||||
try {
|
await hello.Open();
|
||||||
await client.Open();
|
|
||||||
Console.WriteLine($"End {Thread.CurrentThread.ManagedThreadId}");
|
|
||||||
} catch (Exception e) {
|
|
||||||
Console.WriteLine(e.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
client.OnInvited = (conv, initBy) => {
|
hello.OnInvited = (conv, initBy) => {
|
||||||
Console.WriteLine($"on invited: {initBy}");
|
Console.WriteLine($"on invited: {initBy}");
|
||||||
};
|
};
|
||||||
|
|
||||||
client.OnMembersJoined = (conv, memberList, initBy) => {
|
hello.OnMembersJoined = (conv, memberList, initBy) => {
|
||||||
Console.WriteLine($"on members joined: {initBy}");
|
Console.WriteLine($"on members joined: {initBy}");
|
||||||
};
|
};
|
||||||
|
|
||||||
List<string> memberIdList = new List<string> { "world", "code" };
|
List<string> memberIdList = new List<string> { "world", "code" };
|
||||||
string name = Guid.NewGuid().ToString();
|
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");
|
//LCIMTextMessage textMessage = new LCIMTextMessage("hello, world");
|
||||||
//await conversation.Send(textMessage);
|
//await conversation.Send(textMessage);
|
||||||
|
@ -77,10 +79,13 @@ namespace RealtimeConsole {
|
||||||
//LCIMTextMessage textMessage = new LCIMTextMessage("hello, world");
|
//LCIMTextMessage textMessage = new LCIMTextMessage("hello, world");
|
||||||
//await conversation.Send(textMessage);
|
//await conversation.Send(textMessage);
|
||||||
|
|
||||||
LCFile file = new LCFile("avatar", "../../../Storage.Test/assets/hello.png");
|
//LCFile file = new LCFile("avatar", "../../../Storage.Test/assets/hello.png");
|
||||||
await file.Save();
|
//file.MetaData["width"] = 225;
|
||||||
LCIMImageMessage imageMessage = new LCIMImageMessage(file);
|
//file.MetaData["height"] = 225;
|
||||||
await conversation.Send(imageMessage);
|
//file.MetaData["size"] = 1186;
|
||||||
|
//await file.Save();
|
||||||
|
//LCIMImageMessage imageMessage = new LCIMImageMessage(file);
|
||||||
|
//await conversation.Send(imageMessage);
|
||||||
|
|
||||||
LCGeoPoint location = new LCGeoPoint(11, 12);
|
LCGeoPoint location = new LCGeoPoint(11, 12);
|
||||||
LCIMLocationMessage locationMessage = new LCIMLocationMessage(location);
|
LCIMLocationMessage locationMessage = new LCIMLocationMessage(location);
|
||||||
|
|
Loading…
Reference in New Issue