diff --git a/aspnet-core/LINGYUN.MicroService.Common.sln b/aspnet-core/LINGYUN.MicroService.Common.sln index e43cceb25..1992b26c3 100644 --- a/aspnet-core/LINGYUN.MicroService.Common.sln +++ b/aspnet-core/LINGYUN.MicroService.Common.sln @@ -272,6 +272,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.C EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Http.Client.Wrapper", "modules\common\LINGYUN.Abp.Http.Client.Wrapper\LINGYUN.Abp.Http.Client.Wrapper.csproj", "{2C5C57FB-70F5-4C20-92FC-39ACD260CEE3}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tui-juhe", "tui-juhe", "{A1C75C3E-67D1-4BCE-89BF-44A735909BD5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TuiJuhe", "modules\tui-juhe\LINGYUN.Abp.TuiJuhe\LINGYUN.Abp.TuiJuhe.csproj", "{60143C9C-E539-498A-9DBE-B95E6A8301A5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.TuiJuhe", "modules\tui-juhe\LINGYUN.Abp.Notifications.TuiJuhe\LINGYUN.Abp.Notifications.TuiJuhe.csproj", "{C55D9BA0-4AFD-4D18-958B-B53FD3F2FF4F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Notifications.TuiJuhe.Tests", "tests\LINGYUN.Abp.Notifications.TuiJuhe.Tests\LINGYUN.Abp.Notifications.TuiJuhe.Tests.csproj", "{641DF0BA-0E79-441D-B328-FDA288A35CDE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TuiJuhe.Tests", "tests\LINGYUN.Abp.TuiJuhe.Tests\LINGYUN.Abp.TuiJuhe.Tests.csproj", "{2020EA8D-F276-498D-92D1-94D1E25F8E1A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TuiJuhe.SettingManagement", "modules\tui-juhe\LINGYUN.Abp.TuiJuhe.SettingManagement\LINGYUN.Abp.TuiJuhe.SettingManagement.csproj", "{2A3DF8B2-4760-41C4-9337-44FEE29B17CD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -702,6 +714,26 @@ Global {2C5C57FB-70F5-4C20-92FC-39ACD260CEE3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2C5C57FB-70F5-4C20-92FC-39ACD260CEE3}.Release|Any CPU.ActiveCfg = Release|Any CPU {2C5C57FB-70F5-4C20-92FC-39ACD260CEE3}.Release|Any CPU.Build.0 = Release|Any CPU + {60143C9C-E539-498A-9DBE-B95E6A8301A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60143C9C-E539-498A-9DBE-B95E6A8301A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60143C9C-E539-498A-9DBE-B95E6A8301A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60143C9C-E539-498A-9DBE-B95E6A8301A5}.Release|Any CPU.Build.0 = Release|Any CPU + {C55D9BA0-4AFD-4D18-958B-B53FD3F2FF4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C55D9BA0-4AFD-4D18-958B-B53FD3F2FF4F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C55D9BA0-4AFD-4D18-958B-B53FD3F2FF4F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C55D9BA0-4AFD-4D18-958B-B53FD3F2FF4F}.Release|Any CPU.Build.0 = Release|Any CPU + {641DF0BA-0E79-441D-B328-FDA288A35CDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {641DF0BA-0E79-441D-B328-FDA288A35CDE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {641DF0BA-0E79-441D-B328-FDA288A35CDE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {641DF0BA-0E79-441D-B328-FDA288A35CDE}.Release|Any CPU.Build.0 = Release|Any CPU + {2020EA8D-F276-498D-92D1-94D1E25F8E1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2020EA8D-F276-498D-92D1-94D1E25F8E1A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2020EA8D-F276-498D-92D1-94D1E25F8E1A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2020EA8D-F276-498D-92D1-94D1E25F8E1A}.Release|Any CPU.Build.0 = Release|Any CPU + {2A3DF8B2-4760-41C4-9337-44FEE29B17CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A3DF8B2-4760-41C4-9337-44FEE29B17CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A3DF8B2-4760-41C4-9337-44FEE29B17CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A3DF8B2-4760-41C4-9337-44FEE29B17CD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -837,6 +869,12 @@ Global {B78E53AC-6BB8-402D-90CF-BEF1BD9558EB} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} {AA039B4E-CE12-43AC-8340-3D52463E971E} = {B91F26C5-B148-4094-B5F1-71E5F945DBED} {2C5C57FB-70F5-4C20-92FC-39ACD260CEE3} = {086BE5BE-8594-4DA7-8819-935FEF76DABD} + {A1C75C3E-67D1-4BCE-89BF-44A735909BD5} = {02EA4E78-5891-43BC-944F-3E52FEE032E4} + {60143C9C-E539-498A-9DBE-B95E6A8301A5} = {A1C75C3E-67D1-4BCE-89BF-44A735909BD5} + {C55D9BA0-4AFD-4D18-958B-B53FD3F2FF4F} = {A1C75C3E-67D1-4BCE-89BF-44A735909BD5} + {641DF0BA-0E79-441D-B328-FDA288A35CDE} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} + {2020EA8D-F276-498D-92D1-94D1E25F8E1A} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} + {2A3DF8B2-4760-41C4-9337-44FEE29B17CD} = {A1C75C3E-67D1-4BCE-89BF-44A735909BD5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/FodyWeavers.xml b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/FodyWeavers.xsd b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/FodyWeavers.xsd new file mode 100644 index 000000000..11da52550 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN.Abp.Notifications.TuiJuhe.csproj b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN.Abp.Notifications.TuiJuhe.csproj new file mode 100644 index 000000000..ba203b119 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN.Abp.Notifications.TuiJuhe.csproj @@ -0,0 +1,16 @@ + + + + + + + netstandard2.0 + + + + + + + + + diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN/Abp/Notifications/NotificationDefinitionExtensions.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN/Abp/Notifications/NotificationDefinitionExtensions.cs new file mode 100644 index 000000000..d65df5d71 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN/Abp/Notifications/NotificationDefinitionExtensions.cs @@ -0,0 +1,57 @@ +using LINGYUN.Abp.TuiJuhe.Messages; + +namespace LINGYUN.Abp.Notifications; + +public static class NotificationDefinitionExtensions +{ + private const string Prefix = "tui-juhe:"; + private const string ServiceIdKey = Prefix + "serviceId"; + + /// + /// 获取消息内容类型 + /// + /// + /// + /// + public static MessageContentType GetContentTypeOrDefault( + this NotificationDefinition notification, + MessageContentType defaultContentType = MessageContentType.Text) + { + return notification.ContentType switch + { + NotificationContentType.Text => MessageContentType.Text, + NotificationContentType.Html => MessageContentType.Html, + NotificationContentType.Markdown => MessageContentType.Markdown, + NotificationContentType.Json => MessageContentType.Text, + _ => defaultContentType, + }; + } + /// + /// 指定服务编号 + /// + /// 群组编码 + /// 服务编号,在服务创建后自动生成ServiceID,是服务的唯一标识,可在每个服务的详情页中查看 + /// + /// + /// + public static NotificationDefinition WithServiceId( + this NotificationDefinition notification, + string serviceId) + { + return notification.WithProperty(ServiceIdKey, serviceId); + } + /// + /// 获取服务编号 + /// + /// + public static string GetServiceIdOrNull( + this NotificationDefinition notification) + { + if (notification.Properties.TryGetValue(ServiceIdKey, out var serviceIdDefine)) + { + return serviceIdDefine.ToString(); + } + + return null; + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN/Abp/Notifications/TuiJuhe/AbpNotificationsTuiJuheModule.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN/Abp/Notifications/TuiJuhe/AbpNotificationsTuiJuheModule.cs new file mode 100644 index 000000000..95ed92c76 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN/Abp/Notifications/TuiJuhe/AbpNotificationsTuiJuheModule.cs @@ -0,0 +1,18 @@ +using LINGYUN.Abp.TuiJuhe; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Notifications.TuiJuhe; + +[DependsOn( + typeof(AbpNotificationsModule), + typeof(AbpTuiJuheModule))] +public class AbpNotificationsTuiJuheModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.PublishProviders.Add(); + }); + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN/Abp/Notifications/TuiJuhe/TuiJuheNotificationPublishProvider.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN/Abp/Notifications/TuiJuhe/TuiJuheNotificationPublishProvider.cs new file mode 100644 index 000000000..d96df5047 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/LINGYUN/Abp/Notifications/TuiJuhe/TuiJuheNotificationPublishProvider.cs @@ -0,0 +1,115 @@ +using LINGYUN.Abp.RealTime.Localization; +using LINGYUN.Abp.TuiJuhe.Features; +using LINGYUN.Abp.TuiJuhe.Messages; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Features; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.Notifications.TuiJuhe; + +public class TuiJuheNotificationPublishProvider : NotificationPublishProvider +{ + public const string ProviderName = "TuiJuhe"; + + public override string Name => ProviderName; + + protected IFeatureChecker FeatureChecker { get; } + + protected ITuiJuheMessageSender TuiJuheMessageSender { get; } + + protected IStringLocalizerFactory LocalizerFactory { get; } + + protected AbpLocalizationOptions LocalizationOptions { get; } + + protected INotificationDefinitionManager NotificationDefinitionManager { get; } + + public TuiJuheNotificationPublishProvider( + IFeatureChecker featureChecker, + ITuiJuheMessageSender tuiJuheMessageSender, + IStringLocalizerFactory localizerFactory, + IOptions localizationOptions, + INotificationDefinitionManager notificationDefinitionManager) + { + FeatureChecker = featureChecker; + TuiJuheMessageSender = tuiJuheMessageSender; + LocalizerFactory = localizerFactory; + LocalizationOptions = localizationOptions.Value; + NotificationDefinitionManager = notificationDefinitionManager; + } + + protected async override Task CanPublishAsync(NotificationInfo notification, CancellationToken cancellationToken = default) + { + if (!await FeatureChecker.IsEnabledAsync(TuiJuheFeatureNames.Message.Enable)) + { + Logger.LogWarning( + "{0} cannot push messages because the feature {1} is not enabled", + Name, + TuiJuheFeatureNames.Message.Enable); + return false; + } + return true; + } + + protected async override Task PublishAsync( + NotificationInfo notification, + IEnumerable identifiers, + CancellationToken cancellationToken = default) + { + var notificationDefine = await NotificationDefinitionManager.GetOrNullAsync(notification.Name); + var contentType = notificationDefine?.GetContentTypeOrDefault(MessageContentType.Text) + ?? MessageContentType.Text; + var serviceId = notificationDefine?.GetServiceIdOrNull(); + + if (serviceId.IsNullOrWhiteSpace()) + { + Logger.LogWarning( + "{0} cannot push messages because the notification {1} service id is not specified", + Name, + notification.Name); + return; + } + + if (!notification.Data.NeedLocalizer()) + { + var title = notification.Data.TryGetData("title").ToString(); + var message = notification.Data.TryGetData("message").ToString(); + + await TuiJuheMessageSender.SendAsync( + title: title, + content: message, + serviceId: serviceId, + contentType: contentType, + cancellationToken: cancellationToken); + } + else + { + var titleInfo = notification.Data.TryGetData("title").As(); + var titleResource = GetResource(titleInfo.ResourceName); + var title = LocalizerFactory.Create(titleResource.ResourceType)[titleInfo.Name, titleInfo.Values].Value; + + var messageInfo = notification.Data.TryGetData("message").As(); + var messageResource = GetResource(messageInfo.ResourceName); + var message = LocalizerFactory.Create(messageResource.ResourceType)[messageInfo.Name, messageInfo.Values].Value; + + await TuiJuheMessageSender.SendAsync( + title: title, + content: message, + serviceId: serviceId, + contentType: contentType, + cancellationToken: cancellationToken); + } + } + + private LocalizationResource GetResource(string resourceName) + { + return LocalizationOptions.Resources.Values + .First(x => x.ResourceName.Equals(resourceName)); + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/README.md b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/README.md new file mode 100644 index 000000000..93b5c8c8c --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.Notifications.TuiJuhe/README.md @@ -0,0 +1,15 @@ +# LINGYUN.Abp.Notifications.TuiJuhe + +通知模块的TuiJuhe实现 + +使应用可通过TuiJuhe发布实时通知 + +## 模块引用 + +```csharp +[DependsOn(typeof(AbpNotificationsTuiJuheModule))] +public class YouProjectModule : AbpModule +{ + // other +} +``` diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/FodyWeavers.xml b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/FodyWeavers.xsd b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/FodyWeavers.xsd new file mode 100644 index 000000000..11da52550 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN.Abp.TuiJuhe.SettingManagement.csproj b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN.Abp.TuiJuhe.SettingManagement.csproj new file mode 100644 index 000000000..d15f3f3f2 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN.Abp.TuiJuhe.SettingManagement.csproj @@ -0,0 +1,30 @@ + + + + + + + net6.0 + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/AbpTuiJuheSettingManagementModule.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/AbpTuiJuheSettingManagementModule.cs new file mode 100644 index 000000000..fcaa2eef4 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/AbpTuiJuheSettingManagementModule.cs @@ -0,0 +1,48 @@ +using LINGYUN.Abp.TuiJuhe.Localization; +using Localization.Resources.AbpUi; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.TuiJuhe.SettingManagement +{ + [DependsOn( + typeof(AbpTuiJuheModule), + typeof(AbpAspNetCoreMvcModule))] + public class AbpWxPusherSettingManagementModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + PreConfigure(mvcBuilder => + { + mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpWxPusherSettingManagementModule).Assembly); + }); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Get() + .AddVirtualJson("/LINGYUN/Abp/TuiJuhe/SettingManagement/Localization/Resources"); + }); + + Configure(options => + { + options.Resources + .Get() + .AddBaseTypes( + typeof(AbpUiResource) + ); + }); + } + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/ITuiJuheSettingAppService.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/ITuiJuheSettingAppService.cs new file mode 100644 index 000000000..bdc6e7659 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/ITuiJuheSettingAppService.cs @@ -0,0 +1,8 @@ +using LINGYUN.Abp.SettingManagement; + +namespace LINGYUN.Abp.TuiJuhe.SettingManagement +{ + public interface ITuiJuheSettingAppService : IReadonlySettingAppService + { + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/Localization/Resources/en.json b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/Localization/Resources/en.json new file mode 100644 index 000000000..4a7d52470 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/Localization/Resources/en.json @@ -0,0 +1,7 @@ +{ + "culture": "en", + "texts": { + "Permission:TuiJuhe": "TuiJuhe", + "Permission:ManageSetting": "Manage Setting" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/Localization/Resources/zh-Hans.json b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..505023415 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/Localization/Resources/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "culture": "zh-Hans", + "texts": { + "Permission:TuiJuhe": "聚合云推", + "Permission:ManageSetting": "管理设置" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingAppService.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingAppService.cs new file mode 100644 index 000000000..8e0061804 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingAppService.cs @@ -0,0 +1,61 @@ +using LINGYUN.Abp.SettingManagement; +using LINGYUN.Abp.TuiJuhe.Localization; +using LINGYUN.Abp.TuiJuhe.Settings; +using System.Threading.Tasks; +using Volo.Abp.Application.Services; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.MultiTenancy; +using Volo.Abp.SettingManagement; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.TuiJuhe.SettingManagement +{ + public class TuiJuheSettingAppService : ApplicationService, ITuiJuheSettingAppService + { + protected ISettingManager SettingManager { get; } + protected IPermissionChecker PermissionChecker { get; } + protected ISettingDefinitionManager SettingDefinitionManager { get; } + + public TuiJuheSettingAppService( + ISettingManager settingManager, + IPermissionChecker permissionChecker, + ISettingDefinitionManager settingDefinitionManager) + { + SettingManager = settingManager; + PermissionChecker = permissionChecker; + SettingDefinitionManager = settingDefinitionManager; + LocalizationResource = typeof(TuiJuheResource); + } + + public async virtual Task GetAllForCurrentTenantAsync() + { + return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString()); + } + + public async virtual Task GetAllForGlobalAsync() + { + return await GetAllForProviderAsync(GlobalSettingValueProvider.ProviderName, null); + } + + protected async virtual Task GetAllForProviderAsync(string providerName, string providerKey) + { + var settingGroups = new SettingGroupResult(); + var wxPusherSettingGroup = new SettingGroupDto(L["DisplayName:TuiJuhe"], L["Description:TuiJuhe"]); + + if (await PermissionChecker.IsGrantedAsync(TuiJuheSettingPermissionNames.ManageSetting)) + { + var securitySetting = wxPusherSettingGroup.AddSetting(L["Security"], L["Security"]); + securitySetting.AddDetail( + SettingDefinitionManager.Get(TuiJuheSettingNames.Security.Token), + StringLocalizerFactory, + await SettingManager.GetOrNullAsync(TuiJuheSettingNames.Security.Token, providerName, providerKey), + ValueType.String, + providerName); + } + + settingGroups.AddGroup(wxPusherSettingGroup); + + return settingGroups; + } + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingController.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingController.cs new file mode 100644 index 000000000..4521554d3 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingController.cs @@ -0,0 +1,36 @@ +using LINGYUN.Abp.SettingManagement; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.AspNetCore.Mvc; + +namespace LINGYUN.Abp.TuiJuhe.SettingManagement +{ + [RemoteService(Name = AbpSettingManagementRemoteServiceConsts.RemoteServiceName)] + [Area(AbpSettingManagementRemoteServiceConsts.ModuleName)] + [Route($"api/{AbpSettingManagementRemoteServiceConsts.ModuleName}/tui-juhe")] + public class TuiJuheSettingController : AbpController, ITuiJuheSettingAppService + { + protected ITuiJuheSettingAppService Service { get; } + + public TuiJuheSettingController( + ITuiJuheSettingAppService service) + { + Service = service; + } + + [HttpGet] + [Route("by-current-tenant")] + public async virtual Task GetAllForCurrentTenantAsync() + { + return await Service.GetAllForCurrentTenantAsync(); + } + + [HttpGet] + [Route("by-global")] + public async virtual Task GetAllForGlobalAsync() + { + return await Service.GetAllForGlobalAsync(); + } + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingPermissionDefinitionProvider.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingPermissionDefinitionProvider.cs new file mode 100644 index 000000000..68e7977e3 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingPermissionDefinitionProvider.cs @@ -0,0 +1,24 @@ +using LINGYUN.Abp.TuiJuhe.Localization; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.TuiJuhe.SettingManagement +{ + public class WxPusherSettingPermissionDefinitionProvider : PermissionDefinitionProvider + { + public override void Define(IPermissionDefinitionContext context) + { + var tuiJuheGroup = context.AddGroup( + TuiJuheSettingPermissionNames.GroupName, + L("Permission:TuiJuhe")); + + tuiJuheGroup.AddPermission( + TuiJuheSettingPermissionNames.ManageSetting, L("Permission:ManageSetting")); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingPermissionNames.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingPermissionNames.cs new file mode 100644 index 000000000..ad5fd02c3 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe.SettingManagement/LINGYUN/Abp/TuiJuhe/SettingManagement/TuiJuheSettingPermissionNames.cs @@ -0,0 +1,9 @@ +namespace LINGYUN.Abp.TuiJuhe.SettingManagement +{ + public class TuiJuheSettingPermissionNames + { + public const string GroupName = "Abp.TuiJuhe"; + + public const string ManageSetting = GroupName + ".ManageSetting"; + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/FodyWeavers.xml b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/FodyWeavers.xsd b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/FodyWeavers.xsd new file mode 100644 index 000000000..11da52550 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN.Abp.TuiJuhe.csproj b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN.Abp.TuiJuhe.csproj new file mode 100644 index 000000000..9e0759210 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN.Abp.TuiJuhe.csproj @@ -0,0 +1,29 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/AbpTuiJuheModule.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/AbpTuiJuheModule.cs new file mode 100644 index 000000000..491f117ad --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/AbpTuiJuheModule.cs @@ -0,0 +1,42 @@ +using LINGYUN.Abp.Features.LimitValidation; +using LINGYUN.Abp.TuiJuhe.Localization; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Caching; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.Settings; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.TuiJuhe; + +[DependsOn( + typeof(AbpJsonModule), + typeof(AbpSettingsModule), + typeof(AbpCachingModule), + typeof(AbpFeaturesLimitValidationModule))] +public class AbpTuiJuheModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddTuiJuheClient(); + + Configure(options => + { + + }); + + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Add() + .AddVirtualJson("/LINGYUN/Abp/TuiJuhe/Localization/Resources"); + }); + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Features/TuiJuheFeatureDefinitionProvider.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Features/TuiJuheFeatureDefinitionProvider.cs new file mode 100644 index 000000000..4a2ae74a6 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Features/TuiJuheFeatureDefinitionProvider.cs @@ -0,0 +1,51 @@ +using LINGYUN.Abp.TuiJuhe.Localization; +using Volo.Abp.Features; +using Volo.Abp.Localization; +using Volo.Abp.Validation.StringValues; + +namespace LINGYUN.Abp.TuiJuhe.Features; + +public class TuiJuheFeatureDefinitionProvider : FeatureDefinitionProvider +{ + public override void Define(IFeatureDefinitionContext context) + { + var group = context.AddGroup( + name: TuiJuheFeatureNames.GroupName, + displayName: L("Features:TuiJuhe")); + group.AddFeature( + name: TuiJuheFeatureNames.Enable, + defaultValue: "false", + displayName: L("Features:TuiJuheEnable"), + description: L("Features:TuiJuheEnableDesc"), + valueType: new ToggleStringValueType(new BooleanValueValidator())); + + var message = group.AddFeature( + name: TuiJuheFeatureNames.Message.GroupName, + displayName: L("Features:Message"), + description: L("Features:Message")); + + message.CreateChild( + name: TuiJuheFeatureNames.Message.Enable, + defaultValue: "false", + displayName: L("Features:MessageEnable"), + description: L("Features:MessageEnableDesc"), + valueType: new ToggleStringValueType(new BooleanValueValidator())); + message.CreateChild( + name: TuiJuheFeatureNames.Message.SendLimit, + defaultValue: "50", + displayName: L("Features:Message.SendLimit"), + description: L("Features:Message.SendLimitDesc"), + valueType: new FreeTextStringValueType(new NumericValueValidator(1, 50))); + message.CreateChild( + name: TuiJuheFeatureNames.Message.SendLimitInterval, + defaultValue: "1", + displayName: L("Features:Message.SendLimitInterval"), + description: L("Features:Message.SendLimitIntervalDesc"), + valueType: new FreeTextStringValueType(new NumericValueValidator(1, 1))); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Features/TuiJuheFeatureNames.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Features/TuiJuheFeatureNames.cs new file mode 100644 index 000000000..e8059cec3 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Features/TuiJuheFeatureNames.cs @@ -0,0 +1,28 @@ +namespace LINGYUN.Abp.TuiJuhe.Features; + +public static class TuiJuheFeatureNames +{ + public const string GroupName = "TuiJuhe"; + + /// + /// 启用TuiJuhe + /// + public const string Enable = GroupName + ".Enable"; + + public static class Message + { + public const string GroupName = TuiJuheFeatureNames.GroupName + ".Message"; + /// + /// 启用消息推送 + /// + public const string Enable = GroupName + ".Enable"; + /// + /// 发送次数上限 + /// + public const string SendLimit = GroupName + ".SendLimit"; + /// + /// 发送次数上限时长 + /// + public const string SendLimitInterval = GroupName + ".SendLimitInterval"; + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Localization/Resources/en.json b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Localization/Resources/en.json new file mode 100644 index 000000000..a853ce480 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Localization/Resources/en.json @@ -0,0 +1,20 @@ +{ + "culture": "en", + "texts": { + "DisplayName:TuiJuhe": "TuiJuhe", + "Description:TuiJuhe": "TuiJuhe", + "Settings:Security.Token": "Token", + "Settings:Security.TokenDesc": "The user token, (https://tui.juhe.cn/setup) in the center of the personal page views.", + "Features:TuiJuhe": "TuiJuhe push service", + "Features:TuiJuheEnable": "Enable TuiJuhe", + "Features:TuiJuheEnableDesc": "Enable to enable the application to have TuiJuhe capabilities.", + "Features:Message": "TuiJuhe message push", + "Features:MessageEnable": "Enable TuiJuhe Message Push", + "Features:MessageEnableDesc": "Enable so that apps will have the ability to be pushed notification via TuiJuhe.", + "Features:Message.SendLimit": "Amount of TuiJuhe push", + "Features:Message.SendLimitDesc": "Set to limit the amount of TuiJuhe message push.", + "Features:Message.SendLimitInterval": "TuiJuhe message limit interval", + "Features:Message.SendLimitIntervalDesc": "Set the TuiJuhe message limit period (time scale: hours). Message sending frequency (request limit) : The rate does not exceed 50 times per unit hour.", + "Security": "Security" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Localization/Resources/zh-Hans.json b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..3964376cc --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Localization/Resources/zh-Hans.json @@ -0,0 +1,20 @@ +{ + "culture": "zh-Hans", + "texts": { + "DisplayName:TuiJuhe": "聚合云推", + "Description:TuiJuhe": "聚合云推(TuiJuhe)", + "Settings:Security.Token": "用户令牌", + "Settings:Security.TokenDesc": "用户令牌,在个人中心(https://tui.juhe.cn/setup)页面查看获取.", + "Features:TuiJuhe": "聚合云推服务", + "Features:TuiJuheEnable": "启用聚合云推", + "Features:TuiJuheEnableDesc": "启用以使应用拥有聚合云推的能力.", + "Features:Message": "聚合云推消息推送", + "Features:MessageEnable": "启用聚合云推消息推送", + "Features:MessageEnableDesc": "启用以使应用将拥有通过聚合云推推送到实时消息的能力.", + "Features:Message.SendLimit": "聚合云推推送量", + "Features:Message.SendLimitDesc": "设置以限制聚合云推推送量.", + "Features:Message.SendLimitInterval": "聚合云推消息限制周期", + "Features:Message.SendLimitIntervalDesc": "设置聚合云推消息限制周期(时间刻度: 时).消息发送频率(请求限制): 单位小时内不超过50次率.", + "Security": "安全选项" + } +} \ No newline at end of file diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Localization/TuiJuheResource.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Localization/TuiJuheResource.cs new file mode 100644 index 000000000..c0b126ce1 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Localization/TuiJuheResource.cs @@ -0,0 +1,8 @@ +using Volo.Abp.Localization; + +namespace LINGYUN.Abp.TuiJuhe.Localization; + +[LocalizationResourceName("TuiJuhe")] +public class TuiJuheResource +{ +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/ITuiJuheMessageSender.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/ITuiJuheMessageSender.cs new file mode 100644 index 000000000..c202993c4 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/ITuiJuheMessageSender.cs @@ -0,0 +1,15 @@ +using JetBrains.Annotations; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.TuiJuhe.Messages; + +public interface ITuiJuheMessageSender +{ + Task> SendAsync( + [NotNull] string title, + [NotNull] string content, + [NotNull] string serviceId, + MessageContentType contentType = MessageContentType.Text, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/MessageContentType.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/MessageContentType.cs new file mode 100644 index 000000000..bffc32d7e --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/MessageContentType.cs @@ -0,0 +1,9 @@ +namespace LINGYUN.Abp.TuiJuhe.Messages; + +public enum MessageContentType +{ + Text = 0, + Html = 1, + Markdown = 2, + Json = 3 +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/MessageHttpClientExtensions.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/MessageHttpClientExtensions.cs new file mode 100644 index 000000000..d443b2031 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/MessageHttpClientExtensions.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.TuiJuhe.Messages; + +internal static class MessageHttpClientExtensions +{ + public async static Task SendMessageAsync( + this HttpClient httpClient, + string token, + string title, + string content, + string serviceId, + string docType = "txt", + CancellationToken cancellationToken = default) + { + var requestMessage = new HttpRequestMessage( + HttpMethod.Post, + "/api/plus/pushApi"); + + var requestData = new Dictionary + { + { "token", token }, + { "title", title }, + { "content", content }, + { "service_id", serviceId }, + { "doc_type", docType ?? "txt" }, + }; + var formData = new FormUrlEncodedContent(requestData); + requestMessage.Content = formData; + + var httpResponse = await httpClient.SendAsync(requestMessage, cancellationToken); + + return await httpResponse.Content.ReadAsStringAsync(); + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/TuiJuheMessageSender.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/TuiJuheMessageSender.cs new file mode 100644 index 000000000..322a830c1 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Messages/TuiJuheMessageSender.cs @@ -0,0 +1,76 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.Features.LimitValidation; +using LINGYUN.Abp.TuiJuhe.Features; +using LINGYUN.Abp.TuiJuhe.Token; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; +using Volo.Abp.Json; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.TuiJuhe.Messages; + +[RequiresFeature(TuiJuheFeatureNames.Enable)] +public class TuiJuheMessageSender : ITuiJuheMessageSender, ITransientDependency +{ + protected IJsonSerializer JsonSerializer { get; } + protected ISettingProvider SettingProvider { get; } + protected IHttpClientFactory HttpClientFactory { get; } + protected ITuiJuheTokenProvider TokenProvider { get; } + + public TuiJuheMessageSender( + IJsonSerializer jsonSerializer, + ISettingProvider settingProvider, + IHttpClientFactory httpClientFactory, + ITuiJuheTokenProvider tokenProvider) + { + JsonSerializer = jsonSerializer; + SettingProvider = settingProvider; + HttpClientFactory = httpClientFactory; + TokenProvider = tokenProvider; + } + + // 消息发送频率(请求限制):单位小时内不超过50次 + [RequiresFeature(TuiJuheFeatureNames.Message.Enable)] + [RequiresLimitFeature( + TuiJuheFeatureNames.Message.SendLimit, + TuiJuheFeatureNames.Message.SendLimitInterval, + LimitPolicy.Hours)] + public async virtual Task> SendAsync( + [NotNull] string title, + [NotNull] string content, + [NotNull] string serviceId, + MessageContentType contentType = MessageContentType.Text, + CancellationToken cancellationToken = default) + { + var token = await TokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.GetTuiJuheClient(); + + var resultContent = await client.SendMessageAsync( + token, + title, + content, + serviceId, + GetDocType(contentType), + cancellationToken); + + var response = JsonSerializer + .Deserialize>(resultContent); + + return response; + } + + private static string GetDocType(MessageContentType contentType) + { + return contentType switch + { + MessageContentType.Html => "html", + MessageContentType.Text => "txt", + MessageContentType.Json => "json", + MessageContentType.Markdown => "markdown", + _ => "html", + }; + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Settings/TuiJuheSettingDefinitionProvider.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Settings/TuiJuheSettingDefinitionProvider.cs new file mode 100644 index 000000000..a35623511 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Settings/TuiJuheSettingDefinitionProvider.cs @@ -0,0 +1,30 @@ +using LINGYUN.Abp.TuiJuhe.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.TuiJuhe.Settings; + +public class TuiJuheSettingDefinitionProvider : SettingDefinitionProvider +{ + public override void Define(ISettingDefinitionContext context) + { + context.Add(new[] + { + new SettingDefinition( + name: TuiJuheSettingNames.Security.Token, + displayName: L("Settings:Security.Token"), + description: L("Settings:Security.TokenDesc"), + isEncrypted: true) + .WithProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName), + }); + } + + public static ILocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Settings/TuiJuheSettingNames.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Settings/TuiJuheSettingNames.cs new file mode 100644 index 000000000..9c080c05f --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Settings/TuiJuheSettingNames.cs @@ -0,0 +1,13 @@ +namespace LINGYUN.Abp.TuiJuhe.Settings; + +public static class TuiJuheSettingNames +{ + public const string Prefix = "TuiJuhe"; + + public static class Security + { + public const string Prefix = TuiJuheSettingNames.Prefix + ".Security"; + + public const string Token = Prefix + ".Token"; + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Token/ITuiJuheTokenProvider.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Token/ITuiJuheTokenProvider.cs new file mode 100644 index 000000000..4aa82aceb --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Token/ITuiJuheTokenProvider.cs @@ -0,0 +1,9 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.TuiJuhe.Token; + +public interface ITuiJuheTokenProvider +{ + Task GetTokenAsync(CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Token/TuiJuheTokenProvider.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Token/TuiJuheTokenProvider.cs new file mode 100644 index 000000000..289b8ff43 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/Token/TuiJuheTokenProvider.cs @@ -0,0 +1,23 @@ +using LINGYUN.Abp.TuiJuhe.Settings; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Settings; + +namespace LINGYUN.Abp.TuiJuhe.Token; + +public class TuiJuheTokenProvider : ITuiJuheTokenProvider, ITransientDependency +{ + protected ISettingProvider SettingProvider { get; } + + public TuiJuheTokenProvider(ISettingProvider settingProvider) + { + SettingProvider = settingProvider; + } + + public async virtual Task GetTokenAsync(CancellationToken cancellationToken = default) + { + return await SettingProvider.GetOrNullAsync( + TuiJuheSettingNames.Security.Token); + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/TuiJuheRemoteCallException.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/TuiJuheRemoteCallException.cs new file mode 100644 index 000000000..4167416c4 --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/TuiJuheRemoteCallException.cs @@ -0,0 +1,15 @@ +using Volo.Abp; +using Volo.Abp.ExceptionHandling; + +namespace LINGYUN.Abp.TuiJuhe; + +public class TuiJuheRemoteCallException : AbpException, IHasErrorCode +{ + public string Code { get; } + + public TuiJuheRemoteCallException(string code, string message) + : base($"The TuiJuhe api returns an error: {code} - {message}") + { + Code = code; + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/TuiJuheResult.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/TuiJuheResult.cs new file mode 100644 index 000000000..7bdd8cacb --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/LINGYUN/Abp/TuiJuhe/TuiJuheResult.cs @@ -0,0 +1,64 @@ +using Newtonsoft.Json; +using System; + +namespace LINGYUN.Abp.TuiJuhe; + +[Serializable] +public class TuiJuheResult +{ + /// + /// 状态码 + /// + [JsonProperty("code")] + public int Code { get; set; } + /// + /// 错误消息 + /// + [JsonProperty("reason")] + public string Reason { get; set; } + /// + /// 响应数据 + /// + [JsonProperty("result")] + public TResult Result { get; set; } + /// + /// 响应参数 + /// + [JsonProperty("params")] + public TParam Params { get; set; } + + [JsonIgnore] + public bool Success => 200 == Code; + + public TuiJuheResult() + { + } + + public TuiJuheResult(int code, string reason) + { + Code = code; + Reason = reason; + } + + public TuiJuheResult(int code, string reason, TResult result) + { + Code = code; + Reason = reason; + Result = result; + } + + public TResult GetData() + { + ThrowOfFailed(); + + return Result; + } + + public void ThrowOfFailed() + { + if (!Success) + { + throw new TuiJuheRemoteCallException(Code.ToString(), Reason); + } + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/Microsoft/Extensions/DependencyInjection/IServiceCollectionExtensions.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/Microsoft/Extensions/DependencyInjection/IServiceCollectionExtensions.cs new file mode 100644 index 000000000..c6d1a183f --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/Microsoft/Extensions/DependencyInjection/IServiceCollectionExtensions.cs @@ -0,0 +1,19 @@ +using System; + +namespace Microsoft.Extensions.DependencyInjection; + +internal static class IServiceCollectionExtensions +{ + public static IServiceCollection AddTuiJuheClient( + this IServiceCollection services) + { + services.AddHttpClient( + "_Abp_TuiJuhe_Client", + (httpClient) => + { + httpClient.BaseAddress = new Uri("https://tui.juhe.cn"); + }); + + return services; + } +} diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/README.md b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/README.md new file mode 100644 index 000000000..f5ca4369f --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/README.md @@ -0,0 +1,31 @@ +# LINGYUN.Abp.TuiJuhe + +集成TuiJuhe(仅适用于特定消息与人员通知, 不支持群发) + +实现TuiJuhe相关Api文档,拥有TuiJuhe开放能力 + +详情见TuiJuhe文档: https://tui.juhe.cn/docs + +## 模块引用 + +```csharp +[DependsOn(typeof(AbpTuiJuheModule))] +public class YouProjectModule : AbpModule +{ + // other +} +``` + +## Features + +* TuiJuhe TuiJuhe特性分组 +* TuiJuhe.Enable 全局启用TuiJuhe +* TuiJuhe.Message.Enable 全局启用TuiJuhe消息通道 +* TuiJuhe.Message TuiJuhe消息推送 +* TuiJuhe.Message.Enable 启用TuiJuhe消息推送 +* TuiJuhe.Message.SendLimit TuiJuhe消息推送限制次数 +* TuiJuhe.Message.SendLimitInterval TuiJuhe消息推送限制周期(时) + +## Settings + +* TuiJuhe.Security.Token 用户令牌. diff --git a/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/System/Net/Http/IHttpClientFactoryExtensions.cs b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/System/Net/Http/IHttpClientFactoryExtensions.cs new file mode 100644 index 000000000..e082eb04c --- /dev/null +++ b/aspnet-core/modules/tui-juhe/LINGYUN.Abp.TuiJuhe/System/Net/Http/IHttpClientFactoryExtensions.cs @@ -0,0 +1,10 @@ +namespace System.Net.Http; + +internal static class IHttpClientFactoryExtensions +{ + public static HttpClient GetTuiJuheClient( + this IHttpClientFactory httpClientFactory) + { + return httpClientFactory.CreateClient("_Abp_TuiJuhe_Client"); + } +} diff --git a/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/Messages/WxPusherMessageProvider.cs b/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/Messages/WxPusherMessageProvider.cs index 4a9a48b05..65ade6783 100644 --- a/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/Messages/WxPusherMessageProvider.cs +++ b/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/Messages/WxPusherMessageProvider.cs @@ -13,7 +13,7 @@ public class WxPusherMessageProvider : WxPusherRequestProvider, IWxPusherMessage int messageId, CancellationToken cancellationToken = default) { - var client = HttpClientFactory.GetPushPlusClient(); + var client = HttpClientFactory.GetWxPusherClient(); var content = await client.QueryMessageAsync( messageId, diff --git a/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/Messages/WxPusherMessageSender.cs b/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/Messages/WxPusherMessageSender.cs index 1ed0290d5..45f889a6a 100644 --- a/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/Messages/WxPusherMessageSender.cs +++ b/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/Messages/WxPusherMessageSender.cs @@ -34,7 +34,7 @@ public class WxPusherMessageSender : WxPusherRequestProvider, IWxPusherMessageSe CancellationToken cancellationToken = default) { var token = await WxPusherTokenProvider.GetTokenAsync(cancellationToken); - var client = HttpClientFactory.GetPushPlusClient(); + var client = HttpClientFactory.GetWxPusherClient(); var sendMessage = new SendMessage( token, content, diff --git a/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/QrCode/WxPusherQrCodeProvider.cs b/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/QrCode/WxPusherQrCodeProvider.cs index 17faee998..c755261e6 100644 --- a/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/QrCode/WxPusherQrCodeProvider.cs +++ b/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/QrCode/WxPusherQrCodeProvider.cs @@ -25,7 +25,7 @@ public class WxPusherQrCodeProvider : WxPusherRequestProvider, IWxPusherQrCodePr CancellationToken cancellationToken = default) { var token = await WxPusherTokenProvider.GetTokenAsync(cancellationToken); - var client = HttpClientFactory.GetPushPlusClient(); + var client = HttpClientFactory.GetWxPusherClient(); var request = new CreateQrcodeRequest(token, extra, validTime); var content = await client.CreateQrcodeAsync( @@ -43,7 +43,7 @@ public class WxPusherQrCodeProvider : WxPusherRequestProvider, IWxPusherQrCodePr { Check.NotNullOrWhiteSpace(code, nameof(code)); - var client = HttpClientFactory.GetPushPlusClient(); + var client = HttpClientFactory.GetWxPusherClient(); var content = await client.GetScanQrCodeUidAsync( code, diff --git a/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/User/WxPusherUserProvider.cs b/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/User/WxPusherUserProvider.cs index 15f5d0616..119a97beb 100644 --- a/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/User/WxPusherUserProvider.cs +++ b/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/LINGYUN/Abp/WxPusher/User/WxPusherUserProvider.cs @@ -23,7 +23,7 @@ public class WxPusherUserProvider : WxPusherRequestProvider, IWxPusherUserProvid CancellationToken cancellationToken = default) { var token = await WxPusherTokenProvider.GetTokenAsync(cancellationToken); - var client = HttpClientFactory.GetPushPlusClient(); + var client = HttpClientFactory.GetWxPusherClient(); var content = await client.DeleteUserAsync( token, @@ -49,7 +49,7 @@ public class WxPusherUserProvider : WxPusherRequestProvider, IWxPusherUserProvid } var token = await WxPusherTokenProvider.GetTokenAsync(cancellationToken); - var client = HttpClientFactory.GetPushPlusClient(); + var client = HttpClientFactory.GetWxPusherClient(); var content = await client.GetUserListAsync( token, @@ -72,7 +72,7 @@ public class WxPusherUserProvider : WxPusherRequestProvider, IWxPusherUserProvid CancellationToken cancellationToken = default) { var token = await WxPusherTokenProvider.GetTokenAsync(cancellationToken); - var client = HttpClientFactory.GetPushPlusClient(); + var client = HttpClientFactory.GetWxPusherClient(); var content = await client.RejectUserAsync( token, diff --git a/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/System/Net/Http/IHttpClientFactoryExtensions.cs b/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/System/Net/Http/IHttpClientFactoryExtensions.cs index 1134d85cb..66fcf2814 100644 --- a/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/System/Net/Http/IHttpClientFactoryExtensions.cs +++ b/aspnet-core/modules/wx-pusher/LINGYUN.Abp.WxPusher/System/Net/Http/IHttpClientFactoryExtensions.cs @@ -2,7 +2,7 @@ internal static class IHttpClientFactoryExtensions { - public static HttpClient GetPushPlusClient( + public static HttpClient GetWxPusherClient( this IHttpClientFactory httpClientFactory) { return httpClientFactory.CreateClient("_Abp_WxPusher_Client"); diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsDefinitionProvider.cs b/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsDefinitionProvider.cs index 89e87f50a..8b1b02cab 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsDefinitionProvider.cs +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsDefinitionProvider.cs @@ -8,16 +8,23 @@ group.AddNotification(NotificationsTestsNames.Test1, notificationType: NotificationType.Application, + contentType: NotificationContentType.Text, lifetime: NotificationLifetime.OnlyOne); group.AddNotification(NotificationsTestsNames.Test2, notificationType: NotificationType.Application, + contentType: NotificationContentType.Html, lifetime: NotificationLifetime.Persistent); group.AddNotification(NotificationsTestsNames.Test3, notificationType: NotificationType.User, contentType: NotificationContentType.Markdown, lifetime: NotificationLifetime.OnlyOne); + + group.AddNotification(NotificationsTestsNames.Test4, + notificationType: NotificationType.System, + contentType: NotificationContentType.Json, + lifetime: NotificationLifetime.OnlyOne); } } } diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsDefinitionProvider_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsDefinitionProvider_Tests.cs index 528e5c3ac..6dd8683d3 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsDefinitionProvider_Tests.cs +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsDefinitionProvider_Tests.cs @@ -25,7 +25,7 @@ namespace LINGYUN.Abp.Notifications public async Task GetNotifications_Test() { var notifications = await NotificationDefinitionManager.GetNotificationsAsync(); - notifications.Count.ShouldBe(6); + notifications.Count.ShouldBe(7); } [Fact] diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsNames.cs b/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsNames.cs index 2516405e3..a9db93e14 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsNames.cs +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.Tests/LINGYUN/Abp/Notifications/NotificationsTestsNames.cs @@ -8,6 +8,8 @@ public const string Test2 = GroupName + ".Test2"; - public const string Test3 = GroupName + ".Test3"; + public const string Test3 = GroupName + ".Test3"; + + public const string Test4 = GroupName + ".Test4"; } } diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/AbpNotificationsTuiJuheTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/AbpNotificationsTuiJuheTestBase.cs new file mode 100644 index 000000000..a5816be3b --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/AbpNotificationsTuiJuheTestBase.cs @@ -0,0 +1,7 @@ +using LINGYUN.Abp.Tests; + +namespace LINGYUN.Abp.Notifications.TuiJuhe; + +public abstract class AbpNotificationsTuiJuheTestBase : AbpTestsBase +{ +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/AbpNotificationsTuiJuheTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/AbpNotificationsTuiJuheTestModule.cs new file mode 100644 index 000000000..14c4db473 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/AbpNotificationsTuiJuheTestModule.cs @@ -0,0 +1,11 @@ +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Notifications.TuiJuhe; + +[DependsOn( + typeof(AbpNotificationsTuiJuheModule), + typeof(AbpTuiJuheTestModule), + typeof(AbpNotificationsTestsModule))] +public class AbpNotificationsTuiJuheTestModule : AbpModule +{ +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/NotificationSenderTests.cs b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/NotificationSenderTests.cs new file mode 100644 index 000000000..1f01d6ce4 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/NotificationSenderTests.cs @@ -0,0 +1,94 @@ +using System; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.Notifications.TuiJuhe; + +public class NotificationSenderTests : AbpNotificationsTuiJuheTestBase +{ + protected INotificationSender NotificationSender { get; } + + public NotificationSenderTests() + { + NotificationSender = GetRequiredService(); + } + + [Theory] + [InlineData( + "Form nTest Text", + "Text content from the Xunit unit test. \r\n Click the link https://www.baidu.com/ at the top to redirect baidu site.")] + public async Task Send_Text_Test( + string title, + string message) + { + var notificationData = new NotificationData(); + notificationData.WriteStandardData( + title, + message, + DateTime.Now, + "xUnit Test"); + + await NotificationSender.SendNofiterAsync( + NotificationsTestsNames.Test1, + notificationData); + } + + [Theory] + [InlineData( + "Form nTest Html", + "Html content from the Xunit unit test.
Click to redirect baidu site.")] + public async Task Send_Html_Test( + string title, + string message) + { + var notificationData = new NotificationData(); + notificationData.WriteStandardData( + title, + message, + DateTime.Now, + "xUnit Test"); + + await NotificationSender.SendNofiterAsync( + NotificationsTestsNames.Test2, + notificationData); + } + + [Theory] + [InlineData( + "Form nTest Markdown", + "**Markdown content from the Xunit unit test.**
Click to redirect baidu site.")] + public async Task Send_Markdown_Test( + string title, + string message) + { + var notificationData = new NotificationData(); + notificationData.WriteStandardData( + title, + message, + DateTime.Now, + "xUnit Test"); + + await NotificationSender.SendNofiterAsync( + NotificationsTestsNames.Test3, + notificationData); + } + + [Theory] + [InlineData( + "Form nTest Json", + "{\"content\":\"Content from the Xunit unit test.\",\"url\":{\"component\":{\"name\":\"a\",\"value\":\"Click to redirect baidu site.\",\"options\":{\"href\":\"https://www.baidu.com/\"}}}}")] + public async Task Send_Json_Test( + string title, + string message) + { + var notificationData = new NotificationData(); + notificationData.WriteStandardData( + title, + message, + DateTime.Now, + "xUnit Test"); + + await NotificationSender.SendNofiterAsync( + NotificationsTestsNames.Test4, + notificationData); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/NotificationsWxPusherTestsDefinitionProvider.cs b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/NotificationsWxPusherTestsDefinitionProvider.cs new file mode 100644 index 000000000..0cef4a0ba --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Abp/Notifications/TuiJuhe/NotificationsWxPusherTestsDefinitionProvider.cs @@ -0,0 +1,27 @@ +using System.Linq; + +namespace LINGYUN.Abp.Notifications.TuiJuhe; + +public class NotificationsWxPusherTestsDefinitionProvider : NotificationDefinitionProvider +{ + public override void Define(INotificationDefinitionContext context) + { + var group = context.GetGroupOrNull(NotificationsTestsNames.GroupName); + + var nt1 = group.Notifications.FirstOrDefault(n => n.Name.Equals(NotificationsTestsNames.Test1)); + nt1.WithProviders(TuiJuheNotificationPublishProvider.ProviderName) + .WithServiceId("1d5v5GuH"); + + var nt2 = group.Notifications.FirstOrDefault(n => n.Name.Equals(NotificationsTestsNames.Test2)); + nt2.WithProviders(TuiJuheNotificationPublishProvider.ProviderName) + .WithServiceId("1d5v5GuH"); + + var nt3 = group.Notifications.FirstOrDefault(n => n.Name.Equals(NotificationsTestsNames.Test3)); + nt3.WithProviders(TuiJuheNotificationPublishProvider.ProviderName) + .WithServiceId("1d5v5GuH"); + + var nt4 = group.Notifications.FirstOrDefault(n => n.Name.Equals(NotificationsTestsNames.Test4)); + nt4.WithProviders(TuiJuheNotificationPublishProvider.ProviderName) + .WithServiceId("1d5v5GuH"); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests.csproj new file mode 100644 index 000000000..24df96843 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests.csproj @@ -0,0 +1,20 @@ + + + + net6.0 + + false + + + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Usings.cs b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Usings.cs new file mode 100644 index 000000000..90e686b70 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Notifications.TuiJuhe.Tests/Usings.cs @@ -0,0 +1,4 @@ +global using Xunit; +global using Shouldly; +global using LINGYUN.Abp.TuiJuhe; +global using LINGYUN.Abp.Notifications.TuiJuhe; \ No newline at end of file diff --git a/aspnet-core/tests/LINGYUN.Abp.PushPlus.Tests/LINGYUN/Abp/PushPlus/AbpPushPlusTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.PushPlus.Tests/LINGYUN/Abp/PushPlus/AbpPushPlusTestModule.cs index 17c8c3300..f0d1255c7 100644 --- a/aspnet-core/tests/LINGYUN.Abp.PushPlus.Tests/LINGYUN/Abp/PushPlus/AbpPushPlusTestModule.cs +++ b/aspnet-core/tests/LINGYUN.Abp.PushPlus.Tests/LINGYUN/Abp/PushPlus/AbpPushPlusTestModule.cs @@ -1,4 +1,6 @@ -using LINGYUN.Abp.Tests; +using LINGYUN.Abp.PushPlus.Features; +using LINGYUN.Abp.Tests; +using LINGYUN.Abp.Tests.Features; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; @@ -21,4 +23,20 @@ public class AbpPushPlusTestModule : AbpModule context.Services.ReplaceConfiguration(configuration); } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Map(PushPlusFeatureNames.Message.Enable, (_) => "true"); + + options.Map(PushPlusFeatureNames.Channel.Email.Enable, (_) => "true"); + options.Map(PushPlusFeatureNames.Channel.Email.SendLimit, (_) => "500"); + options.Map(PushPlusFeatureNames.Channel.Email.SendLimitInterval, (_) => "1"); + + options.Map(PushPlusFeatureNames.Channel.WeChat.Enable, (_) => "true"); + options.Map(PushPlusFeatureNames.Channel.WeChat.SendLimit, (_) => "500"); + options.Map(PushPlusFeatureNames.Channel.WeChat.SendLimitInterval, (_) => "1"); + }); + } } diff --git a/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN.Abp.TuiJuhe.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN.Abp.TuiJuhe.Tests.csproj new file mode 100644 index 000000000..1a416f446 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN.Abp.TuiJuhe.Tests.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + + false + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN/Abp/TuiJuhe/AbpTuiJuheTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN/Abp/TuiJuhe/AbpTuiJuheTestBase.cs new file mode 100644 index 000000000..c34ca83eb --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN/Abp/TuiJuhe/AbpTuiJuheTestBase.cs @@ -0,0 +1,7 @@ +using LINGYUN.Abp.Tests; + +namespace LINGYUN.Abp.TuiJuhe; + +public class AbpTuiJuheTestBase : AbpTestsBase +{ +} diff --git a/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN/Abp/TuiJuhe/AbpTuiJuheTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN/Abp/TuiJuhe/AbpTuiJuheTestModule.cs new file mode 100644 index 000000000..d08457ebb --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN/Abp/TuiJuhe/AbpTuiJuheTestModule.cs @@ -0,0 +1,37 @@ +using LINGYUN.Abp.Tests; +using LINGYUN.Abp.Tests.Features; +using LINGYUN.Abp.TuiJuhe.Features; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.TuiJuhe; + +[DependsOn( + typeof(AbpTuiJuheModule), + typeof(AbpTestsBaseModule))] +public class AbpTuiJuheTestModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var configurationOptions = new AbpConfigurationBuilderOptions + { + BasePath = @"D:\Projects\Development\Abp\TuiJuhe", + EnvironmentName = "Test" + }; + var configuration = ConfigurationHelper.BuildConfiguration(configurationOptions); + + context.Services.ReplaceConfiguration(configuration); + } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Map(TuiJuheFeatureNames.Enable, (_) => "true"); + options.Map(TuiJuheFeatureNames.Message.Enable, (_) => "true"); + options.Map(TuiJuheFeatureNames.Message.SendLimit, (_) => "50"); + options.Map(TuiJuheFeatureNames.Message.SendLimitInterval, (_) => "1"); + }); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN/Abp/TuiJuhe/Messages/TuiJuheMessageSenderTests.cs b/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN/Abp/TuiJuhe/Messages/TuiJuheMessageSenderTests.cs new file mode 100644 index 000000000..c8ac0fbac --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/LINGYUN/Abp/TuiJuhe/Messages/TuiJuheMessageSenderTests.cs @@ -0,0 +1,100 @@ +using System.Threading.Tasks; + +namespace LINGYUN.Abp.TuiJuhe.Messages; + +public class TuiJuheMessageSenderTests : AbpTuiJuheTestBase +{ + protected ITuiJuheMessageSender MessageSender { get; } + public TuiJuheMessageSenderTests() + { + MessageSender = GetRequiredService(); + } + + [Theory] + [InlineData( + "Form Test Text", + "Content from the xUnit unit test. \r\n Click the link https://www.baidu.com/ at the top to redirect baidu site.", + "1d5v5GuH")] + public async virtual Task Send_Text_Test(string title, string content, string serviceId) + { + var result = await MessageSender + .SendAsync( + title, + content, + serviceId, + MessageContentType.Text); + + result.ShouldNotBeNull(); + result.Code.ShouldBe(200); + result.Reason.ShouldBe("success"); + result.Success.ShouldBeTrue(); + result.Params.ShouldBeNull(); + result.Result.ShouldBeNull(); + } + + [Theory] + [InlineData( + "Form Test Html", + "Content from the xUnit unit test.
Click to redirect baidu site.", + "1d5v5GuH")] + public async virtual Task Send_Html_Test(string title, string content, string serviceId) + { + var result = await MessageSender + .SendAsync( + title, + content, + serviceId, + MessageContentType.Html); + + result.ShouldNotBeNull(); + result.Code.ShouldBe(200); + result.Reason.ShouldBe("success"); + result.Success.ShouldBeTrue(); + result.Params.ShouldBeNull(); + result.Result.ShouldBeNull(); + } + + [Theory] + [InlineData( + "Form Test Markdown", + "**Content from the Xunit unit test.**
Click to redirect baidu site.", + "1d5v5GuH")] + public async virtual Task Send_Markdown_Test(string title, string content, string serviceId) + { + var result = await MessageSender + .SendAsync( + title, + content, + serviceId, + MessageContentType.Markdown); + + result.ShouldNotBeNull(); + result.Code.ShouldBe(200); + result.Reason.ShouldBe("success"); + result.Success.ShouldBeTrue(); + result.Params.ShouldBeNull(); + result.Result.ShouldBeNull(); + } + + [Theory] + [InlineData( + "Form Test Json", + "{\"content\":\"Content from the Xunit unit test.\",\"url\":{\"component\":{\"name\":\"a\",\"value\":\"Click to redirect baidu site.\",\"options\":{\"href\":\"https://www.baidu.com/\"}}}}", + "1d5v5GuH")] + public async virtual Task Send_Json_Test(string title, string content, string serviceId) + { + var result = await MessageSender + .SendAsync( + title, + content, + serviceId, + MessageContentType.Json); + + result.ShouldNotBeNull(); + result.Code.ShouldBe(200); + result.Reason.ShouldBe("success"); + result.Success.ShouldBeTrue(); + result.Params.ShouldBeNull(); + result.Result.ShouldBeNull(); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/Usings.cs b/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/Usings.cs new file mode 100644 index 000000000..cc8a010b0 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.TuiJuhe.Tests/Usings.cs @@ -0,0 +1,3 @@ +global using Xunit; +global using Shouldly; +global using LINGYUN.Abp.TuiJuhe; \ No newline at end of file diff --git a/aspnet-core/tests/LINGYUN.Abp.WxPusher.Tests/LINGYUN/Abp/WxPusher/AbpWxPusherTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.WxPusher.Tests/LINGYUN/Abp/WxPusher/AbpWxPusherTestModule.cs index c27d43a09..c923c42bc 100644 --- a/aspnet-core/tests/LINGYUN.Abp.WxPusher.Tests/LINGYUN/Abp/WxPusher/AbpWxPusherTestModule.cs +++ b/aspnet-core/tests/LINGYUN.Abp.WxPusher.Tests/LINGYUN/Abp/WxPusher/AbpWxPusherTestModule.cs @@ -1,4 +1,6 @@ using LINGYUN.Abp.Tests; +using LINGYUN.Abp.Tests.Features; +using LINGYUN.Abp.WxPusher.Features; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.Modularity; @@ -21,4 +23,15 @@ public class AbpWxPusherTestModule : AbpModule context.Services.ReplaceConfiguration(configuration); } + + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Map(WxPusherFeatureNames.Enable, (_) => "true"); + options.Map(WxPusherFeatureNames.Message.Enable, (_) => "true"); + options.Map(WxPusherFeatureNames.Message.SendLimit, (_) => "500"); + options.Map(WxPusherFeatureNames.Message.SendLimitInterval, (_) => "1"); + }); + } }