committed by
GitHub
16 changed files with 523 additions and 595 deletions
@ -1,26 +1,30 @@ |
|||||
namespace LINGYUN.Abp.IM.Group |
namespace LINGYUN.Abp.IM.Group |
||||
{ |
{ |
||||
public class Group |
public class Group |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// 群组名称
|
/// 群组标识
|
||||
/// </summary>
|
/// </summary>
|
||||
public string Name { get; set; } |
public string Id { get; set; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// 允许匿名聊天
|
/// 群组名称
|
||||
/// </summary>
|
/// </summary>
|
||||
public bool AllowAnonymous { get; set; } |
public string Name { get; set; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// 允许发送消息
|
/// 允许匿名聊天
|
||||
/// </summary>
|
/// </summary>
|
||||
public bool AllowSendMessage { get; set; } |
public bool AllowAnonymous { get; set; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// 最大用户数
|
/// 允许发送消息
|
||||
/// </summary>
|
/// </summary>
|
||||
public int MaxUserLength { get; set; } |
public bool AllowSendMessage { get; set; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// 群组用户数
|
/// 最大用户数
|
||||
/// </summary>
|
/// </summary>
|
||||
public int GroupUserCount { get; set; } |
public int MaxUserLength { get; set; } |
||||
} |
/// <summary>
|
||||
} |
/// 群组用户数
|
||||
|
/// </summary>
|
||||
|
public int GroupUserCount { get; set; } |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -1,18 +1,32 @@ |
|||||
using LINGYUN.Abp.MessageService.Localization; |
using LINGYUN.Abp.MessageService.Localization; |
||||
using Volo.Abp.Localization; |
using Volo.Abp.Localization; |
||||
using Volo.Abp.Modularity; |
using Volo.Abp.Localization.ExceptionHandling; |
||||
|
using Volo.Abp.Modularity; |
||||
namespace LINGYUN.Abp.MessageService |
using Volo.Abp.VirtualFileSystem; |
||||
{ |
|
||||
[DependsOn(typeof(AbpLocalizationModule))] |
namespace LINGYUN.Abp.MessageService |
||||
public class AbpMessageServiceDomainSharedModule : AbpModule |
{ |
||||
{ |
[DependsOn(typeof(AbpLocalizationModule))] |
||||
public override void ConfigureServices(ServiceConfigurationContext context) |
public class AbpMessageServiceDomainSharedModule : AbpModule |
||||
{ |
{ |
||||
Configure<AbpLocalizationOptions>(options => |
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
{ |
{ |
||||
options.Resources.Add<MessageServiceResource>("en"); |
Configure<AbpVirtualFileSystemOptions>(options => |
||||
}); |
{ |
||||
} |
options.FileSets.AddEmbedded<AbpMessageServiceDomainSharedModule>(); |
||||
} |
}); |
||||
} |
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Add<MessageServiceResource>("en") |
||||
|
.AddVirtualJson("/LINGYUN/Abp/MessageService/Localization/Resources"); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpExceptionLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.MapCodeNamespace(MessageServiceErrorCodes.Namespace, typeof(MessageServiceResource)); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -1,55 +1,38 @@ |
|||||
using LINGYUN.Abp.MessageService.Chat; |
using LINGYUN.Abp.MessageService.Chat; |
||||
using LINGYUN.Abp.MessageService.Localization; |
using LINGYUN.Abp.MessageService.Localization; |
||||
using LINGYUN.Abp.MessageService.Mapper; |
using LINGYUN.Abp.MessageService.Mapper; |
||||
using LINGYUN.Abp.MessageService.ObjectExtending; |
using LINGYUN.Abp.MessageService.ObjectExtending; |
||||
using Volo.Abp.AutoMapper; |
using Volo.Abp.AutoMapper; |
||||
using Volo.Abp.Caching; |
using Volo.Abp.Caching; |
||||
using Volo.Abp.Localization; |
using Volo.Abp.Localization; |
||||
using Volo.Abp.Localization.ExceptionHandling; |
using Volo.Abp.Localization.ExceptionHandling; |
||||
using Volo.Abp.Modularity; |
using Volo.Abp.Modularity; |
||||
using Volo.Abp.ObjectExtending.Modularity; |
using Volo.Abp.ObjectExtending.Modularity; |
||||
using Volo.Abp.VirtualFileSystem; |
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
namespace LINGYUN.Abp.MessageService |
namespace LINGYUN.Abp.MessageService |
||||
{ |
{ |
||||
[DependsOn( |
[DependsOn( |
||||
typeof(AbpAutoMapperModule), |
typeof(AbpAutoMapperModule), |
||||
typeof(AbpCachingModule), |
typeof(AbpCachingModule), |
||||
typeof(AbpMessageServiceDomainSharedModule))] |
typeof(AbpMessageServiceDomainSharedModule))] |
||||
public class AbpMessageServiceDomainModule : AbpModule |
public class AbpMessageServiceDomainModule : AbpModule |
||||
{ |
{ |
||||
public override void ConfigureServices(ServiceConfigurationContext context) |
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
{ |
{ |
||||
Configure<AbpAutoMapperOptions>(options => |
Configure<AbpAutoMapperOptions>(options => |
||||
{ |
{ |
||||
options.AddProfile<MessageServiceDomainAutoMapperProfile>(validate: true); |
options.AddProfile<MessageServiceDomainAutoMapperProfile>(validate: true); |
||||
}); |
}); |
||||
|
} |
||||
Configure<AbpVirtualFileSystemOptions>(options => |
|
||||
{ |
public override void PostConfigureServices(ServiceConfigurationContext context) |
||||
options.FileSets.AddEmbedded<AbpMessageServiceDomainModule>(); |
{ |
||||
}); |
ModuleExtensionConfigurationHelper.ApplyEntityConfigurationToEntity( |
||||
|
MessageServiceModuleExtensionConsts.ModuleName, |
||||
Configure<AbpLocalizationOptions>(options => |
MessageServiceModuleExtensionConsts.EntityNames.Message, |
||||
{ |
typeof(Message) |
||||
options.Resources |
); |
||||
.Get<MessageServiceResource>() |
} |
||||
.AddVirtualJson("/LINGYUN/Abp/MessageService/Localization/Resources"); |
} |
||||
}); |
} |
||||
|
|
||||
Configure<AbpExceptionLocalizationOptions>(options => |
|
||||
{ |
|
||||
options.MapCodeNamespace(MessageServiceErrorCodes.Namespace, typeof(MessageServiceResource)); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
public override void PostConfigureServices(ServiceConfigurationContext context) |
|
||||
{ |
|
||||
ModuleExtensionConfigurationHelper.ApplyEntityConfigurationToEntity( |
|
||||
MessageServiceModuleExtensionConsts.ModuleName, |
|
||||
MessageServiceModuleExtensionConsts.EntityNames.Message, |
|
||||
typeof(Message) |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|||||
@ -1,37 +0,0 @@ |
|||||
{ |
|
||||
"culture": "en", |
|
||||
"texts": { |
|
||||
"LINGYUN.Abp.Message:01400": "Sending the message failed: The message is incomplete!", |
|
||||
"LINGYUN.Abp.Message:01401": "You have not joined the group and cannot operate!", |
|
||||
"LINGYUN.Abp.Message:02301": "Group application has been sent, waiting for administrator's approval", |
|
||||
"LINGYUN.Abp.Message:02302": "You need to validate the questions to join the group chat", |
|
||||
"LINGYUN.Abp.Message:02400": "The administrator has turned on silence mode!", |
|
||||
"LINGYUN.Abp.Message:02403": "The administrator has banned you from speaking!", |
|
||||
"LINGYUN.Abp.Message:02401": "The administrator does not allow anonymous speaking!", |
|
||||
"LINGYUN.Abp.Message:02404": "Sending the message failed: the group does not exist or is disbanded!", |
|
||||
"LINGYUN.Abp.Message:03301": "Friend request has been sent, waiting for the other party's approval", |
|
||||
"LINGYUN.Abp.Message:03302": "You need to verify the problem to add friends", |
|
||||
"LINGYUN.Abp.Message:03400": "The user has rejected all messages!", |
|
||||
"LINGYUN.Abp.Message:03401": "The user rejects the message you sent!", |
|
||||
"LINGYUN.Abp.Message:03402": "Users do not receive anonymous comments!", |
|
||||
"LINGYUN.Abp.Message:03403": "Sending the message failed: the person needs to agree to add a friend!", |
|
||||
"LINGYUN.Abp.Message:03404": "Sending the message failed: the user does not exist or is deactivated!", |
|
||||
"LINGYUN.Abp.Message:03410": "Users refuse to add friends", |
|
||||
"LINGYUN.Abp.Message:03411": "The other party is already your friend or has sent an authentication request. The operation cannot be repeated!", |
|
||||
"Notifications:MultiTenancy": "Multi Tenancy", |
|
||||
"Notifications:Users": "Users", |
|
||||
"Notifications:NewTenantRegisterd": "Tenant creation notification", |
|
||||
"Notifications:WelcomeToApplication": "User Welcome Notice", |
|
||||
"Notifications:IM": "Instant Messaging", |
|
||||
"Notifications:FriendValidation": "Friend verification notification", |
|
||||
"Notifications:NewFriend": "New friend notification", |
|
||||
"Notifications:RequestAddNewFriend": "User {name} has requested that you be added as a friend", |
|
||||
"Notifications:RequestAddNewFriendDetail": "Description: {description}", |
|
||||
"Notifications:JoinGroup": "Join group notification", |
|
||||
"Notifications:ExitGroup": "Exit group notification", |
|
||||
"Notifications:DissolveGroup": "Dissolve group notification", |
|
||||
"AddNewFriendBySearchId": "Add by account search", |
|
||||
"WelcomeToApplicationFormUser": "User :{0} welcome to join us!", |
|
||||
"Messages:NewFriend": "I have added you as a friend, let's chat together!" |
|
||||
} |
|
||||
} |
|
||||
@ -1,37 +0,0 @@ |
|||||
{ |
|
||||
"culture": "zh-Hans", |
|
||||
"texts": { |
|
||||
"LINGYUN.Abp.Message:01400": "发送消息失败: 消息不完整!", |
|
||||
"LINGYUN.Abp.Message:01401": "您还未加入群组,不能进行操作!", |
|
||||
"LINGYUN.Abp.Message:02301": "已发送群组申请,等待管理员同意", |
|
||||
"LINGYUN.Abp.Message:02302": "你需要验证问题才能加入群聊", |
|
||||
"LINGYUN.Abp.Message:02400": "管理员已开启全员禁言!", |
|
||||
"LINGYUN.Abp.Message:02403": "管理员已禁止您发言!", |
|
||||
"LINGYUN.Abp.Message:02401": "管理员不允许匿名发言!", |
|
||||
"LINGYUN.Abp.Message:02404": "发送消息失败: 群组不存在或已解散!", |
|
||||
"LINGYUN.Abp.Message:03301": "已发送好友申请,等待对方同意", |
|
||||
"LINGYUN.Abp.Message:03302": "你需要验证问题才能添加好友", |
|
||||
"LINGYUN.Abp.Message:03400": "用户已拒接所有消息!", |
|
||||
"LINGYUN.Abp.Message:03401": "用户拒绝您发送的消息!", |
|
||||
"LINGYUN.Abp.Message:03402": "用户不接收匿名发言!", |
|
||||
"LINGYUN.Abp.Message:03403": "需要对方同意添加好友才能发送消息!", |
|
||||
"LINGYUN.Abp.Message:03404": "发送消息失败: 用户不存在或已注销账号!", |
|
||||
"LINGYUN.Abp.Message:03410": "用户拒绝添加好友", |
|
||||
"LINGYUN.Abp.Message:03411": "对方已是您的好友或已发送验证请求,不能重复操作!", |
|
||||
"Notifications:MultiTenancy": "租户通知", |
|
||||
"Notifications:Users": "用户通知", |
|
||||
"Notifications:NewTenantRegisterd": "租户创建通知", |
|
||||
"Notifications:WelcomeToApplication": "用户欢迎通知", |
|
||||
"Notifications:IM": "即时通讯", |
|
||||
"Notifications:FriendValidation": "好友验证通知", |
|
||||
"Notifications:NewFriend": "新好友通知", |
|
||||
"Notifications:RequestAddNewFriend": "用户 {name} 请求添加您为好友", |
|
||||
"Notifications:RequestAddNewFriendDetail": "附加说明: {description}", |
|
||||
"Notifications:JoinGroup": "加入群组通知", |
|
||||
"Notifications:ExitGroup": "退出群组通知", |
|
||||
"Notifications:DissolveGroup": "群组解散通知", |
|
||||
"AddNewFriendBySearchId": "通过账号搜索添加", |
|
||||
"WelcomeToApplicationFormUser": "用户:{0} 欢迎您的加入!", |
|
||||
"Messages:NewFriend": "我已经添加您为好友,让我们一起聊天吧!" |
|
||||
} |
|
||||
} |
|
||||
@ -1,221 +1,221 @@ |
|||||
using LINGYUN.Abp.MessageService.Utils; |
using LINGYUN.Abp.MessageService.Utils; |
||||
using LINGYUN.Abp.Notifications; |
using LINGYUN.Abp.Notifications; |
||||
using LINGYUN.Abp.RealTime; |
using LINGYUN.Abp.RealTime; |
||||
using Microsoft.Extensions.Logging; |
using Microsoft.Extensions.Logging; |
||||
using Microsoft.Extensions.Logging.Abstractions; |
using Microsoft.Extensions.Logging.Abstractions; |
||||
using Microsoft.Extensions.Options; |
using Microsoft.Extensions.Options; |
||||
using System; |
using System; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
using System.Linq; |
using System.Linq; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
using Volo.Abp.BackgroundJobs; |
using Volo.Abp.BackgroundJobs; |
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.DependencyInjection; |
||||
using Volo.Abp.EventBus.Distributed; |
using Volo.Abp.EventBus.Distributed; |
||||
using Volo.Abp.Json; |
using Volo.Abp.Json; |
||||
using Volo.Abp.Uow; |
using Volo.Abp.Uow; |
||||
|
|
||||
namespace LINGYUN.Abp.MessageService.EventBus.Distributed |
namespace LINGYUN.Abp.MessageService.EventBus.Distributed |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// 订阅通知发布事件,统一发布消息
|
/// 订阅通知发布事件,统一发布消息
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <remarks>
|
/// <remarks>
|
||||
/// 作用在于SignalR客户端只会与一台服务器建立连接,
|
/// 作用在于SignalR客户端只会与一台服务器建立连接,
|
||||
/// 只有启用了SignlR服务端的才能真正将消息发布到客户端
|
/// 只有启用了SignlR服务端的才能真正将消息发布到客户端
|
||||
/// </remarks>
|
/// </remarks>
|
||||
public class NotificationEventHandler : IDistributedEventHandler<NotificationEto<NotificationData>>, ITransientDependency |
public class NotificationEventHandler : IDistributedEventHandler<NotificationEto<NotificationData>>, ITransientDependency |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// Reference to <see cref="ILogger<DefaultNotificationDispatcher>"/>.
|
/// Reference to <see cref="ILogger<DefaultNotificationDispatcher>"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
public ILogger<NotificationEventHandler> Logger { get; set; } |
public ILogger<NotificationEventHandler> Logger { get; set; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// Reference to <see cref="AbpNotificationOptions"/>.
|
/// Reference to <see cref="AbpNotificationOptions"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
protected AbpNotificationOptions Options { get; } |
protected AbpNotificationOptions Options { get; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// Reference to <see cref="IJsonSerializer"/>.
|
/// Reference to <see cref="IJsonSerializer"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
protected IJsonSerializer JsonSerializer { get; } |
protected IJsonSerializer JsonSerializer { get; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// Reference to <see cref="IBackgroundJobManager"/>.
|
/// Reference to <see cref="IBackgroundJobManager"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
protected IBackgroundJobManager BackgroundJobManager { get; } |
protected IBackgroundJobManager BackgroundJobManager { get; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// Reference to <see cref="INotificationStore"/>.
|
/// Reference to <see cref="INotificationStore"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
protected INotificationStore NotificationStore { get; } |
protected INotificationStore NotificationStore { get; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// Reference to <see cref="INotificationDefinitionManager"/>.
|
/// Reference to <see cref="INotificationDefinitionManager"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
protected INotificationDefinitionManager NotificationDefinitionManager { get; } |
protected INotificationDefinitionManager NotificationDefinitionManager { get; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// Reference to <see cref="INotificationSubscriptionManager"/>.
|
/// Reference to <see cref="INotificationSubscriptionManager"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } |
protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } |
||||
/// <summary>
|
/// <summary>
|
||||
/// Reference to <see cref="INotificationPublishProviderManager"/>.
|
/// Reference to <see cref="INotificationPublishProviderManager"/>.
|
||||
/// </summary>
|
/// </summary>
|
||||
protected INotificationPublishProviderManager NotificationPublishProviderManager { get; } |
protected INotificationPublishProviderManager NotificationPublishProviderManager { get; } |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NotificationEventHandler"/> class.
|
/// Initializes a new instance of the <see cref="NotificationEventHandler"/> class.
|
||||
/// </summary>
|
/// </summary>
|
||||
public NotificationEventHandler( |
public NotificationEventHandler( |
||||
IJsonSerializer jsonSerializer, |
IJsonSerializer jsonSerializer, |
||||
IBackgroundJobManager backgroundJobManager, |
IBackgroundJobManager backgroundJobManager, |
||||
IOptions<AbpNotificationOptions> options, |
IOptions<AbpNotificationOptions> options, |
||||
INotificationStore notificationStore, |
INotificationStore notificationStore, |
||||
INotificationDefinitionManager notificationDefinitionManager, |
INotificationDefinitionManager notificationDefinitionManager, |
||||
INotificationSubscriptionManager notificationSubscriptionManager, |
INotificationSubscriptionManager notificationSubscriptionManager, |
||||
INotificationPublishProviderManager notificationPublishProviderManager) |
INotificationPublishProviderManager notificationPublishProviderManager) |
||||
{ |
{ |
||||
Options = options.Value; |
Options = options.Value; |
||||
JsonSerializer = jsonSerializer; |
JsonSerializer = jsonSerializer; |
||||
BackgroundJobManager = backgroundJobManager; |
BackgroundJobManager = backgroundJobManager; |
||||
NotificationStore = notificationStore; |
NotificationStore = notificationStore; |
||||
NotificationDefinitionManager = notificationDefinitionManager; |
NotificationDefinitionManager = notificationDefinitionManager; |
||||
NotificationSubscriptionManager = notificationSubscriptionManager; |
NotificationSubscriptionManager = notificationSubscriptionManager; |
||||
NotificationPublishProviderManager = notificationPublishProviderManager; |
NotificationPublishProviderManager = notificationPublishProviderManager; |
||||
|
|
||||
Logger = NullLogger<NotificationEventHandler>.Instance; |
Logger = NullLogger<NotificationEventHandler>.Instance; |
||||
} |
} |
||||
|
|
||||
[UnitOfWork] |
[UnitOfWork] |
||||
public virtual async Task HandleEventAsync(NotificationEto<NotificationData> eventData) |
public virtual async Task HandleEventAsync(NotificationEto<NotificationData> eventData) |
||||
{ |
{ |
||||
// 如果上面过滤了应用程序,这里可以使用Get方法,否则,最好使用GetOrNull加以判断
|
// 如果上面过滤了应用程序,这里可以使用Get方法,否则,最好使用GetOrNull加以判断
|
||||
var notification = NotificationDefinitionManager.GetOrNull(eventData.Name); |
var notification = NotificationDefinitionManager.GetOrNull(eventData.Name); |
||||
if (notification == null) |
if (notification == null) |
||||
{ |
{ |
||||
return; |
return; |
||||
} |
} |
||||
|
|
||||
var notificationInfo = new NotificationInfo |
var notificationInfo = new NotificationInfo |
||||
{ |
{ |
||||
Name = notification.Name, |
Name = notification.Name, |
||||
CreationTime = eventData.CreationTime, |
CreationTime = eventData.CreationTime, |
||||
Data = eventData.Data, |
Data = eventData.Data, |
||||
Severity = eventData.Severity, |
Severity = eventData.Severity, |
||||
Lifetime = notification.NotificationLifetime, |
Lifetime = notification.NotificationLifetime, |
||||
TenantId = eventData.TenantId, |
TenantId = eventData.TenantId, |
||||
Type = notification.NotificationType |
Type = notification.NotificationType |
||||
}; |
}; |
||||
notificationInfo.SetId(eventData.Id); |
notificationInfo.SetId(eventData.Id); |
||||
|
|
||||
// TODO: 可以做成一个接口来序列化消息
|
// TODO: 可以做成一个接口来序列化消息
|
||||
notificationInfo.Data = NotificationDataConverter.Convert(notificationInfo.Data); |
notificationInfo.Data = NotificationDataConverter.Convert(notificationInfo.Data); |
||||
|
|
||||
Logger.LogDebug($"Persistent notification {notificationInfo.Name}"); |
Logger.LogDebug($"Persistent notification {notificationInfo.Name}"); |
||||
|
|
||||
// 持久化通知
|
// 持久化通知
|
||||
await NotificationStore.InsertNotificationAsync(notificationInfo); |
await NotificationStore.InsertNotificationAsync(notificationInfo); |
||||
|
|
||||
var providers = Enumerable |
var providers = Enumerable |
||||
.Reverse(NotificationPublishProviderManager.Providers); |
.Reverse(NotificationPublishProviderManager.Providers); |
||||
|
|
||||
await PublishFromProvidersAsync(providers, eventData.Users, notificationInfo); |
await PublishFromProvidersAsync(providers, eventData.Users, notificationInfo); |
||||
} |
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// 指定提供者发布通知
|
/// 指定提供者发布通知
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="providers">提供者列表</param>
|
/// <param name="providers">提供者列表</param>
|
||||
/// <param name="notificationInfo">通知信息</param>
|
/// <param name="notificationInfo">通知信息</param>
|
||||
/// <returns></returns>
|
/// <returns></returns>
|
||||
protected async Task PublishFromProvidersAsync( |
protected async Task PublishFromProvidersAsync( |
||||
IEnumerable<INotificationPublishProvider> providers, |
IEnumerable<INotificationPublishProvider> providers, |
||||
IEnumerable<UserIdentifier> users, |
IEnumerable<UserIdentifier> users, |
||||
NotificationInfo notificationInfo) |
NotificationInfo notificationInfo) |
||||
{ |
{ |
||||
// 检查是够已订阅消息
|
// 检查是够已订阅消息
|
||||
Logger.LogDebug($"Gets a list of user subscriptions {notificationInfo.Name}"); |
Logger.LogDebug($"Gets a list of user subscriptions {notificationInfo.Name}"); |
||||
List<NotificationSubscriptionInfo> userSubscriptions; |
List<NotificationSubscriptionInfo> userSubscriptions; |
||||
if (users == null) |
if (users == null) |
||||
{ |
{ |
||||
// 获取用户订阅列表
|
// 获取用户订阅列表
|
||||
userSubscriptions = await NotificationSubscriptionManager |
userSubscriptions = await NotificationSubscriptionManager |
||||
.GetUserSubscriptionsAsync(notificationInfo.TenantId, notificationInfo.Name); |
.GetUserSubscriptionsAsync(notificationInfo.TenantId, notificationInfo.Name); |
||||
} |
} |
||||
else |
else |
||||
{ |
{ |
||||
// 过滤未订阅的用户
|
// 过滤未订阅的用户
|
||||
userSubscriptions = await NotificationSubscriptionManager |
userSubscriptions = await NotificationSubscriptionManager |
||||
.GetUsersSubscriptionsAsync(notificationInfo.TenantId, notificationInfo.Name, users); |
.GetUsersSubscriptionsAsync(notificationInfo.TenantId, notificationInfo.Name, users); |
||||
} |
} |
||||
|
|
||||
users = userSubscriptions.Select(us => new UserIdentifier(us.UserId, us.UserName)); |
users = userSubscriptions.Select(us => new UserIdentifier(us.UserId, us.UserName)); |
||||
|
|
||||
if (users.Count() > 0) |
if (users.Any()) |
||||
{ |
{ |
||||
// 持久化用户通知
|
// 持久化用户通知
|
||||
Logger.LogDebug($"Persistent user notifications {notificationInfo.Name}"); |
Logger.LogDebug($"Persistent user notifications {notificationInfo.Name}"); |
||||
await NotificationStore |
await NotificationStore |
||||
.InsertUserNotificationsAsync( |
.InsertUserNotificationsAsync( |
||||
notificationInfo, |
notificationInfo, |
||||
users.Select(u => u.UserId)); |
users.Select(u => u.UserId)); |
||||
|
|
||||
// 2020-11-02 fix bug, 多个发送提供者处于同一个工作单元之下,不能把删除用户订阅写入到单个通知提供者完成事件中
|
// 2020-11-02 fix bug, 多个发送提供者处于同一个工作单元之下,不能把删除用户订阅写入到单个通知提供者完成事件中
|
||||
// 而且为了确保一致性,删除订阅移动到发布通知之前
|
// 而且为了确保一致性,删除订阅移动到发布通知之前
|
||||
if (notificationInfo.Lifetime == NotificationLifetime.OnlyOne) |
if (notificationInfo.Lifetime == NotificationLifetime.OnlyOne) |
||||
{ |
{ |
||||
// 一次性通知在发送完成后就取消用户订阅
|
// 一次性通知在发送完成后就取消用户订阅
|
||||
await NotificationStore |
await NotificationStore |
||||
.DeleteUserSubscriptionAsync( |
.DeleteUserSubscriptionAsync( |
||||
notificationInfo.TenantId, |
notificationInfo.TenantId, |
||||
users, |
users, |
||||
notificationInfo.Name); |
notificationInfo.Name); |
||||
} |
} |
||||
|
|
||||
// 发布通知
|
// 发布通知
|
||||
foreach (var provider in providers) |
foreach (var provider in providers) |
||||
{ |
{ |
||||
await PublishAsync(provider, notificationInfo, users); |
await PublishAsync(provider, notificationInfo, users); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
/// <summary>
|
/// <summary>
|
||||
/// 发布通知
|
/// 发布通知
|
||||
/// </summary>
|
/// </summary>
|
||||
/// <param name="provider">通知发布者</param>
|
/// <param name="provider">通知发布者</param>
|
||||
/// <param name="notificationInfo">通知信息</param>
|
/// <param name="notificationInfo">通知信息</param>
|
||||
/// <param name="subscriptionUserIdentifiers">订阅用户列表</param>
|
/// <param name="subscriptionUserIdentifiers">订阅用户列表</param>
|
||||
/// <returns></returns>
|
/// <returns></returns>
|
||||
protected async Task PublishAsync( |
protected async Task PublishAsync( |
||||
INotificationPublishProvider provider, |
INotificationPublishProvider provider, |
||||
NotificationInfo notificationInfo, |
NotificationInfo notificationInfo, |
||||
IEnumerable<UserIdentifier> subscriptionUserIdentifiers) |
IEnumerable<UserIdentifier> subscriptionUserIdentifiers) |
||||
{ |
{ |
||||
try |
try |
||||
{ |
{ |
||||
Logger.LogDebug($"Sending notification with provider {provider.Name}"); |
Logger.LogDebug($"Sending notification with provider {provider.Name}"); |
||||
var notifacationDataMapping = Options.NotificationDataMappings |
var notifacationDataMapping = Options.NotificationDataMappings |
||||
.GetMapItemOrDefault(notificationInfo.Name, provider.Name); |
.GetMapItemOrDefault(notificationInfo.Name, provider.Name); |
||||
if (notifacationDataMapping != null) |
if (notifacationDataMapping != null) |
||||
{ |
{ |
||||
notificationInfo.Data = notifacationDataMapping.MappingFunc(notificationInfo.Data); |
notificationInfo.Data = notifacationDataMapping.MappingFunc(notificationInfo.Data); |
||||
} |
} |
||||
// 发布
|
// 发布
|
||||
await provider.PublishAsync(notificationInfo, subscriptionUserIdentifiers); |
await provider.PublishAsync(notificationInfo, subscriptionUserIdentifiers); |
||||
|
|
||||
Logger.LogDebug($"Send notification {notificationInfo.Name} with provider {provider.Name} was successful"); |
Logger.LogDebug($"Send notification {notificationInfo.Name} with provider {provider.Name} was successful"); |
||||
} |
} |
||||
catch (Exception ex) |
catch (Exception ex) |
||||
{ |
{ |
||||
Logger.LogWarning($"Send notification error with provider {provider.Name}"); |
Logger.LogWarning($"Send notification error with provider {provider.Name}"); |
||||
Logger.LogWarning($"Error message:{ex.Message}"); |
Logger.LogWarning($"Error message:{ex.Message}"); |
||||
|
|
||||
Logger.LogTrace(ex, $"Send notification error with provider { provider.Name}"); |
Logger.LogTrace(ex, $"Send notification error with provider { provider.Name}"); |
||||
|
|
||||
Logger.LogDebug($"Send notification error, notification {notificationInfo.Name} entry queue"); |
Logger.LogDebug($"Send notification error, notification {notificationInfo.Name} entry queue"); |
||||
// 发送失败的消息进入后台队列
|
// 发送失败的消息进入后台队列
|
||||
await BackgroundJobManager.EnqueueAsync( |
await BackgroundJobManager.EnqueueAsync( |
||||
new NotificationPublishJobArgs( |
new NotificationPublishJobArgs( |
||||
notificationInfo.GetId(), |
notificationInfo.GetId(), |
||||
provider.GetType().AssemblyQualifiedName, |
provider.GetType().AssemblyQualifiedName, |
||||
subscriptionUserIdentifiers.ToList(), |
subscriptionUserIdentifiers.ToList(), |
||||
notificationInfo.TenantId)); |
notificationInfo.TenantId)); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,83 +1,72 @@ |
|||||
using LINGYUN.Abp.MessageService.Localization; |
using LINGYUN.Abp.MessageService.Localization; |
||||
using LINGYUN.Abp.MultiTenancy; |
using LINGYUN.Abp.MultiTenancy; |
||||
using LINGYUN.Abp.Notifications; |
using LINGYUN.Abp.Notifications; |
||||
using Microsoft.Extensions.Localization; |
using Microsoft.Extensions.Logging; |
||||
using Microsoft.Extensions.Logging; |
using System; |
||||
using System; |
using System.Collections.Generic; |
||||
using System.Globalization; |
using System.Threading.Tasks; |
||||
using System.Threading.Tasks; |
using Volo.Abp.DependencyInjection; |
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.EventBus.Distributed; |
||||
using Volo.Abp.EventBus.Distributed; |
using Volo.Abp.Localization; |
||||
using Volo.Abp.Localization; |
using Volo.Abp.MultiTenancy; |
||||
using Volo.Abp.MultiTenancy; |
|
||||
using Volo.Abp.Settings; |
namespace LINGYUN.Abp.MessageService.EventBus.Distributed |
||||
|
{ |
||||
namespace LINGYUN.Abp.MessageService.EventBus.Distributed |
public class TenantCreateEventHandler : IDistributedEventHandler<CreateEventData>, ITransientDependency |
||||
{ |
{ |
||||
public class TenantCreateEventHandler : IDistributedEventHandler<CreateEventData>, ITransientDependency |
protected ILogger<TenantCreateEventHandler> Logger { get; } |
||||
{ |
protected INotificationSender NotificationSender { get; } |
||||
protected ILogger<TenantCreateEventHandler> Logger { get; } |
protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } |
||||
protected ICurrentTenant CurrentTenant { get; } |
|
||||
protected ISettingProvider SettingProvider { get; } |
public TenantCreateEventHandler( |
||||
protected IStringLocalizer StringLocalizer { get; } |
INotificationSender notificationSender, |
||||
protected INotificationSender NotificationSender { get; } |
INotificationSubscriptionManager notificationSubscriptionManager, |
||||
protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } |
ILogger<TenantCreateEventHandler> logger) |
||||
|
{ |
||||
public TenantCreateEventHandler( |
Logger = logger; |
||||
ICurrentTenant currentTenant, |
NotificationSender = notificationSender; |
||||
ISettingProvider settingProvider, |
NotificationSubscriptionManager = notificationSubscriptionManager; |
||||
INotificationSender notificationSender, |
} |
||||
INotificationSubscriptionManager notificationSubscriptionManager, |
|
||||
IStringLocalizer<MessageServiceResource> stringLocalizer, |
public async Task HandleEventAsync(CreateEventData eventData) |
||||
ILogger<TenantCreateEventHandler> logger) |
{ |
||||
{ |
var tenantAdminUserIdentifier = new UserIdentifier(eventData.AdminUserId, eventData.AdminEmailAddress); |
||||
Logger = logger; |
|
||||
CurrentTenant = currentTenant; |
Logger.LogInformation("tenant administrator subscribes to new tenant events.."); |
||||
SettingProvider = settingProvider; |
// 租户管理员订阅事件
|
||||
StringLocalizer = stringLocalizer; |
await NotificationSubscriptionManager |
||||
NotificationSender = notificationSender; |
.SubscribeAsync( |
||||
NotificationSubscriptionManager = notificationSubscriptionManager; |
eventData.Id, |
||||
} |
tenantAdminUserIdentifier, |
||||
|
TenantNotificationNames.NewTenantRegistered); |
||||
public async Task HandleEventAsync(CreateEventData eventData) |
|
||||
{ |
var notificationData = new NotificationData(); |
||||
var tenantAdminUserIdentifier = new UserIdentifier(eventData.AdminUserId, eventData.AdminEmailAddress); |
notificationData.WriteLocalizedData( |
||||
|
new LocalizableStringInfo( |
||||
// 租户管理员订阅事件
|
LocalizationResourceNameAttribute.GetName(typeof(MessageServiceResource)), |
||||
await NotificationSubscriptionManager |
"NewTenantRegisteredNotificationTitle", |
||||
.SubscribeAsync( |
new Dictionary<object, object> |
||||
eventData.Id, |
{ |
||||
tenantAdminUserIdentifier, |
{ "User", eventData.Name } |
||||
TenantNotificationNames.NewTenantRegistered); |
}), |
||||
|
new LocalizableStringInfo( |
||||
var userDefaultCultureName = await SettingProvider.GetOrNullAsync(LocalizationSettingNames.DefaultLanguage); |
LocalizationResourceNameAttribute.GetName(typeof(MessageServiceResource)), |
||||
if (userDefaultCultureName.IsNullOrWhiteSpace()) |
"NewTenantRegisteredNotificationMessage", |
||||
{ |
new Dictionary<object, object> |
||||
userDefaultCultureName = CultureInfo.CurrentUICulture.Name; |
{ |
||||
} |
{ "User", eventData.Name} |
||||
// 使用系统区域语言发布通知
|
}), |
||||
using (CultureHelper.Use(userDefaultCultureName, userDefaultCultureName)) |
DateTime.Now, eventData.AdminEmailAddress); |
||||
{ |
|
||||
var notificationData = new NotificationData(); |
Logger.LogInformation("publish new tenant notification.."); |
||||
notificationData.WriteStandardData( |
// 发布租户创建通知
|
||||
L("NewTenantRegisteredNotificationTitle"), |
await NotificationSender |
||||
L("NewTenantRegisteredNotificationMessage", eventData.Name), |
.SendNofiterAsync( |
||||
DateTime.Now, eventData.AdminEmailAddress); |
TenantNotificationNames.NewTenantRegistered, |
||||
|
notificationData, |
||||
// 发布租户创建通知
|
tenantAdminUserIdentifier, |
||||
await NotificationSender |
eventData.Id, |
||||
.SendNofiterAsync( |
NotificationSeverity.Success); |
||||
TenantNotificationNames.NewTenantRegistered, |
} |
||||
notificationData, |
} |
||||
tenantAdminUserIdentifier, |
} |
||||
eventData.Id, |
|
||||
NotificationSeverity.Success); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
protected string L(string name, params object[] args) |
|
||||
{ |
|
||||
return StringLocalizer[name, args]?.Value; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|||||
@ -1,63 +1,72 @@ |
|||||
using LINGYUN.Abp.MessageService.Localization; |
using LINGYUN.Abp.MessageService.Localization; |
||||
using LINGYUN.Abp.Notifications; |
using LINGYUN.Abp.Notifications; |
||||
using System; |
using System; |
||||
using System.Threading.Tasks; |
using System.Collections.Generic; |
||||
using Volo.Abp.DependencyInjection; |
using System.Threading.Tasks; |
||||
using Volo.Abp.Domain.Entities.Events; |
using Volo.Abp.DependencyInjection; |
||||
using Volo.Abp.EventBus; |
using Volo.Abp.Domain.Entities.Events; |
||||
using Volo.Abp.Localization; |
using Volo.Abp.EventBus; |
||||
using Volo.Abp.Users; |
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Users; |
||||
namespace LINGYUN.Abp.MessageService.EventBus |
|
||||
{ |
namespace LINGYUN.Abp.MessageService.EventBus |
||||
public class UserCreateSendWelcomeEventHandler : ILocalEventHandler<EntityCreatedEventData<UserEto>>, ITransientDependency |
{ |
||||
{ |
public class UserCreateSendWelcomeEventHandler : ILocalEventHandler<EntityCreatedEventData<UserEto>>, ITransientDependency |
||||
private readonly INotificationSender _notificationSender; |
{ |
||||
private readonly INotificationSubscriptionManager _notificationSubscriptionManager; |
private readonly INotificationSender _notificationSender; |
||||
public UserCreateSendWelcomeEventHandler( |
private readonly INotificationSubscriptionManager _notificationSubscriptionManager; |
||||
INotificationSender notificationSender, |
public UserCreateSendWelcomeEventHandler( |
||||
INotificationSubscriptionManager notificationSubscriptionManager |
INotificationSender notificationSender, |
||||
) |
INotificationSubscriptionManager notificationSubscriptionManager |
||||
{ |
) |
||||
_notificationSender = notificationSender; |
{ |
||||
_notificationSubscriptionManager = notificationSubscriptionManager; |
_notificationSender = notificationSender; |
||||
} |
_notificationSubscriptionManager = notificationSubscriptionManager; |
||||
|
} |
||||
public async Task HandleEventAsync(EntityCreatedEventData<UserEto> eventData) |
|
||||
{ |
public async Task HandleEventAsync(EntityCreatedEventData<UserEto> eventData) |
||||
var userIdentifer = new UserIdentifier(eventData.Entity.Id, eventData.Entity.UserName); |
{ |
||||
// 订阅用户欢迎消息
|
var userIdentifer = new UserIdentifier(eventData.Entity.Id, eventData.Entity.UserName); |
||||
await _notificationSubscriptionManager |
// 订阅用户欢迎消息
|
||||
.SubscribeAsync( |
await _notificationSubscriptionManager |
||||
eventData.Entity.TenantId, |
.SubscribeAsync( |
||||
userIdentifer, |
eventData.Entity.TenantId, |
||||
UserNotificationNames.WelcomeToApplication); |
userIdentifer, |
||||
|
UserNotificationNames.WelcomeToApplication); |
||||
var userWelcomeNotifictionData = new NotificationData(); |
|
||||
|
var userWelcomeNotifictionData = new NotificationData(); |
||||
//userWelcomeNotifictionData.WriteStandardData(
|
|
||||
// L("WelcomeToApplicationFormUser", eventData.Entity.Name ?? eventData.Entity.UserName),
|
//userWelcomeNotifictionData.WriteStandardData(
|
||||
// L("WelcomeToApplicationFormUser", eventData.Entity.Name ?? eventData.Entity.UserName),
|
// L("WelcomeToApplicationFormUser", eventData.Entity.Name ?? eventData.Entity.UserName),
|
||||
// DateTime.Now, eventData.Entity.UserName);
|
// L("WelcomeToApplicationFormUser", eventData.Entity.Name ?? eventData.Entity.UserName),
|
||||
|
// DateTime.Now, eventData.Entity.UserName);
|
||||
userWelcomeNotifictionData |
|
||||
.WriteLocalizedData( |
userWelcomeNotifictionData |
||||
new LocalizableStringInfo( |
.WriteLocalizedData( |
||||
LocalizationResourceNameAttribute.GetName(typeof(MessageServiceResource)), |
new LocalizableStringInfo( |
||||
"WelcomeToApplicationFormUser"), |
LocalizationResourceNameAttribute.GetName(typeof(MessageServiceResource)), |
||||
new LocalizableStringInfo( |
"WelcomeToApplicationFormUser", |
||||
LocalizationResourceNameAttribute.GetName(typeof(MessageServiceResource)), |
new Dictionary<object, object> |
||||
"WelcomeToApplicationFormUser"), |
{ |
||||
DateTime.Now, eventData.Entity.UserName); |
{ "User", eventData.Entity.UserName } |
||||
|
}), |
||||
await _notificationSender |
new LocalizableStringInfo( |
||||
.SendNofiterAsync( |
LocalizationResourceNameAttribute.GetName(typeof(MessageServiceResource)), |
||||
UserNotificationNames.WelcomeToApplication, |
"WelcomeToApplicationFormUser", |
||||
userWelcomeNotifictionData, |
new Dictionary<object, object> |
||||
userIdentifer, |
{ |
||||
eventData.Entity.TenantId, |
{ "User", eventData.Entity.UserName } |
||||
NotificationSeverity.Info |
}), |
||||
); |
DateTime.Now, eventData.Entity.UserName); |
||||
} |
|
||||
} |
await _notificationSender |
||||
} |
.SendNofiterAsync( |
||||
|
UserNotificationNames.WelcomeToApplication, |
||||
|
userWelcomeNotifictionData, |
||||
|
userIdentifer, |
||||
|
eventData.Entity.TenantId, |
||||
|
NotificationSeverity.Info |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|||||
Loading…
Reference in new issue