* LCIMConversation.cs: chore: 会话自定义属性
* LCIMClient.cs: * Conversation.cs: * LCDecoder.cs: * LCEncoder.cs: * LCEqualCondition.cs: * ILCQueryCondition.cs: * LCRelatedCondition.cs: * LCIMConversationQuery.cs: * LCOperationCondition.cs: * LCIMTemporaryConversation.cs: * LCCompositionalCondition.cs:
parent
6d4befe446
commit
05e642237e
|
@ -2,7 +2,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using LeanCloud.Realtime.Protocol;
|
using LeanCloud.Realtime.Protocol;
|
||||||
|
using LeanCloud.Storage.Internal.Codec;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
public class LCIMConversation {
|
public class LCIMConversation {
|
||||||
|
@ -11,7 +13,11 @@ namespace LeanCloud.Realtime {
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name {
|
public string Name {
|
||||||
get; set;
|
get {
|
||||||
|
return this["name"] as string;
|
||||||
|
} set {
|
||||||
|
this["name"] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string CreatorId {
|
public string CreatorId {
|
||||||
|
@ -30,7 +36,22 @@ namespace LeanCloud.Realtime {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsMute => false;
|
public DateTime LastMessageAt {
|
||||||
|
get; internal set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object this[string key] {
|
||||||
|
get {
|
||||||
|
return customProperties[key];
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
customProperties[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsMute {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual bool IsSystem => false;
|
public virtual bool IsSystem => false;
|
||||||
|
|
||||||
|
@ -38,39 +59,122 @@ namespace LeanCloud.Realtime {
|
||||||
|
|
||||||
private readonly LCIMClient client;
|
private readonly LCIMClient client;
|
||||||
|
|
||||||
|
private Dictionary<string, object> customProperties;
|
||||||
|
|
||||||
internal LCIMConversation(LCIMClient client) {
|
internal LCIMConversation(LCIMClient client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
customProperties = new Dictionary<string, object>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set(string key, object value) {
|
/// <summary>
|
||||||
// 自定义属性
|
/// 获取对话人数,或暂态对话的在线人数
|
||||||
|
/// </summary>
|
||||||
}
|
/// <returns></returns>
|
||||||
|
|
||||||
public async Task<int> Count() {
|
public async Task<int> Count() {
|
||||||
return 0;
|
ConvCommand conv = new ConvCommand {
|
||||||
|
Cid = Id,
|
||||||
|
};
|
||||||
|
GenericCommand command = client.NewCommand(CommandType.Conv, OpType.Count);
|
||||||
|
command.ConvMessage = conv;
|
||||||
|
GenericCommand response = await client.client.SendRequest(command);
|
||||||
|
return response.ConvMessage.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LCIMConversation> Save() {
|
public async Task<LCIMConversation> Save() {
|
||||||
|
ConvCommand conv = new ConvCommand {
|
||||||
|
Cid = Id,
|
||||||
|
};
|
||||||
|
// 注意序列化是否与存储一致
|
||||||
|
string json = JsonConvert.SerializeObject(LCEncoder.Encode(customProperties));
|
||||||
|
conv.Attr = new JsonObjectMessage {
|
||||||
|
Data = json
|
||||||
|
};
|
||||||
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Update);
|
||||||
|
request.ConvMessage = conv;
|
||||||
|
GenericCommand response = await client.client.SendRequest(request);
|
||||||
|
JsonObjectMessage attr = response.ConvMessage.AttrModified;
|
||||||
|
// 更新自定义属性
|
||||||
|
if (attr != null) {
|
||||||
|
Dictionary<string, object> data = JsonConvert.DeserializeObject<Dictionary<string, object>>(attr.Data);
|
||||||
|
Dictionary<string, object> objectData = LCDecoder.Decode(data) as Dictionary<string, object>;
|
||||||
|
foreach (KeyValuePair<string, object> kv in objectData) {
|
||||||
|
customProperties[kv.Key] = kv.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Add(List<string> clientIdList) {
|
/// <summary>
|
||||||
|
/// 添加用户到对话
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientIds">用户 Id</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<LCIMConversation> Add(IEnumerable<string> clientIds) {
|
||||||
|
if (clientIds == null || clientIds.Count() == 0) {
|
||||||
|
throw new ArgumentNullException(nameof(clientIds));
|
||||||
|
}
|
||||||
|
ConvCommand conv = new ConvCommand {
|
||||||
|
Cid = Id,
|
||||||
|
};
|
||||||
|
conv.M.AddRange(clientIds);
|
||||||
|
// TODO 签名参数
|
||||||
|
|
||||||
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Add);
|
||||||
|
request.ConvMessage = conv;
|
||||||
|
GenericCommand response = await client.client.SendRequest(request);
|
||||||
|
List<string> allowedIds = response.ConvMessage.AllowedPids.ToList();
|
||||||
|
List<ErrorCommand> failedIds = response.ConvMessage.FailedPids.ToList();
|
||||||
|
// TODO 转化为返回
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Remove(List<string> removeIdList) {
|
/// <summary>
|
||||||
|
/// 删除用户
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="removeIds">用户 Id</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<LCIMConversation> Remove(IEnumerable<string> removeIds) {
|
||||||
|
if (removeIds == null || removeIds.Count() == 0) {
|
||||||
|
throw new ArgumentNullException(nameof(removeIds));
|
||||||
|
}
|
||||||
|
ConvCommand conv = new ConvCommand {
|
||||||
|
Cid = Id,
|
||||||
|
};
|
||||||
|
conv.M.AddRange(removeIds);
|
||||||
|
// TODO 签名参数
|
||||||
|
|
||||||
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove);
|
||||||
|
request.ConvMessage = conv;
|
||||||
|
GenericCommand response = await client.client.SendRequest(request);
|
||||||
|
List<string> allowedIds = response.ConvMessage.AllowedPids.ToList();
|
||||||
|
List<ErrorCommand> failedIds = response.ConvMessage.FailedPids.ToList();
|
||||||
|
// TODO 转化为返回
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加入对话
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<LCIMConversation> Join() {
|
public async Task<LCIMConversation> Join() {
|
||||||
return this;
|
return await Add(new string[] { client.ClientId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 离开对话
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<LCIMConversation> Quit() {
|
public async Task<LCIMConversation> Quit() {
|
||||||
return this;
|
return await Remove(new string[] { client.ClientId });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送消息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<LCIMMessage> Send(LCIMMessage message) {
|
public async Task<LCIMMessage> Send(LCIMMessage message) {
|
||||||
DirectCommand direct = new DirectCommand {
|
DirectCommand direct = new DirectCommand {
|
||||||
FromPeerId = client.ClientId,
|
FromPeerId = client.ClientId,
|
||||||
|
@ -88,30 +192,108 @@ namespace LeanCloud.Realtime {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LCIMRecalledMessage> Recall(LCIMMessage message) {
|
public async Task<LCIMRecalledMessage> Recall(LCIMMessage message) {
|
||||||
|
if (message == null) {
|
||||||
|
throw new ArgumentNullException(nameof(message));
|
||||||
|
}
|
||||||
|
PatchCommand patch = new PatchCommand();
|
||||||
|
PatchItem item = new PatchItem {
|
||||||
|
Cid = Id,
|
||||||
|
Mid = message.Id,
|
||||||
|
Recall = true
|
||||||
|
};
|
||||||
|
patch.Patches.Add(item);
|
||||||
|
GenericCommand request = client.NewCommand(CommandType.Patch, OpType.Modify);
|
||||||
|
request.PatchMessage = patch;
|
||||||
|
GenericCommand response = await client.client.SendRequest(request);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 静音
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<LCIMConversation> Mute() {
|
public async Task<LCIMConversation> Mute() {
|
||||||
|
ConvCommand conv = new ConvCommand {
|
||||||
|
Cid = Id
|
||||||
|
};
|
||||||
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Mute);
|
||||||
|
request.ConvMessage = conv;
|
||||||
|
GenericCommand response = await client.client.SendRequest(request);
|
||||||
|
IsMute = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取消静音
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<LCIMConversation> Unmute() {
|
public async Task<LCIMConversation> Unmute() {
|
||||||
|
ConvCommand conv = new ConvCommand {
|
||||||
|
Cid = Id
|
||||||
|
};
|
||||||
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Unmute);
|
||||||
|
request.ConvMessage = conv;
|
||||||
|
GenericCommand response = await client.client.SendRequest(request);
|
||||||
|
IsMute = false;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task MuteMemberList(List<string> clientIdList) {
|
/// <summary>
|
||||||
|
/// 禁言
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientIds"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task MuteMembers(IEnumerable<string> clientIds) {
|
||||||
|
if (clientIds == null || clientIds.Count() == 0) {
|
||||||
|
throw new ArgumentNullException(nameof(clientIds));
|
||||||
|
}
|
||||||
|
ConvCommand conv = new ConvCommand {
|
||||||
|
Cid = Id
|
||||||
|
};
|
||||||
|
conv.M.AddRange(clientIds);
|
||||||
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.AddShutup);
|
||||||
|
request.ConvMessage = conv;
|
||||||
|
GenericCommand response = await client.client.SendRequest(request);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UnmuteMemberList(List<string> clientIdList) {
|
/// <summary>
|
||||||
|
/// 取消禁言
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientIdList"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task UnmuteMembers(IEnumerable<string> clientIds) {
|
||||||
|
if (clientIds == null || clientIds.Count() == 0) {
|
||||||
|
throw new ArgumentNullException(nameof(clientIds));
|
||||||
|
}
|
||||||
|
ConvCommand conv = new ConvCommand {
|
||||||
|
Cid = Id
|
||||||
|
};
|
||||||
|
conv.M.AddRange(clientIds);
|
||||||
|
GenericCommand request = client.NewCommand(CommandType.Conv, OpType.Remove);
|
||||||
|
request.ConvMessage = conv;
|
||||||
|
GenericCommand response = await client.client.SendRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task BlockMemberList(List<string> clientIdList) {
|
/// <summary>
|
||||||
|
/// 将用户加入黑名单
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientIds"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task BlockMembers(IEnumerable<string> clientIds) {
|
||||||
|
if (clientIds == null || clientIds.Count() == 0) {
|
||||||
|
throw new ArgumentNullException(nameof(clientIds));
|
||||||
|
}
|
||||||
|
BlacklistCommand blacklist = new BlacklistCommand {
|
||||||
|
SrcCid = Id,
|
||||||
|
|
||||||
|
};
|
||||||
|
GenericCommand request = client.NewCommand(CommandType.Blacklist, OpType.Block);
|
||||||
|
request.BlacklistMessage = blacklist;
|
||||||
|
await client.client.SendRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UnblockMemberList(List<string> clientIdList) {
|
public async Task UnblockMembers(IEnumerable<string> clientIds) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +306,10 @@ namespace LeanCloud.Realtime {
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LCIMConversationMemberInfo> GetMemberInfo(string memberId) {
|
public async Task<LCIMConversationMemberInfo> GetMemberInfo(string memberId) {
|
||||||
|
if (string.IsNullOrEmpty(memberId)) {
|
||||||
|
throw new ArgumentNullException(nameof(memberId));
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,256 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using LeanCloud.Storage.Internal.Query;
|
||||||
|
using LeanCloud.Realtime.Protocol;
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
public class LCIMConversationQuery {
|
public class LCIMConversationQuery {
|
||||||
public LCIMConversationQuery() {
|
private LCCompositionalCondition condition;
|
||||||
|
|
||||||
|
private LCIMClient client;
|
||||||
|
|
||||||
|
public LCIMConversationQuery(LCIMClient client) {
|
||||||
|
condition = new LCCompositionalCondition();
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 等于
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereEqualTo(string key, object value) {
|
||||||
|
condition.WhereEqualTo(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 不等于
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereNotEqualTo(string key, object value) {
|
||||||
|
condition.WhereNotEqualTo(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 包含
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="values"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereContainedIn(string key, IEnumerable values) {
|
||||||
|
condition.WhereContainedIn(key, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 包含全部
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="values"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereContainsAll(string key, IEnumerable values) {
|
||||||
|
condition.WhereContainsAll(key, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 存在
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereExists(string key) {
|
||||||
|
condition.WhereExists(key);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 不存在
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereDoesNotExist(string key) {
|
||||||
|
condition.WhereDoesNotExist(key);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 长度等于
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="size"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereSizeEqualTo(string key, int size) {
|
||||||
|
condition.WhereSizeEqualTo(key, size);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 大于
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereGreaterThan(string key, object value) {
|
||||||
|
condition.WhereGreaterThan(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 大于等于
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereGreaterThanOrEqualTo(string key, object value) {
|
||||||
|
condition.WhereGreaterThanOrEqualTo(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 小于
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereLessThan(string key, object value) {
|
||||||
|
condition.WhereLessThan(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 小于等于
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereLessThanOrEqualTo(string key, object value) {
|
||||||
|
condition.WhereLessThanOrEqualTo(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 前缀
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="prefix"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereStartsWith(string key, string prefix) {
|
||||||
|
condition.WhereStartsWith(key, prefix);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 后缀
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="suffix"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereEndsWith(string key, string suffix) {
|
||||||
|
condition.WhereEndsWith(key, suffix);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 字符串包含
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="subString"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery WhereContains(string key, string subString) {
|
||||||
|
condition.WhereContains(key, subString);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按 key 升序
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery OrderBy(string key) {
|
||||||
|
condition.OrderBy(key);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按 key 降序
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery OrderByDescending(string key) {
|
||||||
|
condition.OrderByDescending(key);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 拉取 key 的完整对象
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery Include(string key) {
|
||||||
|
condition.Include(key);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 包含 key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery Select(string key) {
|
||||||
|
condition.Select(key);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 跳过
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery Skip(int value) {
|
||||||
|
condition.Skip = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 限制数量
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery Limit(int value) {
|
||||||
|
condition.Limit = value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool WithLastMessageRefreshed {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<LCIMConversation>> Find() {
|
||||||
|
GenericCommand command = new GenericCommand {
|
||||||
|
Cmd = CommandType.Conv,
|
||||||
|
Op = OpType.Query,
|
||||||
|
AppId = LCApplication.AppId,
|
||||||
|
PeerId = client.ClientId,
|
||||||
|
};
|
||||||
|
ConvCommand conv = new ConvCommand();
|
||||||
|
string where = condition.BuildWhere();
|
||||||
|
if (!string.IsNullOrEmpty(where)) {
|
||||||
|
conv.Where = JsonObjectMessage.Parser.ParseJson(where);
|
||||||
|
}
|
||||||
|
command.ConvMessage = conv;
|
||||||
|
GenericCommand response = await client.client.SendRequest(command);
|
||||||
|
JsonObjectMessage results = response.ConvMessage.Results;
|
||||||
|
List<LCIMConversation> convList = null;
|
||||||
|
// TODO 反序列化
|
||||||
|
|
||||||
|
return convList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,16 @@
|
||||||
|
|
||||||
namespace LeanCloud.Realtime {
|
namespace LeanCloud.Realtime {
|
||||||
public class LCIMTemporaryConversation : LCIMConversation {
|
public class LCIMTemporaryConversation : LCIMConversation {
|
||||||
|
public DateTime ExpiredAt {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsExpired {
|
||||||
|
get {
|
||||||
|
return DateTime.Now > ExpiredAt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public LCIMTemporaryConversation(LCIMClient client) : base(client) {
|
public LCIMTemporaryConversation(LCIMClient client) : base(client) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,24 +24,24 @@ namespace LeanCloud.Realtime {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 当前客户端被服务端强行下线
|
|
||||||
/// </summary>
|
|
||||||
public Action OnClosed {
|
|
||||||
get; set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 客户端连接断开
|
/// 客户端连接断开
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action OnDisconnected {
|
public Action OnPaused {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 客户端连接恢复正常
|
/// 客户端连接恢复正常
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Action OnReconnect {
|
public Action OnResume {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前客户端被服务端强行下线
|
||||||
|
/// </summary>
|
||||||
|
public Action OnOffline {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,10 @@ namespace LeanCloud.Realtime {
|
||||||
conversationDict = new Dictionary<string, LCIMConversation>();
|
conversationDict = new Dictionary<string, LCIMConversation>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task Open() {
|
public async Task Open() {
|
||||||
client = new LCWebSocketClient {
|
client = new LCWebSocketClient {
|
||||||
OnNotification = OnNotification
|
OnNotification = OnNotification
|
||||||
|
@ -86,6 +90,14 @@ namespace LeanCloud.Realtime {
|
||||||
await client.SendRequest(command);
|
await client.SendRequest(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 关闭
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task Close() {
|
||||||
|
await client.Close();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<LCIMChatRoom> CreateChatRoom(
|
public async Task<LCIMChatRoom> CreateChatRoom(
|
||||||
string name,
|
string name,
|
||||||
Dictionary<string, object> properties = null) {
|
Dictionary<string, object> properties = null) {
|
||||||
|
@ -143,16 +155,48 @@ namespace LeanCloud.Realtime {
|
||||||
return conversation;
|
return conversation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取某个特定的对话
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task<LCIMConversation> GetConversation(string id) {
|
public async Task<LCIMConversation> GetConversation(string id) {
|
||||||
|
if (string.IsNullOrEmpty(id)) {
|
||||||
|
throw new ArgumentNullException(nameof(id));
|
||||||
|
}
|
||||||
|
LCIMConversationQuery query = GetQuery();
|
||||||
|
query.WhereEqualTo("objectId", id)
|
||||||
|
.Limit(1);
|
||||||
|
List<LCIMConversation> results = await query.Find();
|
||||||
|
if (results == null || results.Count < 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
return results[0];
|
||||||
public async Task<List<LCIMConversation>> GetConversationList(List<string> idList) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<LCIMConversationQuery> GetConversationQuery() {
|
/// <summary>
|
||||||
return null;
|
/// 获取某些特定的对话
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ids"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<List<LCIMConversation>> GetConversationList(IEnumerable<string> ids) {
|
||||||
|
if (ids == null || ids.Count() == 0) {
|
||||||
|
throw new ArgumentNullException(nameof(ids));
|
||||||
|
}
|
||||||
|
List<LCIMConversation> conversationList = new List<LCIMConversation>();
|
||||||
|
foreach (string id in ids) {
|
||||||
|
LCIMConversation conversation = await GetConversation(id);
|
||||||
|
conversationList.Add(conversation);
|
||||||
|
}
|
||||||
|
return conversationList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取对话查询对象
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public LCIMConversationQuery GetQuery() {
|
||||||
|
return new LCIMConversationQuery(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnNotification(GenericCommand notification) {
|
private void OnNotification(GenericCommand notification) {
|
||||||
|
@ -166,12 +210,22 @@ namespace LeanCloud.Realtime {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnConversationNotification(GenericCommand notification) {
|
private void OnConversationNotification(GenericCommand notification) {
|
||||||
|
ConvCommand conv = notification.ConvMessage;
|
||||||
switch (notification.Op) {
|
switch (notification.Op) {
|
||||||
case OpType.Joined:
|
case OpType.Joined:
|
||||||
OnConversationJoined(notification.ConvMessage);
|
OnConversationJoined(conv);
|
||||||
break;
|
break;
|
||||||
case OpType.MembersJoined:
|
case OpType.MembersJoined:
|
||||||
OnConversationMembersJoined(notification.ConvMessage);
|
OnConversationMembersJoined(conv);
|
||||||
|
break;
|
||||||
|
case OpType.Left:
|
||||||
|
OnConversationLeft(conv);
|
||||||
|
break;
|
||||||
|
case OpType.MembersLeft:
|
||||||
|
OnConversationMemberLeft(conv);
|
||||||
|
break;
|
||||||
|
case OpType.Updated:
|
||||||
|
OnPropertiesUpdated(conv);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -190,6 +244,26 @@ namespace LeanCloud.Realtime {
|
||||||
OnMembersJoined?.Invoke(conversation, conv.M.ToList(), conv.InitBy);
|
OnMembersJoined?.Invoke(conversation, conv.M.ToList(), conv.InitBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnConversationLeft(ConvCommand conv) {
|
||||||
|
if (conversationDict.TryGetValue(conv.Cid, out LCIMConversation conversation)) {
|
||||||
|
OnKicked?.Invoke(conversation, conv.InitBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnConversationMemberLeft(ConvCommand conv) {
|
||||||
|
if (conversationDict.TryGetValue(conv.Cid, out LCIMConversation conversation)) {
|
||||||
|
List<string> leftIdList = conv.M.ToList();
|
||||||
|
OnMembersLeft?.Invoke(conversation, leftIdList, conv.InitBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPropertiesUpdated(ConvCommand conv) {
|
||||||
|
if (conversationDict.TryGetValue(conv.Cid, out LCIMConversation conversation)) {
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -4,8 +4,8 @@ using System.Collections.Generic;
|
||||||
using LeanCloud.Storage.Internal.Object;
|
using LeanCloud.Storage.Internal.Object;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal.Codec {
|
namespace LeanCloud.Storage.Internal.Codec {
|
||||||
internal static class LCDecoder {
|
public static class LCDecoder {
|
||||||
internal static object Decode(object obj) {
|
public static object Decode(object obj) {
|
||||||
if (obj is IDictionary dict) {
|
if (obj is IDictionary dict) {
|
||||||
if (dict.Contains("__type")) {
|
if (dict.Contains("__type")) {
|
||||||
string type = dict["__type"].ToString();
|
string type = dict["__type"].ToString();
|
||||||
|
|
|
@ -5,8 +5,8 @@ using LeanCloud.Storage.Internal.Operation;
|
||||||
using LeanCloud.Storage.Internal.Query;
|
using LeanCloud.Storage.Internal.Query;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal.Codec {
|
namespace LeanCloud.Storage.Internal.Codec {
|
||||||
internal static class LCEncoder {
|
public static class LCEncoder {
|
||||||
internal static object Encode(object obj) {
|
public static object Encode(object obj) {
|
||||||
if (obj is DateTime dateTime) {
|
if (obj is DateTime dateTime) {
|
||||||
return EncodeDateTime(dateTime);
|
return EncodeDateTime(dateTime);
|
||||||
} else if (obj is byte[] bytes) {
|
} else if (obj is byte[] bytes) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal.Query {
|
namespace LeanCloud.Storage.Internal.Query {
|
||||||
internal interface ILCQueryCondition {
|
public interface ILCQueryCondition {
|
||||||
bool Equals(ILCQueryCondition other);
|
bool Equals(ILCQueryCondition other);
|
||||||
Dictionary<string, object> Encode();
|
Dictionary<string, object> Encode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@ using Newtonsoft.Json;
|
||||||
using LeanCloud.Storage.Internal.Codec;
|
using LeanCloud.Storage.Internal.Codec;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal.Query {
|
namespace LeanCloud.Storage.Internal.Query {
|
||||||
internal class LCCompositionalCondition : ILCQueryCondition {
|
public class LCCompositionalCondition : ILCQueryCondition {
|
||||||
internal const string And = "$and";
|
public const string And = "$and";
|
||||||
internal const string Or = "$or";
|
public const string Or = "$or";
|
||||||
|
|
||||||
readonly string composition;
|
readonly string composition;
|
||||||
|
|
||||||
|
@ -16,93 +16,93 @@ namespace LeanCloud.Storage.Internal.Query {
|
||||||
HashSet<string> includes;
|
HashSet<string> includes;
|
||||||
HashSet<string> selectedKeys;
|
HashSet<string> selectedKeys;
|
||||||
|
|
||||||
internal int Skip {
|
public int Skip {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal int Limit {
|
public int Limit {
|
||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal LCCompositionalCondition(string composition = And) {
|
public LCCompositionalCondition(string composition = And) {
|
||||||
this.composition = composition;
|
this.composition = composition;
|
||||||
Skip = 0;
|
Skip = 0;
|
||||||
Limit = 30;
|
Limit = 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询条件
|
// 查询条件
|
||||||
internal void WhereEqualTo(string key, object value) {
|
public void WhereEqualTo(string key, object value) {
|
||||||
Add(new LCEqualCondition(key, value));
|
Add(new LCEqualCondition(key, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereNotEqualTo(string key, object value) {
|
public void WhereNotEqualTo(string key, object value) {
|
||||||
AddOperation(key, "$ne", value);
|
AddOperation(key, "$ne", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereContainedIn(string key, IEnumerable values) {
|
public void WhereContainedIn(string key, IEnumerable values) {
|
||||||
AddOperation(key, "$in", values);
|
AddOperation(key, "$in", values);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereNotContainedIn(string key, IEnumerable values) {
|
public void WhereNotContainedIn(string key, IEnumerable values) {
|
||||||
AddOperation(key, "nin", values);
|
AddOperation(key, "nin", values);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereContainsAll(string key, IEnumerable values) {
|
public void WhereContainsAll(string key, IEnumerable values) {
|
||||||
AddOperation(key, "$all", values);
|
AddOperation(key, "$all", values);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereExists(string key) {
|
public void WhereExists(string key) {
|
||||||
AddOperation(key, "$exists", true);
|
AddOperation(key, "$exists", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereDoesNotExist(string key) {
|
public void WhereDoesNotExist(string key) {
|
||||||
AddOperation(key, "$exists", false);
|
AddOperation(key, "$exists", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereSizeEqualTo(string key, int size) {
|
public void WhereSizeEqualTo(string key, int size) {
|
||||||
AddOperation(key, "$size", size);
|
AddOperation(key, "$size", size);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereGreaterThan(string key, object value) {
|
public void WhereGreaterThan(string key, object value) {
|
||||||
AddOperation(key, "$gt", value);
|
AddOperation(key, "$gt", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereGreaterThanOrEqualTo(string key, object value) {
|
public void WhereGreaterThanOrEqualTo(string key, object value) {
|
||||||
AddOperation(key, "$gte", value);
|
AddOperation(key, "$gte", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereLessThan(string key, object value) {
|
public void WhereLessThan(string key, object value) {
|
||||||
AddOperation(key, "$lt", value);
|
AddOperation(key, "$lt", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereLessThanOrEqualTo(string key, object value) {
|
public void WhereLessThanOrEqualTo(string key, object value) {
|
||||||
AddOperation(key, "$lte", value);
|
AddOperation(key, "$lte", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereNear(string key, LCGeoPoint point) {
|
public void WhereNear(string key, LCGeoPoint point) {
|
||||||
AddOperation(key, "$nearSphere", point);
|
AddOperation(key, "$nearSphere", point);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereWithinGeoBox(string key, LCGeoPoint southwest, LCGeoPoint northeast) {
|
public void WhereWithinGeoBox(string key, LCGeoPoint southwest, LCGeoPoint northeast) {
|
||||||
Dictionary<string, object> value = new Dictionary<string, object> {
|
Dictionary<string, object> value = new Dictionary<string, object> {
|
||||||
{ "$box", new List<object> { southwest, northeast } }
|
{ "$box", new List<object> { southwest, northeast } }
|
||||||
};
|
};
|
||||||
AddOperation(key, "$within", value);
|
AddOperation(key, "$within", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereRelatedTo(LCObject parent, string key) {
|
public void WhereRelatedTo(LCObject parent, string key) {
|
||||||
Add(new LCRelatedCondition(parent, key));
|
Add(new LCRelatedCondition(parent, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereStartsWith(string key, string prefix) {
|
public void WhereStartsWith(string key, string prefix) {
|
||||||
AddOperation(key, "$regex", $"^{prefix}.*");
|
AddOperation(key, "$regex", $"^{prefix}.*");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereEndsWith(string key, string suffix) {
|
public void WhereEndsWith(string key, string suffix) {
|
||||||
AddOperation(key, "$regex", $".*{suffix}$");
|
AddOperation(key, "$regex", $".*{suffix}$");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void WhereContains(string key, string subString) {
|
public void WhereContains(string key, string subString) {
|
||||||
AddOperation(key, "$regex", $".*{subString}.*");
|
AddOperation(key, "$regex", $".*{subString}.*");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ namespace LeanCloud.Storage.Internal.Query {
|
||||||
Add(cond);
|
Add(cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Add(ILCQueryCondition cond) {
|
public void Add(ILCQueryCondition cond) {
|
||||||
if (cond == null) {
|
if (cond == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -123,25 +123,25 @@ namespace LeanCloud.Storage.Internal.Query {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 筛选条件
|
// 筛选条件
|
||||||
internal void OrderBy(string key) {
|
public void OrderBy(string key) {
|
||||||
if (orderByList == null) {
|
if (orderByList == null) {
|
||||||
orderByList = new List<string>();
|
orderByList = new List<string>();
|
||||||
}
|
}
|
||||||
orderByList.Add(key);
|
orderByList.Add(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OrderByDescending(string key) {
|
public void OrderByDescending(string key) {
|
||||||
OrderBy($"-{key}");
|
OrderBy($"-{key}");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Include(string key) {
|
public void Include(string key) {
|
||||||
if (includes == null) {
|
if (includes == null) {
|
||||||
includes = new HashSet<string>();
|
includes = new HashSet<string>();
|
||||||
}
|
}
|
||||||
includes.Add(key);
|
includes.Add(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Select(string key) {
|
public void Select(string key) {
|
||||||
if (selectedKeys == null) {
|
if (selectedKeys == null) {
|
||||||
selectedKeys = new HashSet<string>();
|
selectedKeys = new HashSet<string>();
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ namespace LeanCloud.Storage.Internal.Query {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Dictionary<string, object> BuildParams() {
|
public Dictionary<string, object> BuildParams() {
|
||||||
Dictionary<string, object> dict = new Dictionary<string, object> {
|
Dictionary<string, object> dict = new Dictionary<string, object> {
|
||||||
{ "skip", Skip },
|
{ "skip", Skip },
|
||||||
{ "limit", Limit }
|
{ "limit", Limit }
|
||||||
|
@ -185,7 +185,7 @@ namespace LeanCloud.Storage.Internal.Query {
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal string BuildWhere() {
|
public string BuildWhere() {
|
||||||
if (conditionList == null || conditionList.Count == 0) {
|
if (conditionList == null || conditionList.Count == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
using LeanCloud.Storage.Internal.Codec;
|
using LeanCloud.Storage.Internal.Codec;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal.Query {
|
namespace LeanCloud.Storage.Internal.Query {
|
||||||
internal class LCEqualCondition : ILCQueryCondition {
|
public class LCEqualCondition : ILCQueryCondition {
|
||||||
readonly string key;
|
readonly string key;
|
||||||
readonly object value;
|
readonly object value;
|
||||||
|
|
||||||
internal LCEqualCondition(string key, object value) {
|
public LCEqualCondition(string key, object value) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
using LeanCloud.Storage.Internal.Codec;
|
using LeanCloud.Storage.Internal.Codec;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal.Query {
|
namespace LeanCloud.Storage.Internal.Query {
|
||||||
internal class LCOperationCondition : ILCQueryCondition {
|
public class LCOperationCondition : ILCQueryCondition {
|
||||||
readonly string key;
|
readonly string key;
|
||||||
readonly string op;
|
readonly string op;
|
||||||
readonly object value;
|
readonly object value;
|
||||||
|
|
||||||
internal LCOperationCondition(string key, string op, object value) {
|
public LCOperationCondition(string key, string op, object value) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.op = op;
|
this.op = op;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
using LeanCloud.Storage.Internal.Codec;
|
using LeanCloud.Storage.Internal.Codec;
|
||||||
|
|
||||||
namespace LeanCloud.Storage.Internal.Query {
|
namespace LeanCloud.Storage.Internal.Query {
|
||||||
internal class LCRelatedCondition : ILCQueryCondition {
|
public class LCRelatedCondition : ILCQueryCondition {
|
||||||
readonly LCObject parent;
|
readonly LCObject parent;
|
||||||
readonly string key;
|
readonly string key;
|
||||||
|
|
||||||
internal LCRelatedCondition(LCObject parent, string key) {
|
public LCRelatedCondition(LCObject parent, string key) {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.key = key;
|
this.key = key;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,5 +91,34 @@ namespace Realtime.Test {
|
||||||
|
|
||||||
await tcs.Task;
|
await tcs.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Query() {
|
||||||
|
LCIMClient client = new LCIMClient("hello123");
|
||||||
|
await client.Open();
|
||||||
|
|
||||||
|
LCIMConversationQuery query = new LCIMConversationQuery(client);
|
||||||
|
await query.Find();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Save() {
|
||||||
|
string clientId = Guid.NewGuid().ToString();
|
||||||
|
LCIMClient client = new LCIMClient(clientId);
|
||||||
|
|
||||||
|
await client.Open();
|
||||||
|
|
||||||
|
string otherId = Guid.NewGuid().ToString();
|
||||||
|
LCIMConversation conversation = await client.CreateConversation(new List<string> { otherId });
|
||||||
|
|
||||||
|
conversation.Name = "leancloud";
|
||||||
|
conversation["k1"] = "v1";
|
||||||
|
conversation["k2"] = "v2";
|
||||||
|
await conversation.Save();
|
||||||
|
|
||||||
|
Assert.AreEqual(conversation.Name, "leancloud");
|
||||||
|
Assert.AreEqual(conversation["k1"], "v1");
|
||||||
|
Assert.AreEqual(conversation["k2"], "v2");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue