csharp-sdk-upm/Realtime/Internal/Controller/LCIMConversationController.cs

403 lines
18 KiB
C#

using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
using Newtonsoft.Json;
using LeanCloud.Realtime.Protocol;
using LeanCloud.Storage.Internal;
using LeanCloud.Storage.Internal.Codec;
using Google.Protobuf;
namespace LeanCloud.Realtime.Internal.Controller {
internal class LCIMConversationController : LCIMController {
internal LCIMConversationController(LCIMClient client) : base(client) {
}
/// <summary>
/// 创建对话
/// </summary>
/// <param name="members"></param>
/// <param name="name"></param>
/// <param name="transient"></param>
/// <param name="unique"></param>
/// <param name="temporary"></param>
/// <param name="temporaryTtl"></param>
/// <param name="properties"></param>
/// <returns></returns>
internal async Task<LCIMConversation> CreateConv(
IEnumerable<string> members = null,
string name = null,
bool transient = false,
bool unique = true,
bool temporary = false,
int temporaryTtl = 86400,
Dictionary<string, object> properties = null) {
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Start);
ConvCommand conv = new ConvCommand {
Transient = transient,
Unique = unique,
};
if (members != null) {
conv.M.AddRange(members);
}
if (!string.IsNullOrEmpty(name)) {
conv.N = name;
}
if (temporary) {
conv.TempConv = temporary;
conv.TempConvTTL = temporaryTtl;
}
if (properties != null) {
conv.Attr = new JsonObjectMessage {
Data = JsonConvert.SerializeObject(LCEncoder.Encode(properties))
};
}
if (Client.SignatureFactory != null) {
LCIMSignature signature = Client.SignatureFactory.CreateStartConversationSignature(Client.Id, members);
conv.S = signature.Signature;
conv.T = signature.Timestamp;
conv.N = signature.Nonce;
}
request.ConvMessage = conv;
GenericCommand response = await Connection.SendRequest(request);
string convId = response.ConvMessage.Cid;
if (!Client.ConversationDict.TryGetValue(convId, out LCIMConversation conversation)) {
if (transient) {
conversation = new LCIMChatRoom(Client);
} else if (temporary) {
conversation = new LCIMTemporaryConversation(Client);
} else if (properties != null && properties.ContainsKey("system")) {
conversation = new LCIMServiceConversation(Client);
} else {
conversation = new LCIMConversation(Client);
}
Client.ConversationDict[convId] = conversation;
}
// 合并请求数据
conversation.Name = name;
conversation.MemberIdList = members?.ToList();
// 合并服务端推送的数据
conversation.MergeFrom(response.ConvMessage);
return conversation;
}
internal async Task<int> GetMembersCount(string convId) {
ConvCommand conv = new ConvCommand {
Cid = convId,
};
GenericCommand command = Client.NewCommand(CommandType.Conv, OpType.Count);
command.ConvMessage = conv;
GenericCommand response = await Connection.SendRequest(command);
return response.ConvMessage.Count;
}
internal async Task Read(string convId, LCIMMessage message) {
ReadCommand read = new ReadCommand();
ReadTuple tuple = new ReadTuple {
Cid = convId,
Mid = message.Id,
Timestamp = message.SentTimestamp
};
read.Convs.Add(tuple);
GenericCommand request = Client.NewCommand(CommandType.Read, OpType.Open);
request.ReadMessage = read;
await Client.Connection.SendRequest(request);
}
internal async Task<Dictionary<string, object>> UpdateInfo(string convId, Dictionary<string, object> attributes) {
ConvCommand conv = new ConvCommand {
Cid = convId,
};
conv.Attr = new JsonObjectMessage {
Data = JsonConvert.SerializeObject(attributes)
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Update);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
JsonObjectMessage attr = response.ConvMessage.AttrModified;
// 更新自定义属性
if (attr != null) {
Dictionary<string, object> updatedAttr = JsonConvert.DeserializeObject<Dictionary<string, object>>(attr.Data);
return updatedAttr;
}
return null;
}
internal async Task<LCIMPartiallySuccessResult> AddMembers(string convId, IEnumerable<string> clientIds) {
ConvCommand conv = new ConvCommand {
Cid = convId,
};
conv.M.AddRange(clientIds);
// 签名参数
if (Client.SignatureFactory != null) {
LCIMSignature signature = Client.SignatureFactory.CreateConversationSignature(convId,
Client.Id,
clientIds,
LCIMSignatureAction.Invite);
conv.S = signature.Signature;
conv.T = signature.Timestamp;
conv.N = signature.Nonce;
}
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Add);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
List<string> allowedIds = response.ConvMessage.AllowedPids.ToList();
List<ErrorCommand> errors = response.ConvMessage.FailedPids.ToList();
return NewPartiallySuccessResult(allowedIds, errors);
}
internal async Task<LCIMPartiallySuccessResult> RemoveMembers(string convId, IEnumerable<string> removeIds) {
ConvCommand conv = new ConvCommand {
Cid = convId,
};
conv.M.AddRange(removeIds);
// 签名参数
if (Client.SignatureFactory != null) {
LCIMSignature signature = Client.SignatureFactory.CreateConversationSignature(convId,
Client.Id,
removeIds,
LCIMSignatureAction.Kick);
conv.S = signature.Signature;
conv.T = signature.Timestamp;
conv.N = signature.Nonce;
}
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Remove);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
List<string> allowedIds = response.ConvMessage.AllowedPids.ToList();
List<ErrorCommand> errors = response.ConvMessage.FailedPids.ToList();
return NewPartiallySuccessResult(allowedIds, errors);
}
internal async Task Mute(string convId) {
ConvCommand conv = new ConvCommand {
Cid = convId
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Mute);
request.ConvMessage = conv;
await Client.Connection.SendRequest(request);
}
internal async Task Unmute(string convId) {
ConvCommand conv = new ConvCommand {
Cid = convId
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Unmute);
request.ConvMessage = conv;
await Client.Connection.SendRequest(request);
}
internal async Task<LCIMPartiallySuccessResult> MuteMembers(string convId, IEnumerable<string> clientIds) {
if (clientIds == null || clientIds.Count() == 0) {
throw new ArgumentNullException(nameof(clientIds));
}
ConvCommand conv = new ConvCommand {
Cid = convId
};
conv.M.AddRange(clientIds);
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.AddShutup);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids);
}
internal async Task<LCIMPartiallySuccessResult> UnmuteMembers(string convId, IEnumerable<string> clientIds) {
ConvCommand conv = new ConvCommand {
Cid = convId
};
conv.M.AddRange(clientIds);
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.Remove);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
return NewPartiallySuccessResult(response.ConvMessage.AllowedPids, response.ConvMessage.FailedPids);
}
internal async Task<LCIMPartiallySuccessResult> BlockMembers(string convId, IEnumerable<string> clientIds) {
BlacklistCommand blacklist = new BlacklistCommand {
SrcCid = convId,
};
blacklist.ToPids.AddRange(clientIds);
if (Client.SignatureFactory != null) {
LCIMSignature signature = Client.SignatureFactory.CreateBlacklistSignature(convId,
Client.Id,
clientIds,
LCIMSignatureAction.ConversationBlockClients);
blacklist.S = signature.Signature;
blacklist.T = signature.Timestamp;
blacklist.N = signature.Nonce;
}
GenericCommand request = Client.NewCommand(CommandType.Blacklist, OpType.Block);
request.BlacklistMessage = blacklist;
GenericCommand response = await Client.Connection.SendRequest(request);
return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids);
}
internal async Task<LCIMPartiallySuccessResult> UnblockMembers(string convId, IEnumerable<string> clientIds) {
BlacklistCommand blacklist = new BlacklistCommand {
SrcCid = convId,
};
blacklist.ToPids.AddRange(clientIds);
if (Client.SignatureFactory != null) {
LCIMSignature signature = Client.SignatureFactory.CreateBlacklistSignature(convId,
Client.Id,
clientIds,
LCIMSignatureAction.ConversationUnblockClients);
blacklist.S = signature.Signature;
blacklist.T = signature.Timestamp;
blacklist.N = signature.Nonce;
}
GenericCommand request = Client.NewCommand(CommandType.Blacklist, OpType.Unblock);
request.BlacklistMessage = blacklist;
GenericCommand response = await Client.Connection.SendRequest(request);
return NewPartiallySuccessResult(response.BlacklistMessage.AllowedPids, response.BlacklistMessage.FailedPids);
}
internal async Task UpdateMemberRole(string convId, string memberId, string role) {
ConvCommand conv = new ConvCommand {
Cid = convId,
TargetClientId = memberId,
Info = new ConvMemberInfo {
Pid = memberId,
Role = role
}
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.MemberInfoUpdate);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
}
internal async Task<List<LCIMConversationMemberInfo>> GetAllMemberInfo(string convId) {
string path = "classes/_ConversationMemberInfo";
string token = await Client.SessionController.GetToken();
Dictionary<string, object> headers = new Dictionary<string, object> {
{ "X-LC-IM-Session-Token", token }
};
Dictionary<string, object> queryParams = new Dictionary<string, object> {
{ "client_id", Client.Id },
{ "cid", convId }
};
Dictionary<string, object> response = await LCApplication.HttpClient.Get<Dictionary<string, object>>(path,
headers: headers, queryParams: queryParams);
List<object> results = response["results"] as List<object>;
List<LCIMConversationMemberInfo> memberList = new List<LCIMConversationMemberInfo>();
foreach (Dictionary<string, object> item in results) {
LCIMConversationMemberInfo member = new LCIMConversationMemberInfo {
ConversationId = item["cid"] as string,
MemberId = item["clientId"] as string,
Role = item["role"] as string
};
memberList.Add(member);
}
return memberList;
}
internal async Task<LCIMPageResult> QueryMutedMembers(string convId, int limit = 10, string next = null) {
ConvCommand conv = new ConvCommand {
Cid = convId,
Limit = limit,
Next = next
};
GenericCommand request = Client.NewCommand(CommandType.Conv, OpType.QueryShutup);
request.ConvMessage = conv;
GenericCommand response = await Client.Connection.SendRequest(request);
return new LCIMPageResult {
Results = response.ConvMessage.M.ToList(),
Next = response.ConvMessage.Next
};
}
internal async Task<LCIMPageResult> QueryBlockedMembers(string convId, int limit = 10, string next = null) {
BlacklistCommand black = new BlacklistCommand {
SrcCid = convId,
Limit = limit,
Next = next
};
GenericCommand request = Client.NewCommand(CommandType.Blacklist, OpType.Query);
request.BlacklistMessage = black;
GenericCommand response = await Client.Connection.SendRequest(request);
return new LCIMPageResult {
Results = response.BlacklistMessage.BlockedPids.ToList(),
Next = response.BlacklistMessage.Next
};
}
private LCIMPartiallySuccessResult NewPartiallySuccessResult(IEnumerable<string> succesfulIds, IEnumerable<ErrorCommand> errors) {
LCIMPartiallySuccessResult result = new LCIMPartiallySuccessResult {
SuccessfulClientIdList = succesfulIds.ToList()
};
if (errors != null) {
result.FailureList = new List<LCIMOperationFailure>();
foreach (ErrorCommand error in errors) {
result.FailureList.Add(new LCIMOperationFailure(error));
}
}
return result;
}
internal override async Task OnNotification(GenericCommand notification) {
ConvCommand conv = notification.ConvMessage;
switch (notification.Op) {
case OpType.Joined:
await OnConversationJoined(conv);
break;
case OpType.MembersJoined:
await OnConversationMembersJoined(conv);
break;
case OpType.Left:
await OnConversationLeft(conv);
break;
case OpType.MembersLeft:
await OnConversationMemberLeft(conv);
break;
case OpType.Updated:
await OnConversationPropertiesUpdated(conv);
break;
case OpType.MemberInfoChanged:
await OnConversationMemberInfoChanged(conv);
break;
default:
break;
}
}
private async Task OnConversationJoined(ConvCommand conv) {
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid);
conversation.MergeFrom(conv);
Client.OnInvited?.Invoke(conversation, conv.InitBy);
}
private async Task OnConversationMembersJoined(ConvCommand conv) {
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid);
conversation.MergeFrom(conv);
Client.OnMembersJoined?.Invoke(conversation, conv.M.ToList(), conv.InitBy);
}
private async Task OnConversationLeft(ConvCommand conv) {
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid);
Client.OnKicked?.Invoke(conversation, conv.InitBy);
}
private async Task OnConversationMemberLeft(ConvCommand conv) {
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid);
List<string> leftIdList = conv.M.ToList();
Client.OnMembersLeft?.Invoke(conversation, leftIdList, conv.InitBy);
}
private async Task OnConversationPropertiesUpdated(ConvCommand conv) {
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid);
Dictionary<string, object> updatedAttr = JsonConvert.DeserializeObject<Dictionary<string, object>>(conv.AttrModified.Data,
new LCJsonConverter());
// 更新内存数据
conversation.MergeInfo(updatedAttr);
Client.OnConversationInfoUpdated?.Invoke(conversation, updatedAttr, conv.InitBy);
}
private async Task OnConversationMemberInfoChanged(ConvCommand conv) {
LCIMConversation conversation = await Client.GetOrQueryConversation(conv.Cid);
ConvMemberInfo memberInfo = conv.Info;
Client.OnMemberInfoUpdated?.Invoke(conversation, memberInfo.Pid, memberInfo.Role, conv.InitBy);
}
}
}