* 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.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using LeanCloud.Realtime.Protocol;
|
||||
using LeanCloud.Storage.Internal.Codec;
|
||||
|
||||
namespace LeanCloud.Realtime {
|
||||
public class LCIMConversation {
|
||||
|
@ -11,7 +13,11 @@ namespace LeanCloud.Realtime {
|
|||
}
|
||||
|
||||
public string Name {
|
||||
get; set;
|
||||
get {
|
||||
return this["name"] as string;
|
||||
} set {
|
||||
this["name"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public string CreatorId {
|
||||
|
@ -30,7 +36,22 @@ namespace LeanCloud.Realtime {
|
|||
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;
|
||||
|
||||
|
@ -38,39 +59,122 @@ namespace LeanCloud.Realtime {
|
|||
|
||||
private readonly LCIMClient client;
|
||||
|
||||
private Dictionary<string, object> customProperties;
|
||||
|
||||
internal LCIMConversation(LCIMClient 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() {
|
||||
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() {
|
||||
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;
|
||||
}
|
||||
|
||||
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() {
|
||||
return this;
|
||||
return await Add(new string[] { client.ClientId });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 离开对话
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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) {
|
||||
DirectCommand direct = new DirectCommand {
|
||||
FromPeerId = client.ClientId,
|
||||
|
@ -88,30 +192,108 @@ namespace LeanCloud.Realtime {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 静音
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消静音
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (string.IsNullOrEmpty(memberId)) {
|
||||
throw new ArgumentNullException(nameof(memberId));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,256 @@
|
|||
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 {
|
||||
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 {
|
||||
public class LCIMTemporaryConversation : LCIMConversation {
|
||||
public DateTime ExpiredAt {
|
||||
get;
|
||||
}
|
||||
|
||||
public bool IsExpired {
|
||||
get {
|
||||
return DateTime.Now > ExpiredAt;
|
||||
}
|
||||
}
|
||||
|
||||
public LCIMTemporaryConversation(LCIMClient client) : base(client) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,24 +24,24 @@ namespace LeanCloud.Realtime {
|
|||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前客户端被服务端强行下线
|
||||
/// </summary>
|
||||
public Action OnClosed {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户端连接断开
|
||||
/// </summary>
|
||||
public Action OnDisconnected {
|
||||
public Action OnPaused {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户端连接恢复正常
|
||||
/// </summary>
|
||||
public Action OnReconnect {
|
||||
public Action OnResume {
|
||||
get; set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前客户端被服务端强行下线
|
||||
/// </summary>
|
||||
public Action OnOffline {
|
||||
get; set;
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,10 @@ namespace LeanCloud.Realtime {
|
|||
conversationDict = new Dictionary<string, LCIMConversation>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task Open() {
|
||||
client = new LCWebSocketClient {
|
||||
OnNotification = OnNotification
|
||||
|
@ -86,6 +90,14 @@ namespace LeanCloud.Realtime {
|
|||
await client.SendRequest(command);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 关闭
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task Close() {
|
||||
await client.Close();
|
||||
}
|
||||
|
||||
public async Task<LCIMChatRoom> CreateChatRoom(
|
||||
string name,
|
||||
Dictionary<string, object> properties = null) {
|
||||
|
@ -143,16 +155,48 @@ namespace LeanCloud.Realtime {
|
|||
return conversation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取某个特定的对话
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
public async Task<List<LCIMConversation>> GetConversationList(List<string> idList) {
|
||||
return null;
|
||||
return results[0];
|
||||
}
|
||||
|
||||
public async Task<LCIMConversationQuery> GetConversationQuery() {
|
||||
return null;
|
||||
/// <summary>
|
||||
/// 获取某些特定的对话
|
||||
/// </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) {
|
||||
|
@ -166,12 +210,22 @@ namespace LeanCloud.Realtime {
|
|||
}
|
||||
|
||||
private void OnConversationNotification(GenericCommand notification) {
|
||||
ConvCommand conv = notification.ConvMessage;
|
||||
switch (notification.Op) {
|
||||
case OpType.Joined:
|
||||
OnConversationJoined(notification.ConvMessage);
|
||||
OnConversationJoined(conv);
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
|
@ -190,6 +244,26 @@ namespace LeanCloud.Realtime {
|
|||
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) {
|
||||
if (!conversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
|
||||
conversation = new LCIMConversation(this);
|
||||
|
|
|
@ -4,8 +4,8 @@ using System.Collections.Generic;
|
|||
using LeanCloud.Storage.Internal.Object;
|
||||
|
||||
namespace LeanCloud.Storage.Internal.Codec {
|
||||
internal static class LCDecoder {
|
||||
internal static object Decode(object obj) {
|
||||
public static class LCDecoder {
|
||||
public static object Decode(object obj) {
|
||||
if (obj is IDictionary dict) {
|
||||
if (dict.Contains("__type")) {
|
||||
string type = dict["__type"].ToString();
|
||||
|
|
|
@ -5,8 +5,8 @@ using LeanCloud.Storage.Internal.Operation;
|
|||
using LeanCloud.Storage.Internal.Query;
|
||||
|
||||
namespace LeanCloud.Storage.Internal.Codec {
|
||||
internal static class LCEncoder {
|
||||
internal static object Encode(object obj) {
|
||||
public static class LCEncoder {
|
||||
public static object Encode(object obj) {
|
||||
if (obj is DateTime dateTime) {
|
||||
return EncodeDateTime(dateTime);
|
||||
} else if (obj is byte[] bytes) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace LeanCloud.Storage.Internal.Query {
|
||||
internal interface ILCQueryCondition {
|
||||
public interface ILCQueryCondition {
|
||||
bool Equals(ILCQueryCondition other);
|
||||
Dictionary<string, object> Encode();
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@ using Newtonsoft.Json;
|
|||
using LeanCloud.Storage.Internal.Codec;
|
||||
|
||||
namespace LeanCloud.Storage.Internal.Query {
|
||||
internal class LCCompositionalCondition : ILCQueryCondition {
|
||||
internal const string And = "$and";
|
||||
internal const string Or = "$or";
|
||||
public class LCCompositionalCondition : ILCQueryCondition {
|
||||
public const string And = "$and";
|
||||
public const string Or = "$or";
|
||||
|
||||
readonly string composition;
|
||||
|
||||
|
@ -16,93 +16,93 @@ namespace LeanCloud.Storage.Internal.Query {
|
|||
HashSet<string> includes;
|
||||
HashSet<string> selectedKeys;
|
||||
|
||||
internal int Skip {
|
||||
public int Skip {
|
||||
get; set;
|
||||
}
|
||||
|
||||
internal int Limit {
|
||||
public int Limit {
|
||||
get; set;
|
||||
}
|
||||
|
||||
internal LCCompositionalCondition(string composition = And) {
|
||||
public LCCompositionalCondition(string composition = And) {
|
||||
this.composition = composition;
|
||||
Skip = 0;
|
||||
Limit = 30;
|
||||
}
|
||||
|
||||
// 查询条件
|
||||
internal void WhereEqualTo(string key, object value) {
|
||||
public void WhereEqualTo(string key, object value) {
|
||||
Add(new LCEqualCondition(key, value));
|
||||
}
|
||||
|
||||
internal void WhereNotEqualTo(string key, object value) {
|
||||
public void WhereNotEqualTo(string key, object value) {
|
||||
AddOperation(key, "$ne", value);
|
||||
}
|
||||
|
||||
internal void WhereContainedIn(string key, IEnumerable values) {
|
||||
public void WhereContainedIn(string key, IEnumerable values) {
|
||||
AddOperation(key, "$in", values);
|
||||
}
|
||||
|
||||
internal void WhereNotContainedIn(string key, IEnumerable values) {
|
||||
public void WhereNotContainedIn(string key, IEnumerable values) {
|
||||
AddOperation(key, "nin", values);
|
||||
}
|
||||
|
||||
internal void WhereContainsAll(string key, IEnumerable values) {
|
||||
public void WhereContainsAll(string key, IEnumerable values) {
|
||||
AddOperation(key, "$all", values);
|
||||
}
|
||||
|
||||
internal void WhereExists(string key) {
|
||||
public void WhereExists(string key) {
|
||||
AddOperation(key, "$exists", true);
|
||||
}
|
||||
|
||||
internal void WhereDoesNotExist(string key) {
|
||||
public void WhereDoesNotExist(string key) {
|
||||
AddOperation(key, "$exists", false);
|
||||
}
|
||||
|
||||
internal void WhereSizeEqualTo(string key, int size) {
|
||||
public void WhereSizeEqualTo(string key, int size) {
|
||||
AddOperation(key, "$size", size);
|
||||
}
|
||||
|
||||
internal void WhereGreaterThan(string key, object value) {
|
||||
public void WhereGreaterThan(string key, object value) {
|
||||
AddOperation(key, "$gt", value);
|
||||
}
|
||||
|
||||
internal void WhereGreaterThanOrEqualTo(string key, object value) {
|
||||
public void WhereGreaterThanOrEqualTo(string key, object value) {
|
||||
AddOperation(key, "$gte", value);
|
||||
}
|
||||
|
||||
internal void WhereLessThan(string key, object value) {
|
||||
public void WhereLessThan(string key, object value) {
|
||||
AddOperation(key, "$lt", value);
|
||||
}
|
||||
|
||||
internal void WhereLessThanOrEqualTo(string key, object value) {
|
||||
public void WhereLessThanOrEqualTo(string key, object value) {
|
||||
AddOperation(key, "$lte", value);
|
||||
}
|
||||
|
||||
internal void WhereNear(string key, LCGeoPoint point) {
|
||||
public void WhereNear(string key, LCGeoPoint 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> {
|
||||
{ "$box", new List<object> { southwest, northeast } }
|
||||
};
|
||||
AddOperation(key, "$within", value);
|
||||
}
|
||||
|
||||
internal void WhereRelatedTo(LCObject parent, string key) {
|
||||
public void WhereRelatedTo(LCObject parent, string key) {
|
||||
Add(new LCRelatedCondition(parent, key));
|
||||
}
|
||||
|
||||
internal void WhereStartsWith(string key, string prefix) {
|
||||
public void WhereStartsWith(string key, string prefix) {
|
||||
AddOperation(key, "$regex", $"^{prefix}.*");
|
||||
}
|
||||
|
||||
internal void WhereEndsWith(string key, string suffix) {
|
||||
public void WhereEndsWith(string key, string suffix) {
|
||||
AddOperation(key, "$regex", $".*{suffix}$");
|
||||
}
|
||||
|
||||
internal void WhereContains(string key, string subString) {
|
||||
public void WhereContains(string key, string subString) {
|
||||
AddOperation(key, "$regex", $".*{subString}.*");
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ namespace LeanCloud.Storage.Internal.Query {
|
|||
Add(cond);
|
||||
}
|
||||
|
||||
internal void Add(ILCQueryCondition cond) {
|
||||
public void Add(ILCQueryCondition cond) {
|
||||
if (cond == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -123,25 +123,25 @@ namespace LeanCloud.Storage.Internal.Query {
|
|||
}
|
||||
|
||||
// 筛选条件
|
||||
internal void OrderBy(string key) {
|
||||
public void OrderBy(string key) {
|
||||
if (orderByList == null) {
|
||||
orderByList = new List<string>();
|
||||
}
|
||||
orderByList.Add(key);
|
||||
}
|
||||
|
||||
internal void OrderByDescending(string key) {
|
||||
public void OrderByDescending(string key) {
|
||||
OrderBy($"-{key}");
|
||||
}
|
||||
|
||||
internal void Include(string key) {
|
||||
public void Include(string key) {
|
||||
if (includes == null) {
|
||||
includes = new HashSet<string>();
|
||||
}
|
||||
includes.Add(key);
|
||||
}
|
||||
|
||||
internal void Select(string key) {
|
||||
public void Select(string key) {
|
||||
if (selectedKeys == null) {
|
||||
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> {
|
||||
{ "skip", Skip },
|
||||
{ "limit", Limit }
|
||||
|
@ -185,7 +185,7 @@ namespace LeanCloud.Storage.Internal.Query {
|
|||
return dict;
|
||||
}
|
||||
|
||||
internal string BuildWhere() {
|
||||
public string BuildWhere() {
|
||||
if (conditionList == null || conditionList.Count == 0) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
using LeanCloud.Storage.Internal.Codec;
|
||||
|
||||
namespace LeanCloud.Storage.Internal.Query {
|
||||
internal class LCEqualCondition : ILCQueryCondition {
|
||||
public class LCEqualCondition : ILCQueryCondition {
|
||||
readonly string key;
|
||||
readonly object value;
|
||||
|
||||
internal LCEqualCondition(string key, object value) {
|
||||
public LCEqualCondition(string key, object value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
using LeanCloud.Storage.Internal.Codec;
|
||||
|
||||
namespace LeanCloud.Storage.Internal.Query {
|
||||
internal class LCOperationCondition : ILCQueryCondition {
|
||||
public class LCOperationCondition : ILCQueryCondition {
|
||||
readonly string key;
|
||||
readonly string op;
|
||||
readonly object value;
|
||||
|
||||
internal LCOperationCondition(string key, string op, object value) {
|
||||
public LCOperationCondition(string key, string op, object value) {
|
||||
this.key = key;
|
||||
this.op = op;
|
||||
this.value = value;
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
using LeanCloud.Storage.Internal.Codec;
|
||||
|
||||
namespace LeanCloud.Storage.Internal.Query {
|
||||
internal class LCRelatedCondition : ILCQueryCondition {
|
||||
public class LCRelatedCondition : ILCQueryCondition {
|
||||
readonly LCObject parent;
|
||||
readonly string key;
|
||||
|
||||
internal LCRelatedCondition(LCObject parent, string key) {
|
||||
public LCRelatedCondition(LCObject parent, string key) {
|
||||
this.parent = parent;
|
||||
this.key = key;
|
||||
}
|
||||
|
|
|
@ -91,5 +91,34 @@ namespace Realtime.Test {
|
|||
|
||||
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