添加项目文件。

This commit is contained in:
2026-05-09 17:06:30 +08:00
parent c60f5fe117
commit 720ef957d4
378 changed files with 14843 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
namespace IM.Commons
{
public class BaseEvent
{
// --- 标准元数据 ---
public Guid EventId { get; init; } = Guid.NewGuid();
public DateTime OccurredOn { get; init; } = DateTime.Now;
public Guid CorrelationId { get; init; }
}
}
+14
View File
@@ -0,0 +1,14 @@
using System.Linq.Expressions;
namespace IM.Commons
{
public abstract class BaseSpecification<T, TResult> : ISpecification<T, TResult>
{
public Expression<Func<T, bool>> Criteria { get; private set; }
public List<Expression<Func<T, object>>> Includes { get; private set; }
public Expression<Func<T, TResult>> Select { get; private set; }
}
}
+21
View File
@@ -0,0 +1,21 @@
using System.ComponentModel;
using System.Reflection;
namespace IM.Commons
{
public static class EnumHelper
{
/// <summary>
/// 获取枚举的 Description 描述信息
/// </summary>
public static string GetDescription(this Enum value)
{
FieldInfo? field = value.GetType().GetField(value.ToString());
if (field == null) return value.ToString();
DescriptionAttribute? attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
return attribute == null ? value.ToString() : attribute.Description;
}
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace IM.Commons
{
public class EventHandlerException : Exception
{
public EventHandlerException()
{
}
public EventHandlerException(string? message) : base(message)
{
}
}
}
+15
View File
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IM.Commons
{
public class GrpcOptions
{
public string MessageServiceUrl { get; set; }
public string IdentityServiceUrl { get; set; }
public string ContactServiceUrl { get; set; }
}
}
+16
View File
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AsmResolver.DotNet" Version="5.5.1" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="StackExchange.Redis" Version="2.12.14" />
</ItemGroup>
</Project>
+13
View File
@@ -0,0 +1,13 @@
using Microsoft.Extensions.DependencyInjection;
namespace IM.Commons
{
/// <summary>
/// 所有项目中的实现了IModuleInitializer接口都会被调用,请在Initialize中编写注册本模块需要的服务。
/// 一个项目中可以放多个实现了IModuleInitializer的类。不过为了集中管理,还是建议一个项目中只放一个实现了IModuleInitializer的类
/// </summary>
public interface IModuleInitializer
{
public void Initialize(IServiceCollection services);
}
}
+38
View File
@@ -0,0 +1,38 @@
using Microsoft.Extensions.DependencyInjection;
namespace IM.Commons
{
public interface IRedisService
{
/// <summary>
/// 设置缓存
/// </summary>
/// <typeparam name="T">缓存对象类型</typeparam>
/// <param name="key">缓存索引值</param>
/// <param name="value">要缓存的对象</param>
/// <param name="expiration">过期时间</param>
/// <returns></returns>
Task SetAsync<T>(string key, T value, TimeSpan? expiration = null);
/// <summary>
/// 获取缓存
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">缓存索引</param>
/// <returns></returns>
Task<T?> GetAsync<T>(string key);
/// <summary>
/// 删除缓存
/// </summary>
/// <param name="key">缓存索引</param>
/// <returns></returns>
Task RemoveAsync(string key);
}
public static class RedisServiceExtension
{
public static IServiceCollection AddRedisCache(this IServiceCollection services)
{
return services.AddScoped<IRedisService, RedisCacheService>();
}
}
}
+14
View File
@@ -0,0 +1,14 @@
using System.Linq.Expressions;
namespace IM.Commons
{
public interface ISpecification<T, TResut> : ISpecification<T>
{
public Expression<Func<T, TResut>> Select { get; }
}
public interface ISpecification<T>
{
Expression<Func<T, bool>> Criteria { get; }
List<Expression<Func<T, object>>> Includes { get; }
}
}
@@ -0,0 +1,14 @@
namespace IM.Commons.IntegrationEvents
{
public class FriendAddedEvent : BaseEvent
{
public Guid OwnerId { get; set; }
public string OwnerNickName { get; set; }
public string? OwnerAvatar { get; set; }
public Guid TargetId { get; set; }
public string TargetNickName { get; set; }
public string? TargetAvatar { get; set; }
public string? RemarkName { get; set; }
public string Status { get; set; }
}
}
@@ -0,0 +1,31 @@
namespace IM.Commons.IntegrationEvents
{
public class FriendRequestStateUpdateEvent : BaseEvent
{
/// <summary>
/// 申请人
/// </summary>
public Guid OwnerId { get; set; }
/// <summary>
/// 被申请人
/// </summary>
public Guid TargetId { get; set; }
/// <summary>
/// 申请附言
/// </summary>
public string Description { get; set; }
/// <summary>
/// 申请状态(0:待通过,1:拒绝,2:同意,3:拉黑)
/// </summary>
public string State { get; set; }
/// <summary>
/// 备注
/// </summary>
public string? RemarkName { get; set; }
}
}
@@ -0,0 +1,20 @@
namespace IM.Commons.IntegrationEvents
{
public class GroupBlockEvent : BaseEvent
{
public Guid GroupId { get; private set; }
public string GroupName { get; private set; }
public Guid GroupMaster { get; private set; }
public string Status { get; private set; }
public string? Avatar { get; private set; }
public GroupBlockEvent(Guid groupId, string groupName, Guid groupMaster, string status, string? avatar)
{
GroupId = groupId;
GroupName = groupName;
GroupMaster = groupMaster;
Status = status;
Avatar = avatar;
}
}
}
@@ -0,0 +1,18 @@
namespace IM.Commons.IntegrationEvents
{
public class GroupCreateEvent
{
public Guid GroupId { get; private set; }
public string GroupName { get; private set; }
public Guid GroupMaster { get; private set; }
public string? Avatar { get; private set; }
public GroupCreateEvent(Guid groupId, string groupName, Guid groupMaster, string? avatar)
{
GroupId = groupId;
GroupName = groupName;
GroupMaster = groupMaster;
Avatar = avatar;
}
}
}
@@ -0,0 +1,9 @@
namespace IM.Commons.IntegrationEvents
{
public class GroupInvitationAcceptEvent : GroupInvitationCreateEvent
{
public GroupInvitationAcceptEvent(Guid invitationId, Guid userId, string userNickName, string? userAvatar, Guid groupId, string groupName, string groupAvatar, Guid operatorId, string operatorName, string operatorAvatar) : base(invitationId, userId, userNickName, userAvatar, groupId, groupName, groupAvatar, operatorId, operatorName, operatorAvatar)
{
}
}
}
@@ -0,0 +1,30 @@
namespace IM.Commons.IntegrationEvents
{
public class GroupInvitationCreateEvent : BaseEvent
{
public Guid InvitationId { get; private set; }
public Guid UserId { get; private set; }
public string UserNickName { get; private set; }
public string? UserAvatar { get; private set; }
public Guid GroupId { get; private set; }
public string GroupName { get; private set; }
public string GroupAvatar { get; private set; }
public Guid OperatorId { get; private set; }
public string OperatorName { get; private set; }
public string OperatorAvatar { get; private set; }
public GroupInvitationCreateEvent(Guid invitationId, Guid userId, string userNickName, string? userAvatar, Guid groupId, string groupName, string groupAvatar, Guid operatorId, string operatorName, string operatorAvatar)
{
InvitationId = invitationId;
UserId = userId;
UserNickName = userNickName;
UserAvatar = userAvatar;
GroupId = groupId;
GroupName = groupName;
GroupAvatar = groupAvatar;
OperatorId = operatorId;
OperatorName = operatorName;
OperatorAvatar = operatorAvatar;
}
}
}
@@ -0,0 +1,22 @@
namespace IM.Commons.IntegrationEvents
{
public class GroupMemberJoinedEvent
{
public Guid Id { get; private set; }
public Guid UserId { get; private set; }
public Guid GroupId { get; private set; }
public string GroupNickName { get; private set; }
public string? Avatar { get; private set; }
public string Role { get; private set; }
public GroupMemberJoinedEvent(Guid id, Guid userId, Guid groupId, string groupNickName, string? avatar, string role)
{
Id = id;
UserId = userId;
GroupId = groupId;
GroupNickName = groupNickName;
Avatar = avatar;
Role = role;
}
}
}
@@ -0,0 +1,9 @@
namespace IM.Commons.IntegrationEvents
{
public class GroupRequestDeclinedEvent : GroupRequestPassedEvent
{
public GroupRequestDeclinedEvent(Guid requestId, Guid groupId, string groupName, string groupAvatar, Guid userId, string userNickName, string? userAvatar, Guid operatorId, string operatorName, string operatorAvatar, string description, DateTimeOffset created, DateTimeOffset updated) : base(requestId, groupId, groupName, groupAvatar, userId, userNickName, userAvatar, operatorId, operatorName, operatorAvatar, description, created, updated)
{
}
}
}
@@ -0,0 +1,36 @@
namespace IM.Commons.IntegrationEvents
{
public class GroupRequestPassedEvent
{
public Guid RequestId { get; private set; }
public Guid GroupId { get; private set; }
public string GroupName { get; private set; }
public string GroupAvatar { get; private set; }
public Guid UserId { get; private set; }
public string UserNickName { get; private set; }
public string? UserAvatar { get; private set; }
public Guid OperatorId { get; private set; }
public string OperatorName { get; private set; }
public string OperatorAvatar { get; private set; }
public string Description { get; private set; }
public DateTimeOffset Created { get; private set; }
public DateTimeOffset Updated { get; private set; }
public GroupRequestPassedEvent(Guid requestId, Guid groupId, string groupName, string groupAvatar, Guid userId, string userNickName, string? userAvatar, Guid operatorId, string operatorName, string operatorAvatar, string description, DateTimeOffset created, DateTimeOffset updated)
{
RequestId = requestId;
GroupId = groupId;
GroupName = groupName;
GroupAvatar = groupAvatar;
UserId = userId;
UserNickName = userNickName;
UserAvatar = userAvatar;
OperatorId = operatorId;
OperatorName = operatorName;
OperatorAvatar = operatorAvatar;
Description = description;
Created = created;
Updated = updated;
}
}
}
@@ -0,0 +1,45 @@
namespace IM.Commons.IntegrationEvents
{
public class MsgCreatedEvent
{
public Guid Id { get; set; }
public Guid ClientId { get; set; }
public string ChatType { get; set; }
/// <summary>
/// 消息类型
/// (0:文本,1:图片,2:语音,3:视频,4:文件,5:语音聊天,6:视频聊天)
/// </summary>
public string MsgType { get; set; }
/// <summary>
/// 发送者
/// </summary>
public Guid SenderId { get; set; }
/// <summary>
/// 接收者(私聊为用户ID,群聊为群聊ID)
/// </summary>
public Guid TargetId { get; set; }
/// <summary>
/// 消息状态(0:已发送,1:已撤回)
/// </summary>
public string State { get; set; }
/// <summary>
/// 消息推送唯一标识符
/// </summary>
public string StreamKey { get; set; }
/// <summary>
/// 消息排序标识
/// </summary>
public long SequenceId { get; set; }
public MsgContent Content { get; set; }
}
public record MsgContent(string Fallback, object Body, Dictionary<string, string> Ext, QuoteInfoDto Quote);
public record QuoteInfoDto(Guid MessageId, Guid SenderId, string SenderName, string MessageType, string Preview);
}
@@ -0,0 +1,16 @@
namespace IM.Commons.IntegrationEvents
{
public class MsgWithdrawEvent
{
public Guid MsgId { get; private set; }
public string State { get; private set; }
public string StreamKey { get; private set; }
public MsgWithdrawEvent(Guid msgId, string state, string streamKey)
{
MsgId = msgId;
State = state;
StreamKey = streamKey;
}
}
}
@@ -0,0 +1,14 @@
namespace IM.Commons.IntegrationEvents
{
public class UserProfileUpdateEvent : BaseEvent
{
public Guid UserId { get; set; }
public string NickName { get; set; }
public string? Avatar { get; set; }
public string Description { get; set; }
public string? Email { get; set; }
public string? Phone { get; set; }
public string Status { get; set; }
}
}
+34
View File
@@ -0,0 +1,34 @@
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;
namespace IM.Commons
{
public class RedisCacheService : IRedisService
{
private readonly IDistributedCache _cache;
public RedisCacheService(IDistributedCache cache)
{
_cache = cache;
}
public async Task<T?> GetAsync<T>(string key)
{
var valueBytes = await _cache.GetAsync(key);
if (valueBytes is null || valueBytes.Length == 0) return default;
return JsonSerializer.Deserialize<T>(valueBytes);
}
public async Task RemoveAsync(string key) => await _cache.RemoveAsync(key);
public async Task SetAsync<T>(string key, T value, TimeSpan? expiration = null)
{
var options = new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = expiration ?? TimeSpan.FromHours(1)
};
var valueBytes = JsonSerializer.SerializeToUtf8Bytes(value);
await _cache.SetAsync(key, valueBytes, options);
}
}
}
+16
View File
@@ -0,0 +1,16 @@
namespace IM.Commons
{
public static class RedisHelper
{
public static string GetRefreshTokenKey(string token) => $"sys:refreshtoken:{token}";
public static string GetUserinfoKey(string userId) => $"user:uinfo:{userId}";
public static string GetUserinfoKeyByUsername(string username) => $"user:uinfobyid:{username}";
public static string GetSequenceIdKey(string streamKey) => $"chat:seq:{streamKey}";
public static string GetSequenceIdLockKey(string streamKey) => $"lock:seq:{streamKey}";
public static string GetConnectionIdKey(string userId) => $"signalr:user:con:{userId}";
public static string GetUploadPartKey(Guid taskId) => $"upload:task:{taskId}:parts";
public static string MergeStatus(Guid taskId) => $"upload:task:{taskId}:merge";
public static string GetUploadInfoKey(string sessionId) => $"upload:task:{sessionId}:info";
}
}
+221
View File
@@ -0,0 +1,221 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
namespace IM.Commons
{
public static class ReflectionHelper
{
/// <summary>
/// 据产品名称获取程序集
/// </summary>
/// <param name="productName"></param>
/// <returns></returns>
public static IEnumerable<Assembly> GetAssembliesByProductName(string productName)
{
var asms = AppDomain.CurrentDomain.GetAssemblies();
foreach (var asm in asms)
{
var asmCompanyAttr = asm.GetCustomAttribute<AssemblyProductAttribute>();
if (asmCompanyAttr != null && asmCompanyAttr.Product == productName)
{
yield return asm;
}
}
}
//是否是微软等的官方Assembly
private static bool IsSystemAssembly(Assembly asm)
{
var asmCompanyAttr = asm.GetCustomAttribute<AssemblyCompanyAttribute>();
if (asmCompanyAttr == null)
{
return false;
}
else
{
string companyName = asmCompanyAttr.Company;
return companyName.Contains("Microsoft");
}
}
private static bool IsSystemAssembly(string asmPath)
{
var moduleDef = AsmResolver.DotNet.ModuleDefinition.FromFile(asmPath);
var assembly = moduleDef.Assembly;
if (assembly == null)
{
return false;
}
var asmCompanyAttr = assembly.CustomAttributes.FirstOrDefault(c => c.Constructor?.DeclaringType?.FullName == typeof(AssemblyCompanyAttribute).FullName);
if (asmCompanyAttr == null)
{
return false;
}
var companyName = ((AsmResolver.Utf8String?)asmCompanyAttr.Signature?.FixedArguments[0]?.Element)?.Value;
if (companyName == null)
{
return false;
}
return companyName.Contains("Microsoft");
}
/// <summary>
/// 判断file这个文件是否是程序集
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
private static bool IsManagedAssembly(string file)
{
using var fs = File.OpenRead(file);
using PEReader peReader = new PEReader(fs);
return peReader.HasMetadata && peReader.GetMetadataReader().IsAssembly;
}
private static Assembly? TryLoadAssembly(string asmPath)
{
AssemblyName asmName = AssemblyName.GetAssemblyName(asmPath);
Assembly? asm = null;
try
{
asm = Assembly.Load(asmName);
}
catch (BadImageFormatException ex)
{
Debug.WriteLine(ex);
}
catch (FileLoadException ex)
{
Debug.WriteLine(ex);
}
if (asm == null)
{
try
{
asm = Assembly.LoadFile(asmPath);
}
catch (BadImageFormatException ex)
{
Debug.WriteLine(ex);
}
catch (FileLoadException ex)
{
Debug.WriteLine(ex);
}
}
return asm;
}
/// <summary>
/// loop through all assemblies
/// </summary>
/// <returns></returns>
public static IEnumerable<Assembly> GetAllReferencedAssemblies(bool skipSystemAssemblies = true)
{
Assembly? rootAssembly = Assembly.GetEntryAssembly();
if (rootAssembly == null)
{
rootAssembly = Assembly.GetCallingAssembly();
}
var returnAssemblies = new HashSet<Assembly>(new AssemblyEquality());
var loadedAssemblies = new HashSet<string>();
var assembliesToCheck = new Queue<Assembly>();
assembliesToCheck.Enqueue(rootAssembly);
if (skipSystemAssemblies && IsSystemAssembly(rootAssembly) != false)
{
if (IsValid(rootAssembly))
{
returnAssemblies.Add(rootAssembly);
}
}
while (assembliesToCheck.Any())
{
var assemblyToCheck = assembliesToCheck.Dequeue();
foreach (var reference in assemblyToCheck.GetReferencedAssemblies())
{
if (!loadedAssemblies.Contains(reference.FullName))
{
var assembly = Assembly.Load(reference);
if (skipSystemAssemblies && IsSystemAssembly(assembly))
{
continue;
}
assembliesToCheck.Enqueue(assembly);
loadedAssemblies.Add(reference.FullName);
if (IsValid(assembly))
{
returnAssemblies.Add(assembly);
}
}
}
}
var asmsInBaseDir = Directory.EnumerateFiles(AppContext.BaseDirectory,
"*.dll", new EnumerationOptions { RecurseSubdirectories = true });
foreach (var asmPath in asmsInBaseDir)
{
if (!IsManagedAssembly(asmPath))
{
continue;
}
AssemblyName asmName = AssemblyName.GetAssemblyName(asmPath);
//如果程序集已经加载过了就不再加载
if (returnAssemblies.Any(x => AssemblyName.ReferenceMatchesDefinition(x.GetName(), asmName)))
{
continue;
}
if (skipSystemAssemblies && IsSystemAssembly(asmPath))
{
continue;
}
Assembly? asm = TryLoadAssembly(asmPath);
if (asm == null)
{
continue;
}
//Assembly asm = Assembly.Load(asmName);
if (!IsValid(asm))
{
continue;
}
if (skipSystemAssemblies && IsSystemAssembly(asm))
{
continue;
}
returnAssemblies.Add(asm);
}
return returnAssemblies.ToArray();
}
private static bool IsValid(Assembly asm)
{
try
{
asm.GetTypes();
asm.DefinedTypes.ToList();
return true;
}
catch (ReflectionTypeLoadException)
{
return false;
}
}
class AssemblyEquality : EqualityComparer<Assembly>
{
public override bool Equals(Assembly? x, Assembly? y)
{
if (x == null && y == null) return true;
if (x == null || y == null) return false;
return AssemblyName.ReferenceMatchesDefinition(x.GetName(), y.GetName());
}
public override int GetHashCode([DisallowNull] Assembly obj)
{
return obj.GetName().FullName.GetHashCode();
}
}
}
}
+36
View File
@@ -0,0 +1,36 @@
using System.Text.Json.Serialization;
namespace IM.Commons
{
public class Result<T>(int code, string message, T? data = default)
{
public int Code { get; private set; } = code;
public string Message { get; private set; } = message;
public T? Data { get; private set; } = data;
[JsonIgnore]
public bool Succeeded
{
get => Code == (int)ResultCode.SUCCESS;
}
public static Result<T> Success(T? data = default) => new((int)ResultCode.SUCCESS, ResultCode.SUCCESS.GetDescription(), data);
public static Result<T> Fail(ResultCode code) => new((int)code, code.GetDescription());
public static Result<T> Fail(ResultCode code, string errorMsg) => new((int)code, errorMsg);
public static Result<T> Fail<FuncT>(Result<FuncT> result) => new(result.Code, result.Message);
}
public class Result
{
public static Result<T> Success<T>(T? data = default) => new((int)ResultCode.SUCCESS, ResultCode.SUCCESS.GetDescription(), data);
public static Result<object> Success() => new((int)ResultCode.SUCCESS, ResultCode.SUCCESS.GetDescription(), null);
public static Result<T> Fail<T>(ResultCode code) => new((int)code, code.GetDescription());
public static Result<object> Fail(ResultCode code) => new((int)code, code.GetDescription());
public static Result<T> Fail<T>(ResultCode code, string errorMsg) => new((int)code, errorMsg);
public static Result<T> Fail<T, FuncT>(Result<FuncT> result) => new(result.Code, result.Message);
public static Result<object> Fail<FuncT>(Result<FuncT> result) => new(result.Code, result.Message);
}
}
+159
View File
@@ -0,0 +1,159 @@
using System.ComponentModel;
namespace IM.Commons
{
public enum ResultCode
{
// 3.1 成功类
/// <summary>成功响应</summary>
[Description("成功")]
SUCCESS = 0,
// 3.2 系统级错误(1000 ~ 1999
/// <summary>未知异常</summary>
[Description("系统错误")]
SYSTEM_ERROR = 1000,
/// <summary>服务器维护中或宕机</summary>
[Description("服务不可用")]
SERVICE_UNAVAILABLE = 1001,
/// <summary>后端超时</summary>
[Description("请求超时")]
REQUEST_TIMEOUT = 1002,
/// <summary>缺少或参数不合法</summary>
[Description("参数错误")]
PARAMETER_ERROR = 1003,
/// <summary>数据库读写失败</summary>
[Description("数据库错误")]
DATABASE_ERROR = 1004,
/// <summary>无权限访问</summary>
[Description("权限不足")]
PERMISSION_DENIED = 1005,
/// <summary>Token 无效/过期</summary>
[Description("认证失败")]
AUTH_FAILED = 1006,
// 3.3 用户相关错误(2000 ~ 2099
/// <summary>查询不到用户</summary>
[Description("用户不存在")]
USER_NOT_FOUND = 2000,
/// <summary>注册时用户已存在</summary>
[Description("用户已存在")]
USER_ALREADY_EXISTS = 2001,
/// <summary>登录密码错误</summary>
[Description("密码错误")]
PASSWORD_ERROR = 2002,
/// <summary>被管理员封禁</summary>
[Description("用户被禁用")]
USER_DISABLED = 2003,
/// <summary>需重新登录</summary>
[Description("登录过期")]
LOGIN_EXPIRED = 2004,
// 3.4 好友相关错误(2100 ~ 2199
/// <summary>重复申请</summary>
[Description("好友申请已存在")]
FRIEND_REQUEST_EXISTS = 2100,
/// <summary>不是好友</summary>
[Description("好友关系不存在")]
FRIEND_RELATION_NOT_FOUND = 2101,
/// <summary>重复添加</summary>
[Description("已经是好友")]
ALREADY_FRIENDS = 2102,
/// <summary>被对方拒绝</summary>
[Description("好友请求被拒绝")]
FRIEND_REQUEST_REJECTED = 2103,
/// <summary>被对方拉黑</summary>
[Description("无法申请加好友")]
CANNOT_ADD_FRIEND = 2104,
/// <summary>好友请求不存在</summary>
[Description("好友请求不存在")]
FRIEND_REQUEST_NOT_FOUND = 2105,
/// <summary>处理好友请求操作无效</summary>
[Description("处理好友请求操作无效")]
INVALID_ACTION = 2106,
/// <summary>注册错误</summary>
[Description("注册错误")]
REGISTER_ERROR = 2107,
// 3.5 群聊相关错误(2200 ~ 2299
/// <summary>查询不到群</summary>
[Description("群不存在")]
GROUP_NOT_FOUND = 2200,
/// <summary>不能重复加入</summary>
[Description("已在群中")]
ALREADY_IN_GROUP = 2201,
/// <summary>超出限制</summary>
[Description("群成员已满")]
GROUP_FULL = 2202,
/// <summary>需要邀请/验证</summary>
[Description("无加群权限")]
NO_GROUP_PERMISSION = 2203,
/// <summary>邀请链接过期</summary>
[Description("群邀请已过期")]
GROUP_INVITE_EXPIRED = 2204,
/// <summary>群聊请求不存在</summary>
[Description("群聊请求不存在")]
GROUP_REQUEST_NOT_FOUND = 2205,
/// <summary>群聊成员成员不存在</summary>
[Description("群聊成员不存在")]
GROUP_MEMBER_NOT_FOUNT = 2206,
// 3.6 消息相关错误(2300 ~ 2399
/// <summary>发送时异常</summary>
[Description("消息发送失败")]
MESSAGE_SEND_FAILED = 2300,
/// <summary>查询不到消息</summary>
[Description("消息不存在")]
MESSAGE_NOT_FOUND = 2301,
/// <summary>超过时间限制</summary>
[Description("消息撤回失败")]
MESSAGE_RECALL_FAILED = 2302,
/// <summary>message_type 不合法</summary>
[Description("不支持的消息类型")]
UNSUPPORTED_MESSAGE_TYPE = 2303,
// 3.7 文件相关错误(2400 ~ 2499
/// <summary>存储服务错误</summary>
[Description("文件上传失败")]
FILE_UPLOAD_FAILED = 2400,
/// <summary>下载时未找到</summary>
[Description("文件不存在")]
FILE_NOT_FOUND = 2401,
/// <summary>超过配置限制</summary>
[Description("文件大小超限")]
FILE_TOO_LARGE = 2402,
/// <summary>格式不允许</summary>
[Description("文件类型不支持")]
FILE_TYPE_NOT_SUPPORTED = 2403,
// 3.8 管理后台相关错误(3000 ~ 3099)
/// <summary>账号错误</summary>
[Description("管理员不存在")]
ADMIN_NOT_FOUND = 3000,
/// <summary>后台登录失败</summary>
[Description("密码错误")]
ADMIN_PASSWORD_ERROR = 3001,
/// <summary>角色未找到</summary>
[Description("角色不存在")]
ROLE_NOT_FOUND = 3002,
/// <summary>无操作权限</summary>
[Description("权限不足")]
ADMIN_PERMISSION_DENIED = 3003,
/// <summary>后台日志写入失败</summary>
[Description("操作记录失败")]
OPERATION_LOG_FAILED = 3004,
// 3.9 会话相关错误(3100 ~ 3199
/// <summary>发送时异常</summary>
[Description("会话不存在")]
CONVERSATION_NOT_FOUND = 3100,
// 3.10 分片相关错误(3200 ~ 3299
/// <summary>分片不存在异常</summary>
[Description("分片不存在")]
CHUNK_NOT_FOUND = 3201,
/// <summary>分片合并异常</summary>
[Description("分片合并失败")]
CHUNK_COMBINE_FAIL = 3202
}
}