diff --git a/CHANGELOG.md b/CHANGELOG.md
index 72519ff21..efb8b7c90 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,3 +24,6 @@
## 0.0.7
- 【#44】兼容青龙最新版本(v2.12.0),修复因青龙调整目录结构导致的bug
- 更新`publish-image.yml`,只有`release`时才打`latest tag`,手动运行时不打`latest tag`
+## 0.0.8
+- 【#55】新增日志推送端:Microsoft Teams
+- 【#27】更新README
diff --git a/README.md b/README.md
index b037bafff..0dcd8a20d 100644
--- a/README.md
+++ b/README.md
@@ -71,7 +71,7 @@ BiliBiliTool
- **所有代码都是开源且透明的,任何人均可查看,程序不会保存或滥用任何用户的个人信息**
- **应用内几乎所有功能都开放为了配置(如任务开关、日期、upId等),请仔细阅读配置文档,自己对自己的配置负责**
-_(如果图片挂了,是因为 GitHub 的服务器在国外,经常会刷不出,有梯子的可以架起梯子,没有的也可以先参考 [我的博客](https://www.cnblogs.com/RayWang/p/13909784.html),但博客内容不保证最新)_
+_(如果图片挂了,请自己架梯子,没有的也可以先参考 [我的博客](https://www.cnblogs.com/RayWang/p/13909784.html),但内容不保证最新)_
## 1. 如何使用
@@ -156,7 +156,12 @@ P.S.这里的运行环境指的是 `.NET Runtime 6.0.0` ,安装方法可详见
对于已安装.net环境,且使用的是依赖包,同上,可在终端中执行命令:`dotnet Ray.BiliBiliTool.Console.dll`
-对于使用独立包的,可在终端中执行命令:`Ray.BiliBiliTool.Console`。
+对于使用独立包的,可在终端中执行命令:
+
+```
+chmod +x ./Ray.BiliBiliTool.Console
+Ray.BiliBiliTool.Console
+```
其他系统依此类推,运行结果图示如下:
diff --git a/Ray.BiliBiliTool.sln b/Ray.BiliBiliTool.sln
index ac954cdb2..41fd70ae3 100644
--- a/Ray.BiliBiliTool.sln
+++ b/Ray.BiliBiliTool.sln
@@ -148,6 +148,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{75A9CC5C
docker\build\buildImage_arm64.cmd = docker\build\buildImage_arm64.cmd
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ray.Serilog.Sinks.MicrosoftTeams", "src\Ray.Serilog.Sinks\Ray.Serilog.Sinks.MicrosoftTeams\Ray.Serilog.Sinks.MicrosoftTeams.csproj", "{F249A822-EFD3-4F0A-9C10-95A96676D61A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -226,6 +228,10 @@ Global
{F6B8ED3A-5428-4D26-8172-8B41FBF0C4CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F6B8ED3A-5428-4D26-8172-8B41FBF0C4CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6B8ED3A-5428-4D26-8172-8B41FBF0C4CF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F249A822-EFD3-4F0A-9C10-95A96676D61A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F249A822-EFD3-4F0A-9C10-95A96676D61A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F249A822-EFD3-4F0A-9C10-95A96676D61A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F249A822-EFD3-4F0A-9C10-95A96676D61A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -263,6 +269,7 @@ Global
{830361B7-BCC1-4853-879A-761B0FD86826} = {73DD457B-E06E-45ED-A6BA-7E3C02F8BDF1}
{F6B8ED3A-5428-4D26-8172-8B41FBF0C4CF} = {E9BDDCBE-A57D-4E3B-8252-708088386ADF}
{75A9CC5C-DF92-4D72-A14C-625AA902855B} = {A93210FD-27B6-40E4-B08D-391F96CA2754}
+ {F249A822-EFD3-4F0A-9C10-95A96676D61A} = {4BAFC980-7A73-45C3-9460-8B8CCB87939B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {197319DA-1148-4A99-847C-8B270B6A29AB}
diff --git a/common.props b/common.props
index e462eccc0..b43ce0fd9 100644
--- a/common.props
+++ b/common.props
@@ -1,7 +1,7 @@
Ray
- 0.0.7
+ 0.0.8
$(NoWarn);CS1591;CS0436
diff --git a/docs/configuration.md b/docs/configuration.md
index dfd1b71cd..e1be7ebe6 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -59,6 +59,8 @@
- [3.6.8.2. PushPlus的Topic](#3682-pushplus的topic)
- [3.6.8.3. PushPlus的Channel](#3683-pushplus的channel)
- [3.6.8.4. PushPlus的Webhook](#3684-pushplus的webhook)
+ - [3.6.9. Microsoft Teams](#369-microsoft-teams)
+ - [3.6.9.1. Microsoft Teams的Webhook](#3691-microsoft-teams的webhook)
- [3.7. 日志相关](#37-日志相关)
- [3.7.1. Console日志输出等级](#371-console日志输出等级)
- [3.7.2. Console日志输出样式](#372-console日志输出样式)
@@ -665,6 +667,25 @@ webhook编码(不是地址),在官网平台设定,仅在channel使用webhook
| 命令行示范 | |
| GitHub Secrets | `PUSHPLUSWEBHOOK` |
+
+#### 3.6.9. Microsoft Teams
+
+官网: https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook
+
+
+##### 3.6.9.1. Microsoft Teams的Webhook
+
+webhook的完整地址,在Teams的Channel中获取,详细获取方式请参考官网。
+
+| TITLE | CONTENT |
+| ---------- | -------------- |
+| 配置Key | `Serilog__WriteTo__10__Args__webhook` |
+| 值域 | 一串字符串 |
+| 默认值 | 空 |
+| 环境变量 | `Serilog__WriteTo__10__Args__webhook` |
+| 命令行示范 | |
+| GitHub Secrets | |
+
### 3.7. 日志相关
diff --git a/src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj b/src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj
index 535ef48f9..2a525d2db 100644
--- a/src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj
+++ b/src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj
@@ -76,6 +76,7 @@
+
diff --git a/src/Ray.BiliBiliTool.Console/appsettings.json b/src/Ray.BiliBiliTool.Console/appsettings.json
index 0422ff7a4..a60dd7efc 100644
--- a/src/Ray.BiliBiliTool.Console/appsettings.json
+++ b/src/Ray.BiliBiliTool.Console/appsettings.json
@@ -154,6 +154,14 @@
"webhook": "", //webhook编码(不是地址),仅在channel使用webhook渠道和CP渠道时需要填写
"restrictedToMinimumLevel": "Information"
}
+ },
+ //10.MicrosoftTeams
+ {
+ "Name": "MicrosoftTeamsBatched",
+ "Args": {
+ "webhook": "", //webhook完整地址
+ "restrictedToMinimumLevel": "Information"
+ }
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/MicrosoftTeamsApiClient.cs b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/MicrosoftTeamsApiClient.cs
new file mode 100644
index 000000000..1865379c0
--- /dev/null
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/MicrosoftTeamsApiClient.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Net.Http;
+using System.Text;
+using Ray.Serilog.Sinks.Batched;
+
+namespace Ray.Serilog.Sinks.MicrosoftTeams
+{
+ public class MicrosoftTeamsApiClient : PushService
+ {
+ //https://docs.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook
+
+ private readonly Uri _apiUrl;
+ private readonly HttpClient _httpClient = new HttpClient();
+
+ public MicrosoftTeamsApiClient(
+ string webhook
+ )
+ {
+ _apiUrl = new Uri(webhook);
+ }
+
+ public override string ClientName => "MicrosoftTeams";
+
+ protected override string NewLineStr => "
";
+
+ public override HttpResponseMessage DoSend()
+ {
+ var json = new
+ {
+ text=Msg
+ }.ToJson();
+
+ var content = new StringContent(json, Encoding.UTF8, "application/json");
+
+ var response = _httpClient.PostAsync(_apiUrl, content).GetAwaiter().GetResult();
+ return response;
+ }
+ }
+}
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/MicrosoftTeamsBatchedSink.cs b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/MicrosoftTeamsBatchedSink.cs
new file mode 100644
index 000000000..1d7d00e67
--- /dev/null
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/MicrosoftTeamsBatchedSink.cs
@@ -0,0 +1,38 @@
+using System;
+using Ray.Serilog.Sinks.Batched;
+using Serilog.Events;
+
+namespace Ray.Serilog.Sinks.MicrosoftTeams
+{
+ public class MicrosoftTeamsBatchedSink : BatchedSink
+ {
+ private readonly string _webhook;
+
+ public MicrosoftTeamsBatchedSink(
+ string webhook,
+ Predicate predicate,
+ bool sendBatchesAsOneMessages,
+ string outputTemplate,
+ IFormatProvider formatProvider,
+ LogEventLevel minimumLogEventLevel
+ )
+ : base(predicate, sendBatchesAsOneMessages, outputTemplate, formatProvider, minimumLogEventLevel)
+ {
+ _webhook = webhook;
+ }
+
+ public override void Emit(LogEvent logEvent)
+ {
+ if (_webhook.IsNullOrEmpty()) return;
+ base.Emit(logEvent);
+ }
+
+ protected override PushService PushService => new MicrosoftTeamsApiClient(
+ webhook: _webhook);
+
+ public override void Dispose()
+ {
+ //todo
+ }
+ }
+}
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/MicrosoftTeamsConfigurationExtensions.cs b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/MicrosoftTeamsConfigurationExtensions.cs
new file mode 100644
index 000000000..e85fd6fcf
--- /dev/null
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/MicrosoftTeamsConfigurationExtensions.cs
@@ -0,0 +1,40 @@
+using System;
+using Ray.Serilog.Sinks.Batched;
+using Serilog;
+using Serilog.Configuration;
+using Serilog.Events;
+
+namespace Ray.Serilog.Sinks.MicrosoftTeams
+{
+ public static class MicrosoftTeamsConfigurationExtensions
+ {
+ public static LoggerConfiguration MicrosoftTeamsBatched(
+ this LoggerSinkConfiguration loggerSinkConfiguration,
+ string webhook = "",
+ string containsTrigger = Constants.DefaultContainsTrigger,
+ bool sendBatchesAsOneMessages = true,
+ string outputTemplate = Constants.DefaultOutputTemplate,
+ IFormatProvider formatProvider = null,
+ LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose
+ )
+ {
+ if (loggerSinkConfiguration == null)
+ throw new ArgumentNullException(nameof(loggerSinkConfiguration));
+ if (outputTemplate == null)
+ throw new ArgumentNullException(nameof(outputTemplate));
+
+ if (containsTrigger.IsNullOrEmpty()) containsTrigger = Constants.DefaultContainsTrigger;
+ Predicate predicate = x => x.MessageTemplate.Text.Contains(containsTrigger);
+
+ return loggerSinkConfiguration.Sink(
+ new MicrosoftTeamsBatchedSink(
+ webhook,
+ predicate,
+ sendBatchesAsOneMessages,
+ outputTemplate,
+ formatProvider,
+ restrictedToMinimumLevel),
+ restrictedToMinimumLevel);
+ }
+ }
+}
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/Ray.Serilog.Sinks.MicrosoftTeams.csproj b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/Ray.Serilog.Sinks.MicrosoftTeams.csproj
new file mode 100644
index 000000000..55eb04647
--- /dev/null
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeams/Ray.Serilog.Sinks.MicrosoftTeams.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
diff --git a/test/LogTest/LogTest.csproj b/test/LogTest/LogTest.csproj
index b5e400b4a..97f27ee26 100644
--- a/test/LogTest/LogTest.csproj
+++ b/test/LogTest/LogTest.csproj
@@ -21,6 +21,7 @@
+
diff --git a/test/LogTest/TestMicrosoftTeams.cs b/test/LogTest/TestMicrosoftTeams.cs
new file mode 100644
index 000000000..e5e2d131c
--- /dev/null
+++ b/test/LogTest/TestMicrosoftTeams.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Diagnostics;
+using System.Threading;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using Ray.BiliBiliTool.Console;
+using Ray.BiliBiliTool.Infrastructure;
+using Ray.Serilog.Sinks.CoolPushBatched;
+using Ray.Serilog.Sinks.MicrosoftTeams;
+using Ray.Serilog.Sinks.PushPlusBatched;
+using Ray.Serilog.Sinks.ServerChanBatched;
+using Xunit;
+
+namespace LogTest
+{
+ public class TestMicrosoftTeams
+ {
+ private string _webhook;
+
+ public TestMicrosoftTeams()
+ {
+ Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
+ Program.CreateHost(new string[] { });
+
+ _webhook = Global.ConfigurationRoot["Serilog:WriteTo:10:Args:webhook"];
+ }
+
+ [Fact]
+ public void Test()
+ {
+ var client = new MicrosoftTeamsApiClient(webhook: _webhook);
+
+ var msg = LogConstants.Msg2;
+
+ var result = client.PushMessage(msg);
+ Debug.WriteLine(result.Content.ReadAsStringAsync().Result);
+
+ Assert.True(result.StatusCode == System.Net.HttpStatusCode.OK);
+ }
+ }
+}