From 0e2d15c97acf1cdf4ebcdb731bb03bc86a26a8e9 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 20 May 2024 23:31:55 +0800 Subject: [PATCH 01/10] update UTs --- test/LogTest/LogTest.csproj | 2 ++ test/LogTest/TestCoolPush.cs | 2 -- test/LogTest/TestDingTalk.cs | 2 -- test/LogTest/TestMicrosoftTeams.cs | 2 +- test/LogTest/TestPushPlus.cs | 2 -- test/LogTest/TestWorkWeiXin.cs | 6 ++--- test/LogTest/UnitTest1.cs | 3 --- .../ArticleApiTests.cs | 6 +++-- .../ChargeApiTest.cs | 22 ++++--------------- .../DailyTaskApiTests.cs | 6 ++--- 10 files changed, 17 insertions(+), 36 deletions(-) diff --git a/test/LogTest/LogTest.csproj b/test/LogTest/LogTest.csproj index 71444b237..90f0c86ed 100644 --- a/test/LogTest/LogTest.csproj +++ b/test/LogTest/LogTest.csproj @@ -4,6 +4,8 @@ net6.0 false + + 5bc79f80-380e-4bcf-9c0b-30e98db3b935 diff --git a/test/LogTest/TestCoolPush.cs b/test/LogTest/TestCoolPush.cs index 407e3f28e..5769261f2 100644 --- a/test/LogTest/TestCoolPush.cs +++ b/test/LogTest/TestCoolPush.cs @@ -42,8 +42,6 @@ public void Test2() CoolPushApiClient client = new CoolPushApiClient(_key); var result = client.PushMessage(msg8); Debug.WriteLine(result.Content.ReadAsStringAsync().Result); - - System.Console.ReadLine(); } } } diff --git a/test/LogTest/TestDingTalk.cs b/test/LogTest/TestDingTalk.cs index ddeefd591..2931afc78 100644 --- a/test/LogTest/TestDingTalk.cs +++ b/test/LogTest/TestDingTalk.cs @@ -34,8 +34,6 @@ public void Test2() var result = client.PushMessage(msg); Debug.WriteLine(result.Content.ReadAsStringAsync().Result); - - System.Console.ReadLine(); } } } diff --git a/test/LogTest/TestMicrosoftTeams.cs b/test/LogTest/TestMicrosoftTeams.cs index 491098d7b..4e8083254 100644 --- a/test/LogTest/TestMicrosoftTeams.cs +++ b/test/LogTest/TestMicrosoftTeams.cs @@ -20,7 +20,7 @@ public class TestMicrosoftTeams public TestMicrosoftTeams() { Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development"); - Program.CreateHost(new string[] { }); + Program.CreateHost(new string[] { "ENVIRONMENT=Development" }); _webhook = Global.ConfigurationRoot["Serilog:WriteTo:10:Args:webhook"]; } diff --git a/test/LogTest/TestPushPlus.cs b/test/LogTest/TestPushPlus.cs index 4af77bdba..21932cce3 100644 --- a/test/LogTest/TestPushPlus.cs +++ b/test/LogTest/TestPushPlus.cs @@ -40,8 +40,6 @@ public void Test2() var result = client.PushMessage(msg); Debug.WriteLine(result.Content.ReadAsStringAsync().Result); - - System.Console.ReadLine(); } } } diff --git a/test/LogTest/TestWorkWeiXin.cs b/test/LogTest/TestWorkWeiXin.cs index 08c7b4f26..54de85c0d 100644 --- a/test/LogTest/TestWorkWeiXin.cs +++ b/test/LogTest/TestWorkWeiXin.cs @@ -16,8 +16,8 @@ public class TestWorkWeiXin public TestWorkWeiXin() { - Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development"); - Program.CreateHost(new string[] { }); + Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", "Development"); + Program.CreateHost(new string[] { "ENVIRONMENT=Development" }); _key = Global.ConfigurationRoot["Serilog:WriteTo:4:Args:webHookUrl"]; } @@ -25,7 +25,7 @@ public TestWorkWeiXin() [Fact] public void Test2() { - WorkWeiXinApiClient client = new WorkWeiXinApiClient(_key); + var client = new WorkWeiXinApiClient(_key); //string msg = LogConstants.Msg; string msg = LogConstants.Msg2; diff --git a/test/LogTest/UnitTest1.cs b/test/LogTest/UnitTest1.cs index 9f665ac88..a192b00a5 100644 --- a/test/LogTest/UnitTest1.cs +++ b/test/LogTest/UnitTest1.cs @@ -31,8 +31,6 @@ public void Test1() logger.LogDebug(null); logger.LogDebug("123{0}{1}", null, "haha"); - - System.Console.ReadLine(); } [Fact] @@ -53,7 +51,6 @@ public void Test2() logger.LogInformation("-----ȫִн-----\r\n"); logger.LogInformation("ʼ"); - System.Console.ReadLine(); } private ILogger CreateLogger() diff --git a/test/Ray.BiliBiliTool.Agent.FunctionalTests/ArticleApiTests.cs b/test/Ray.BiliBiliTool.Agent.FunctionalTests/ArticleApiTests.cs index 6f72ea60a..60c03f878 100644 --- a/test/Ray.BiliBiliTool.Agent.FunctionalTests/ArticleApiTests.cs +++ b/test/Ray.BiliBiliTool.Agent.FunctionalTests/ArticleApiTests.cs @@ -117,8 +117,10 @@ public async Task AddCoinForArticleAsync_Normal_Success() BiliBiliAgent.Dtos.BiliApiResponse re = await _api.AddCoinForArticleAsync(req); // Assert - re.Code.Should().Be(0); - re.Message.Should().BeEquivalentTo("0"); + re.Code.Should().BeOneOf( + 0,// 成功 + 34005 // 超过投币上限啦~ + ); } #endregion diff --git a/test/Ray.BiliBiliTool.Agent.FunctionalTests/ChargeApiTest.cs b/test/Ray.BiliBiliTool.Agent.FunctionalTests/ChargeApiTest.cs index 086a6e6b9..eb776dbe4 100644 --- a/test/Ray.BiliBiliTool.Agent.FunctionalTests/ChargeApiTest.cs +++ b/test/Ray.BiliBiliTool.Agent.FunctionalTests/ChargeApiTest.cs @@ -40,30 +40,16 @@ public async void ChargeV2Async_SendRequest_NotEnough() // Assert re.Code.Should().Be(0); - re.Data.Status.Should().Be(-4); - re.Data.Msg.Should().BeEquivalentTo("bp.to.battery http failed, invalid args, errNo=800409904: B "); + re.Data.Status.Should().BeOneOf( + -4,//bp.to.battery http failed, invalid args, errNo=800409904: B  + 4 + ); } #endregion #region ChargeCommentAsync - [Fact] - public async void ChargeCommentAsync_SendRequest_SetWridSuccess() - { - // Arrange - var upId = 220893216; - var req = new ChargeRequest(2, upId, _ck.BiliJct); - - // Act - BiliApiResponse re = await _target.ChargeV2Async(req); - - // Assert - re.Code.Should().Be(0); - re.Data.Status.Should().Be(-4); - re.Data.Msg.Should().BeEquivalentTo("bp.to.battery http failed, invalid args, errNo=800409904: B "); - } - #endregion } diff --git a/test/Ray.BiliBiliTool.Agent.FunctionalTests/DailyTaskApiTests.cs b/test/Ray.BiliBiliTool.Agent.FunctionalTests/DailyTaskApiTests.cs index f4cc92653..5d204b18f 100644 --- a/test/Ray.BiliBiliTool.Agent.FunctionalTests/DailyTaskApiTests.cs +++ b/test/Ray.BiliBiliTool.Agent.FunctionalTests/DailyTaskApiTests.cs @@ -61,10 +61,10 @@ public async Task ReceiveVipPrivilege_Normal_Success() // Arrange // Assert - re.Code.Should().BeOneOf(new List - { + re.Code.Should().BeOneOf( 0, 73319, //todo: sort out meannings - }); + 69801 //你已领取过该权益 + ); } } From ca2a7b2a69d2a7ecb7e41915ad556151e736a15d Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 20 May 2024 23:48:02 +0800 Subject: [PATCH 02/10] add ut script --- scripts/ut.ps1 | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 scripts/ut.ps1 diff --git a/scripts/ut.ps1 b/scripts/ut.ps1 new file mode 100644 index 000000000..26c9f9bf0 --- /dev/null +++ b/scripts/ut.ps1 @@ -0,0 +1,17 @@ +Set-Location .. + +# 安装 ReportGenerator 工具 +Write-Output "Installing ReportGenerator tool..." +dotnet tool install -g dotnet-reportgenerator-globaltool + +# 运行单元测试并生成覆盖率报告 +Write-Output "Running unit tests and generating coverage report..." +dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover + +# 生成 HTML 格式的覆盖率报告 +Write-Output "Generating HTML coverage report..." +reportgenerator "-reports:TestResults/*/coverage.opencover.xml" "-targetdir:coveragereport" -reporttypes:Html + +# 打开生成的覆盖率报告 +Write-Output "Opening coverage report..." +Start-Process "coveragereport/index.htm" \ No newline at end of file From 6feacf714c48a09d725f931c08c7055ae4bad85c Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 22 May 2024 22:47:32 +0800 Subject: [PATCH 03/10] update UT script --- .gitignore | 5 +- Ray.BiliBiliTool.sln | 11 ++++- scripts/ut.ps1 | 14 +++--- .../DailyTask/DonateCoinsTest.cs | 2 - test/BiliAgentTest/HomeApiTest.cs | 35 -------------- test/InfrastructureTest/WbiHelperTest.cs | 2 +- test/LogTest/TestCoolPush.cs | 46 +++++++++---------- test/LogTest/TestDingTalk.cs | 5 +- .../LiveApiTest.cs | 7 ++- 9 files changed, 55 insertions(+), 72 deletions(-) delete mode 100644 test/BiliAgentTest/HomeApiTest.cs rename test/{BiliAgentTest => Ray.BiliBiliTool.Agent.FunctionalTests}/LiveApiTest.cs (97%) diff --git a/.gitignore b/.gitignore index 7b6b2a964..6a25dffb9 100644 --- a/.gitignore +++ b/.gitignore @@ -368,4 +368,7 @@ krew/pkg/utils/fixtures kustomization.yaml # cookie config -**/Ray.BiliBiliTool.Console/cookies.json \ No newline at end of file +**/Ray.BiliBiliTool.Console/cookies.json + +# ut +coveragereport diff --git a/Ray.BiliBiliTool.sln b/Ray.BiliBiliTool.sln index c27d5bed0..617db82c4 100644 --- a/Ray.BiliBiliTool.sln +++ b/Ray.BiliBiliTool.sln @@ -39,7 +39,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig .gitignore = .gitignore CHANGELOG.md = CHANGELOG.md - clean.cmd = clean.cmd common.props = common.props Dockerfile = Dockerfile LICENSE = LICENSE @@ -139,6 +138,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InfrastructureTest", "test\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ray.BiliBiliTool.Agent.FunctionalTests", "test\Ray.BiliBiliTool.Agent.FunctionalTests\Ray.BiliBiliTool.Agent.FunctionalTests.csproj", "{16F315CF-056A-4B08-8C3C-A3177EA3CBB9}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{2B5FD099-CC28-4FBC-9F20-F20300C5DFD2}" + ProjectSection(SolutionItems) = preProject + scripts\clean.cmd = scripts\clean.cmd + scripts\publish.bat = scripts\publish.bat + scripts\publish.ps1 = scripts\publish.ps1 + scripts\publish.sh = scripts\publish.sh + scripts\ut.ps1 = scripts\ut.ps1 + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -233,6 +241,7 @@ Global {26B21C30-7358-4E7B-A73E-2272F10A6CA8} = {E9BDDCBE-A57D-4E3B-8252-708088386ADF} {90C1DB73-B3DB-4BE5-AD1A-5248FE47860E} = {E9BDDCBE-A57D-4E3B-8252-708088386ADF} {16F315CF-056A-4B08-8C3C-A3177EA3CBB9} = {E9BDDCBE-A57D-4E3B-8252-708088386ADF} + {2B5FD099-CC28-4FBC-9F20-F20300C5DFD2} = {F3DE0D72-426B-4AD9-B3ED-3343CF4223F1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {197319DA-1148-4A99-847C-8B270B6A29AB} diff --git a/scripts/ut.ps1 b/scripts/ut.ps1 index 26c9f9bf0..5107aab08 100644 --- a/scripts/ut.ps1 +++ b/scripts/ut.ps1 @@ -6,12 +6,14 @@ dotnet tool install -g dotnet-reportgenerator-globaltool # 运行单元测试并生成覆盖率报告 Write-Output "Running unit tests and generating coverage report..." -dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover +dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput=./TestResults/coverage.opencover.xml -# 生成 HTML 格式的覆盖率报告 -Write-Output "Generating HTML coverage report..." -reportgenerator "-reports:TestResults/*/coverage.opencover.xml" "-targetdir:coveragereport" -reporttypes:Html +# 生成html报告 +$coverageFiles = Get-ChildItem -Path . -Recurse -Filter "coverage.cobertura.xml" +$coverageFiles | ForEach-Object { Write-Output $_.FullName } +$reportPaths = ($coverageFiles | ForEach-Object { $_.FullName }) -join ";" +reportgenerator "-reports:$reportPaths" "-targetdir:coveragereport" -reporttypes:Html -# 打开生成的覆盖率报告 -Write-Output "Opening coverage report..." +# 检查生成的覆盖率报告文件是否存在 +Write-Output "Coverage report generated successfully." Start-Process "coveragereport/index.htm" \ No newline at end of file diff --git a/test/AppServiceTest/DailyTask/DonateCoinsTest.cs b/test/AppServiceTest/DailyTask/DonateCoinsTest.cs index 9b61f1e74..9c6cdbf8e 100644 --- a/test/AppServiceTest/DailyTask/DonateCoinsTest.cs +++ b/test/AppServiceTest/DailyTask/DonateCoinsTest.cs @@ -17,8 +17,6 @@ public void Test1() { using var scope = Global.ServiceProviderRoot.CreateScope(); var appService = scope.ServiceProvider.GetRequiredService(); - - } } } diff --git a/test/BiliAgentTest/HomeApiTest.cs b/test/BiliAgentTest/HomeApiTest.cs deleted file mode 100644 index f953aea73..000000000 --- a/test/BiliAgentTest/HomeApiTest.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Ray.BiliBiliTool.Agent; -using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos; -using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Live; -using Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces; -using Ray.BiliBiliTool.Console; -using Ray.BiliBiliTool.Infrastructure; -using Ray.BiliBiliTool.Infrastructure.Helpers; -using Xunit; - -namespace BiliAgentTest -{ - public class HomeApiTest - { - public HomeApiTest() - { - Program.CreateHost(new[] { "--ENVIRONMENT=Development" }); - } - - [Fact] - public async Task WebHeartBeat_Normal_Success() - { - using var scope = Global.ServiceProviderRoot.CreateScope(); - - var ck = scope.ServiceProvider.GetRequiredService(); - var api = scope.ServiceProvider.GetRequiredService(); - - var re = await api.GetHomePageAsync(ck.ToString()); - - - } - } -} diff --git a/test/InfrastructureTest/WbiHelperTest.cs b/test/InfrastructureTest/WbiHelperTest.cs index 630d3f5f2..2b910dd29 100644 --- a/test/InfrastructureTest/WbiHelperTest.cs +++ b/test/InfrastructureTest/WbiHelperTest.cs @@ -15,7 +15,7 @@ public void Replace_Test() string output = Regex.Replace(input, pattern, replacement); Debug.WriteLine(output); - Assert.Equal(output, "һΰַ@#$%^&ַ"); + Assert.Equal("һΰַ@#$%^&ַ", output); } } } diff --git a/test/LogTest/TestCoolPush.cs b/test/LogTest/TestCoolPush.cs index 5769261f2..848adf3a7 100644 --- a/test/LogTest/TestCoolPush.cs +++ b/test/LogTest/TestCoolPush.cs @@ -16,32 +16,32 @@ namespace LogTest { public class TestCoolPush { - private string _key; + //private string _key; - public TestCoolPush() - { - Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development"); - Program.CreateHost(new string[] { }); + //public TestCoolPush() + //{ + // Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development"); + // Program.CreateHost(new string[] { }); - _key = Global.ConfigurationRoot["Serilog:WriteTo:7:Args:sKey"]; - } + // _key = Global.ConfigurationRoot["Serilog:WriteTo:7:Args:sKey"]; + //} - [Fact] - public void Test2() - { - //var msg = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"投币\"】---\r\n\r\nℹ 今日已投5枚硬币,已完成投币任务,不需要再投啦~\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"漫画签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心银瓜子兑换硬币\"】---\r\n\r\nℹ 银瓜子兑换硬币失败,原因:\"银瓜子余额不足\"\r\n\r\nℹ 当前银瓜子余额: 564\r\n\r\nℹ 当前硬币余额: 672.4\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"每月领取大会员福利\"】---\r\n\r\nℹ 目标领取日期为1号,今天是25号,跳过领取任务\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"每月领取大会员漫画权益\"】---\r\n\r\nℹ 目标领取日期为1号,今天是25号,跳过领取任务\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"每月为自己充电\"】---\r\n\r\nℹ 目标充电日期为31号,今天是25号,跳过充电任务\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ -----全部任务已执行结束-----\r\n\r\n\r\nℹ 开始推送\r\n\r\n"; - //var msg2 = "ℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; - //var msg3 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"投币\"】---\r\n\r\nℹ 今日已投5枚硬币,已完成投币任务,不需要再投啦~\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"漫画签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心银瓜子兑换硬币\"】---\r\n\r\nℹ 银瓜子兑换硬币失败,原因:\"银瓜子余额不足\"\r\n\r\nℹ 当前银瓜子余额: 564\r\n\r\nℹ 当前硬币余额: 672.4\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"每月领取大会员福利\"】---\r\n\r\nℹ 目标领取日期为1号,今天是25号,跳过领取任务\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"每月领取大会员漫画权益\"】---\r\n\r\nℹ 目标领取日期为1号,今天是25号,跳过领取任务\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ"; - //var msg4 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"投币\"】---\r\n\r\nℹ 今日已投5枚硬币,已完成投币任务,不需要再投啦~\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"漫画签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心银瓜子兑换硬币\"】---\r\n\r\nℹ 银瓜子兑换硬币失败,原因:\"银瓜子余额不足\"\r\n\r\nℹ 当前银瓜子余额: 564\r\n\r\nℹ 当前硬币余额: 672.4\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; - //var msg5 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"投币\"】---\r\n\r\nℹ 今日已投5枚硬币,已完成投币任务,不需要再投啦~\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"漫画签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; - //var msg6 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"投币\"】---\r\n\r\nℹ 今日已投5枚硬币,已完成投币任务,不需要再投啦~\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; - //var msg7 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; - var msg8 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; - //var msg9 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\n"; + //[Fact] + //public void Test2() + //{ + // //var msg = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"投币\"】---\r\n\r\nℹ 今日已投5枚硬币,已完成投币任务,不需要再投啦~\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"漫画签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心银瓜子兑换硬币\"】---\r\n\r\nℹ 银瓜子兑换硬币失败,原因:\"银瓜子余额不足\"\r\n\r\nℹ 当前银瓜子余额: 564\r\n\r\nℹ 当前硬币余额: 672.4\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"每月领取大会员福利\"】---\r\n\r\nℹ 目标领取日期为1号,今天是25号,跳过领取任务\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"每月领取大会员漫画权益\"】---\r\n\r\nℹ 目标领取日期为1号,今天是25号,跳过领取任务\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"每月为自己充电\"】---\r\n\r\nℹ 目标充电日期为31号,今天是25号,跳过充电任务\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ -----全部任务已执行结束-----\r\n\r\n\r\nℹ 开始推送\r\n\r\n"; + // //var msg2 = "ℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; + // //var msg3 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"投币\"】---\r\n\r\nℹ 今日已投5枚硬币,已完成投币任务,不需要再投啦~\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"漫画签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心银瓜子兑换硬币\"】---\r\n\r\nℹ 银瓜子兑换硬币失败,原因:\"银瓜子余额不足\"\r\n\r\nℹ 当前银瓜子余额: 564\r\n\r\nℹ 当前硬币余额: 672.4\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"每月领取大会员福利\"】---\r\n\r\nℹ 目标领取日期为1号,今天是25号,跳过领取任务\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"每月领取大会员漫画权益\"】---\r\n\r\nℹ 目标领取日期为1号,今天是25号,跳过领取任务\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ"; + // //var msg4 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"投币\"】---\r\n\r\nℹ 今日已投5枚硬币,已完成投币任务,不需要再投啦~\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"漫画签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心银瓜子兑换硬币\"】---\r\n\r\nℹ 银瓜子兑换硬币失败,原因:\"银瓜子余额不足\"\r\n\r\nℹ 当前银瓜子余额: 564\r\n\r\nℹ 当前硬币余额: 672.4\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; + // //var msg5 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"投币\"】---\r\n\r\nℹ 今日已投5枚硬币,已完成投币任务,不需要再投啦~\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"漫画签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"直播中心签到\"】---\r\n\r\nℹ 今日已签到过,无法重复签到\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; + // //var msg6 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"投币\"】---\r\n\r\nℹ 今日已投5枚硬币,已完成投币任务,不需要再投啦~\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; + // //var msg7 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\nℹ ---开始【\"观看、分享视频\"】---\r\n\r\nℹ 今天已经观看过了,不需要再看啦\r\n\r\nℹ 今天已经分享过了,不要再分享啦\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; + // var msg8 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\nℹ 距离升级到Lv6还有: 261天\r\n\r\nℹ ---结束---\r\n\r\n\r\n"; + // //var msg9 = "ℹ 版本号:\"1.0.18\"\r\n\r\nℹ 开源地址:\"https://github.com/RayWangQvQ/BiliBiliTool\"\r\n\r\nℹ 当前环境:\"Development\" \r\n\r\n\r\nℹ -----开始每日任务-----\r\n\r\n\r\nℹ ---开始【\"登录\"】---\r\n\r\nℹ 登录成功,用户名: \"在*楼\"\r\n\r\nℹ 硬币余额: 672.4\r\n\r\n"; - CoolPushApiClient client = new CoolPushApiClient(_key); - var result = client.PushMessage(msg8); - Debug.WriteLine(result.Content.ReadAsStringAsync().Result); - } + // CoolPushApiClient client = new CoolPushApiClient(_key); + // var result = client.PushMessage(msg8); + // Debug.WriteLine(result.Content.ReadAsStringAsync().Result); + //} } } diff --git a/test/LogTest/TestDingTalk.cs b/test/LogTest/TestDingTalk.cs index 2931afc78..e59c93518 100644 --- a/test/LogTest/TestDingTalk.cs +++ b/test/LogTest/TestDingTalk.cs @@ -20,7 +20,7 @@ public class TestDingTalk public TestDingTalk() { Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development"); - Program.CreateHost(new string[] { }); + Program.CreateHost(new string[] { "ENVIRONMENT=Development" }); _key = Global.ConfigurationRoot["Serilog:WriteTo:5:Args:webHookUrl"]; } @@ -30,9 +30,10 @@ public void Test2() { var client = new DingTalkApiClient(_key); + var title = "这是标题"; var msg = LogConstants.Msg2 + "开始推送"; - var result = client.PushMessage(msg); + var result = client.PushMessage(msg, title); Debug.WriteLine(result.Content.ReadAsStringAsync().Result); } } diff --git a/test/BiliAgentTest/LiveApiTest.cs b/test/Ray.BiliBiliTool.Agent.FunctionalTests/LiveApiTest.cs similarity index 97% rename from test/BiliAgentTest/LiveApiTest.cs rename to test/Ray.BiliBiliTool.Agent.FunctionalTests/LiveApiTest.cs index 6aabd4b27..320c24cf7 100644 --- a/test/BiliAgentTest/LiveApiTest.cs +++ b/test/Ray.BiliBiliTool.Agent.FunctionalTests/LiveApiTest.cs @@ -11,6 +11,7 @@ using Ray.BiliBiliTool.Infrastructure.Cookie; using Xunit; using Ray.BiliBiliTool.Agent.BiliBiliAgent.Services; +using FluentAssertions; namespace BiliAgentTest { @@ -116,11 +117,15 @@ public void WearMedalWall_Normal_Success() var biliCookie = scope.ServiceProvider.GetRequiredService(); // 猫雷粉丝牌 - var request = new WearMedalWallRequest(biliCookie.BiliJct, 365421); + var request = new WearMedalWallRequest(biliCookie.BiliJct, 365421); //todo BiliApiResponse re = api.WearMedalWall(request).Result; Assert.True(re.Code == 0); + re.Code.Should().BeOneOf( + 0, + 1500005 + ); } [Fact] From 6161d06710a140c14758b22cf0a956dbb6c13ad8 Mon Sep 17 00:00:00 2001 From: Polaris_cn Date: Tue, 23 Jul 2024 20:19:40 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E7=9B=B4=E6=92=AD=E4=BA=B2=E5=AF=86?= =?UTF-8?q?=E5=BA=A6=E8=8E=B7=E5=8F=96=E8=A7=84=E5=88=99=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dtos/Live/GetLiveRoomInfoResponse.cs | 4 +- .../Options/LiveFansMedalTaskOptions.cs | 19 +++ .../LiveDomainService.cs | 133 +++++++++++------- 3 files changed, 104 insertions(+), 52 deletions(-) diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Live/GetLiveRoomInfoResponse.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Live/GetLiveRoomInfoResponse.cs index 9a2a42e1a..c69e5f308 100644 --- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Live/GetLiveRoomInfoResponse.cs +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Live/GetLiveRoomInfoResponse.cs @@ -14,6 +14,8 @@ public class GetLiveRoomInfoResponse public long Parent_area_id { get; set; } + public int Live_Status { get; set; } + public long Uid { get; set; } } -} +} \ No newline at end of file diff --git a/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs b/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs index 88abea4c3..0e60cc608 100644 --- a/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs +++ b/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs @@ -35,5 +35,24 @@ public class LiveFansMedalTaskOptions //public const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"; public const int HeartBeatInterval = 60; + + /// + /// 点赞次数 + /// + public int LikeNumber { get; set; } = 55; + + /// + /// 点赞发送失败多少次时放弃 + /// + public int LikeGiveUpThreshold { get; set; } = 5; + + /// + /// 发送弹幕次数 + /// + public int SendDanmakuNumber { get; set; } = 15; + /// + /// 弹幕发送失败多少次时放弃 + /// + public int SendDanmakugiveUpThreshold { get; set; } = 5; } } diff --git a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs index 7acdc3ec3..91cc26e68 100644 --- a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs +++ b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs @@ -59,7 +59,6 @@ public LiveDomainService(ILogger logger, _securityOptions = securityOptions.CurrentValue; _wbiService = wbiService; _biliCookie = biliCookie; - } /// @@ -146,6 +145,7 @@ public async Task ExchangeSilver2Coin() } #region 天选时刻抽奖 + /// /// 天选抽奖 /// @@ -183,9 +183,11 @@ public async Task TianXuan() await TryJoinTianXuan(item); } + if (reData.Has_more != 1) break; defaultSort = reData.New_tags.FirstOrDefault()?.Sort_type ?? ""; } + defaultSort = ""; } @@ -223,7 +225,8 @@ public async Task TryJoinTianXuan(ListItemDto target) } //根据配置过滤 - if (!check.AwardNameIsSatisfied(_liveLotteryTaskOptions.IncludeAwardNameList, _liveLotteryTaskOptions.ExcludeAwardNameList)) + if (!check.AwardNameIsSatisfied(_liveLotteryTaskOptions.IncludeAwardNameList, + _liveLotteryTaskOptions.ExcludeAwardNameList)) { _logger.LogDebug("不满足配置的筛选条件,跳过{newLine}", Environment.NewLine); return; @@ -251,10 +254,7 @@ public async Task TryJoinTianXuan(ListItemDto target) var request = new JoinTianXuanRequest { - Id = check.Id, - Gift_id = check.Gift_id, - Gift_num = check.Gift_num, - Csrf = _biliCookie.BiliJct + Id = check.Id, Gift_id = check.Gift_id, Gift_num = check.Gift_num, Csrf = _biliCookie.BiliJct }; var re = await _liveApi.Join(request); if (re.Code == 0) @@ -285,6 +285,7 @@ public async Task GroupFollowing() _logger.LogInformation("未关注主播"); return; } + _logger.LogInformation("【抽奖的主播】{ups}", string.Join(",", _tianXuanFollowed.Select(x => x.Uname))); @@ -321,7 +322,6 @@ public async Task GroupFollowing() } - /// /// 获取抽奖前最后一个关注的up /// @@ -381,7 +381,8 @@ private async Task GetOrCreateTianXuanGroupId() { _logger.LogInformation("“天选时刻”分组不存在,尝试创建..."); //创建一个 - var createRe = await _relationApi.CreateTag(new CreateTagRequest { Tag = "天选时刻", Csrf = _biliCookie.BiliJct }); + var createRe = + await _relationApi.CreateTag(new CreateTagRequest { Tag = "天选时刻", Csrf = _biliCookie.BiliJct }); groupId = createRe.Data.Tagid; _logger.LogInformation("创建成功"); } @@ -393,27 +394,26 @@ private async Task GetOrCreateTianXuanGroupId() return groupId; } + #endregion public async Task SendDanmakuToFansMedalLive() { if (!await CheckLiveCookie()) return; - (await GetFansMedalInfoList()).ForEach(async info => + var infoList = await GetFansMedalInfoList(); + + foreach (var info in infoList) { var medal = info.MedalInfo; _logger.LogInformation("【直播间】{liveRoomName}", medal.Target_name); _logger.LogInformation("【粉丝牌】{medalName}", medal.Medal_info.Medal_name); - _logger.LogInformation("正在发送弹幕..."); // 通过空间主页信息获取直播间 id var liveHostUserId = medal.Medal_info.Target_id; - var req = new GetSpaceInfoDto() - { - mid = liveHostUserId - }; + var req = new GetSpaceInfoDto() { mid = liveHostUserId }; await _wbiService.SetWridAsync(req); var spaceInfo = await _userInfoApi.GetSpaceInfo(req); @@ -424,21 +424,35 @@ public async Task SendDanmakuToFansMedalLive() return; } + var successCount = 0; + var failedCount = 0; + // 发送弹幕 - var sendResult = await _liveApi.SendLiveDanmuku(new SendLiveDanmukuRequest( - _biliCookie.BiliJct, - spaceInfo.Data.Live_room.Roomid, - _liveFansMedalTaskOptions.DanmakuContent)); - if (sendResult.Code != 0) + while (successCount < _liveFansMedalTaskOptions.SendDanmakuNumber && + failedCount < _liveFansMedalTaskOptions.SendDanmakugiveUpThreshold) { - _logger.LogError("【弹幕发送】失败"); - _logger.LogError("【原因】{message}", sendResult.Message); - return; + await Task.Delay(2000); + + var sendResult = await _liveApi.SendLiveDanmuku(new SendLiveDanmukuRequest( + _biliCookie.BiliJct, + spaceInfo.Data.Live_room.Roomid, + _liveFansMedalTaskOptions.DanmakuContent)); + + if (sendResult.Code != 0) + { + _logger.LogError("【弹幕发送】失败"); + _logger.LogError("【原因】{message}", sendResult.Message); + failedCount++; + } + else + successCount++; } - _logger.LogInformation("【弹幕发送】成功~,你和主播 {name} 的亲密值增加了100!", spaceInfo.Data.Name); - }); + + _logger.LogInformation("【弹幕发送】发送情况:你向主播 {name} 发送弹幕{success}/{total}", spaceInfo.Data.Name, + successCount, successCount + failedCount); + } } public async Task SendHeartBeatToFansMedalLive() @@ -448,7 +462,7 @@ public async Task SendHeartBeatToFansMedalLive() var infoList = new List(); (await GetFansMedalInfoList()).ForEach(medal => infoList.Add(new(medal.RoomId, medal.LiveRoomInfo, new(), 0, 0)) - ); + ); if (infoList.Count == 0) { @@ -460,8 +474,8 @@ public async Task SendHeartBeatToFansMedalLive() while (infoList.Min( info => info.FailedTimes >= _liveFansMedalTaskOptions.HeartBeatSendGiveUpThreshold - ? int.MaxValue : - info.HeartBeatCount) + ? int.MaxValue + : info.HeartBeatCount) < _liveFansMedalTaskOptions.HeartBeatNumber) { foreach (var info in infoList) @@ -473,7 +487,8 @@ public async Task SendHeartBeatToFansMedalLive() var current = Now(); if (current - info.LastBeatTime <= (LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000) { - int sleepTime = (int)((LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000 - (current - info.LastBeatTime)); + int sleepTime = (int)((LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000 - + (current - info.LastBeatTime)); _logger.LogDebug("【休眠】{time} 毫秒", sleepTime); Thread.Sleep(sleepTime); } @@ -494,7 +509,7 @@ public async Task SendHeartBeatToFansMedalLive() _biliCookie.BiliJct, info.RoomInfo.Uid, $"[\"{_biliCookie.LiveBuvid}\",\"{uuid}\"]") - ); + ); } else { @@ -513,7 +528,7 @@ public async Task SendHeartBeatToFansMedalLive() _biliCookie.BiliJct, uuid, $"[\"{_biliCookie.LiveBuvid}\",\"{uuid}\"]") - ); + ); } info.LastBeatTime = Now(); @@ -548,19 +563,35 @@ public async Task LikeFansMedalLive() { if (!await CheckLiveCookie()) return; - (await GetFansMedalInfoList()).ForEach(async info => + var infoList = await GetFansMedalInfoList(); + infoList = infoList.FindAll(info => info.LiveRoomInfo.Live_Status != 1); + + foreach (var info in infoList) { - var result = await _liveApi.LikeLiveRoom(new LikeLiveRoomRequest(info.RoomId, _biliCookie.BiliJct)); - if (result.Code == 0) + var successCount = 0; + var failedCount = 0; + while (successCount < _liveFansMedalTaskOptions.LikeNumber && + failedCount < _liveFansMedalTaskOptions.LikeGiveUpThreshold) { - _logger.LogInformation("【点赞直播间】{roomId} 完成", info.RoomId); - } - else - { - _logger.LogError("【点赞直播间】{roomId} 时候出现错误", info.RoomId); - _logger.LogError("【原因】{message}", result.Message); + var result = await _liveApi.LikeLiveRoom(new LikeLiveRoomRequest(info.RoomId, _biliCookie.BiliJct)); + if (result.Code == 0) + { + // _logger.LogInformation("【点赞直播间】{roomId} 完成", info.RoomId); + successCount++; + } + else + { + _logger.LogError("【点赞直播间】{roomId} 时候出现错误", info.RoomId); + _logger.LogError("【原因】{message}", result.Message); + failedCount++; + } + + await Task.Delay(500); } - }); + + _logger.LogInformation("【点赞直播间】{romeId}完成情况:{success}/{total}", info.RoomId, successCount, + failedCount + successCount); + } } private async Task> GetFansMedalInfoList() @@ -587,11 +618,8 @@ private async Task> GetFansMedalInfoList() // 通过空间主页信息获取直播间 id var liveHostUserId = medal.Medal_info.Target_id; - var req = new GetSpaceInfoDto() - { - mid = liveHostUserId - }; - await _wbiService.SetWridAsync(req); + var req = new GetSpaceInfoDto() { mid = liveHostUserId }; + await _wbiService.SetWridAsync(req); var spaceInfo = await _userInfoApi.GetSpaceInfo(req); if (spaceInfo.Code != 0) @@ -604,11 +632,11 @@ private async Task> GetFansMedalInfoList() // 用以排除有牌子无直播间的up主 if (spaceInfo.Data.Live_room is null) { - _logger.LogInformation("【主播】{name} 直播间id获取失败,已跳过",medal.Target_name); + _logger.LogInformation("【主播】{name} 直播间id获取失败,已跳过", medal.Target_name); continue; } - - + + var roomId = spaceInfo.Data.Live_room.Roomid; // 获取直播间详细信息 @@ -643,13 +671,15 @@ private async Task CheckLiveCookie() // 请求主播主页来正确配置 cookie var liveHome = await _liveApi.GetLiveHome(); - var liveHomeContent = JsonConvert.DeserializeObject(await liveHome.Content.ReadAsStringAsync()); + var liveHomeContent = + JsonConvert.DeserializeObject(await liveHome.Content.ReadAsStringAsync()); if (liveHomeContent.Code != 0) { throw new Exception(liveHomeContent.Message); } - List liveCookies = liveHome.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value.ToList(); + List liveCookies = liveHome.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value + .ToList(); _biliCookie.MergeCurrentCookie(liveCookies); _logger.LogDebug("LiveBuvid {value}", _biliCookie.LiveBuvid); @@ -661,7 +691,8 @@ private async Task CheckLiveCookie() _logger.LogError("【原因】{message}", exception.Message); return false; } + return true; } } -} +} \ No newline at end of file From 03b869e9f1478327d2f0bc7a5883e9aa94f257c3 Mon Sep 17 00:00:00 2001 From: Polaris_cn Date: Mon, 29 Jul 2024 21:49:06 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E7=9B=B4=E6=92=AD=E9=97=B4=E7=82=B9?= =?UTF-8?q?=E8=B5=9EApi=E7=9B=B8=E5=85=B3=E5=8F=82=E6=95=B0=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E5=BE=85=E6=B5=8B=E8=AF=95=E6=9C=89=E6=95=88?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dtos/Live/LikeLiveRoomRequest.cs | 24 ++++++++-- .../BiliBiliAgent/Interfaces/ILiveApi.cs | 6 +-- .../Options/LiveFansMedalTaskOptions.cs | 10 ++-- .../LiveDomainService.cs | 47 +++++++++---------- 4 files changed, 49 insertions(+), 38 deletions(-) diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Live/LikeLiveRoomRequest.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Live/LikeLiveRoomRequest.cs index e7515ac31..18001fe40 100644 --- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Live/LikeLiveRoomRequest.cs +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Live/LikeLiveRoomRequest.cs @@ -8,16 +8,32 @@ namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Live { public class LikeLiveRoomRequest { - public LikeLiveRoomRequest(long roomid, string csrf) + public LikeLiveRoomRequest(long roomid, string csrf, int clickTime, long anchorId, string uid) { Roomid = roomid; - Csrf= csrf; + Csrf = csrf; + Click_Time = clickTime; + Anchor_Id = anchorId; + Uid = uid; } public long Roomid { get; set; } public string Csrf { get; set; } - public string Csrf_token => Csrf; + public string Csrf_Token => Csrf; + + public int Click_Time { get; set; } + + public long Anchor_Id { get; set; } + + public string Uid { get; set; } + + + public string RawTextBuild() + { + return + $"click_time={Click_Time.ToString()}&room_id={Roomid.ToString()}&uid={Uid}&anchor_id={Anchor_Id}&csrf_token={Csrf_Token}&csrf={Csrf}"; + } } -} +} \ No newline at end of file diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveApi.cs index 0db0ae863..02c0fc52a 100644 --- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveApi.cs +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveApi.cs @@ -144,8 +144,8 @@ public interface ILiveApi : IBiliBiliApi /// /// 点赞直播间 /// - [HttpPost("/xlive/web-ucenter/v1/interact/likeInteract")] + [HttpPost("/xlive/app-ucenter/v1/like_info_v3/like/likeReportV3")] [Header("Referer", "https://live.bilibili.com/")] [Header("Origin", "https://live.bilibili.com")] - Task LikeLiveRoom([FormContent] LikeLiveRoomRequest request); -} + Task LikeLiveRoom([RawFormContent] string request); +} \ No newline at end of file diff --git a/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs b/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs index 0e60cc608..0e5a7eb82 100644 --- a/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs +++ b/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs @@ -39,20 +39,16 @@ public class LiveFansMedalTaskOptions /// /// 点赞次数 /// - public int LikeNumber { get; set; } = 55; - - /// - /// 点赞发送失败多少次时放弃 - /// - public int LikeGiveUpThreshold { get; set; } = 5; + public int LikeNumber { get; set; } = 50; /// /// 发送弹幕次数 /// public int SendDanmakuNumber { get; set; } = 15; + /// /// 弹幕发送失败多少次时放弃 /// public int SendDanmakugiveUpThreshold { get; set; } = 5; } -} +} \ No newline at end of file diff --git a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs index 91cc26e68..8863269fe 100644 --- a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs +++ b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs @@ -432,8 +432,6 @@ public async Task SendDanmakuToFansMedalLive() while (successCount < _liveFansMedalTaskOptions.SendDanmakuNumber && failedCount < _liveFansMedalTaskOptions.SendDanmakugiveUpThreshold) { - await Task.Delay(2000); - var sendResult = await _liveApi.SendLiveDanmuku(new SendLiveDanmukuRequest( _biliCookie.BiliJct, spaceInfo.Data.Live_room.Roomid, @@ -447,6 +445,9 @@ public async Task SendDanmakuToFansMedalLive() } else successCount++; + + var delay = new Random().Next(2000, 4000); + await Task.Delay(delay); } @@ -559,38 +560,36 @@ public async Task SendHeartBeatToFansMedalLive() _logger.LogInformation("【直播观看时长】完成情况:{success}/{total} ", successCount, infoList.Count); } + /// + /// 点赞直播间 + /// public async Task LikeFansMedalLive() { if (!await CheckLiveCookie()) return; var infoList = await GetFansMedalInfoList(); - infoList = infoList.FindAll(info => info.LiveRoomInfo.Live_Status != 1); - + infoList = infoList.FindAll(info => info.LiveRoomInfo.Live_Status != 0); + _logger.LogInformation("当前开播直播间数量:{num}", infoList.Count); foreach (var info in infoList) { - var successCount = 0; - var failedCount = 0; - while (successCount < _liveFansMedalTaskOptions.LikeNumber && - failedCount < _liveFansMedalTaskOptions.LikeGiveUpThreshold) - { - var result = await _liveApi.LikeLiveRoom(new LikeLiveRoomRequest(info.RoomId, _biliCookie.BiliJct)); - if (result.Code == 0) - { - // _logger.LogInformation("【点赞直播间】{roomId} 完成", info.RoomId); - successCount++; - } - else - { - _logger.LogError("【点赞直播间】{roomId} 时候出现错误", info.RoomId); - _logger.LogError("【原因】{message}", result.Message); - failedCount++; - } + // Clike_Time 暂时设置为等于设置的LikeNumber,不清楚是否会被风控,我自己抓包最大值为10 + var request = new LikeLiveRoomRequest(info.RoomId, _biliCookie.BiliJct, + _liveFansMedalTaskOptions.LikeNumber, + info.LiveRoomInfo.Uid, _biliCookie.UserId); - await Task.Delay(500); + var result = await _liveApi.LikeLiveRoom(request.RawTextBuild()); + if (result.Code == 0) + { + _logger.LogInformation("【点赞直播间】{roomId} 完成", info.RoomId); + } + else + { + _logger.LogError("【点赞直播间】{roomId} 时候出现错误", info.RoomId); + _logger.LogError("【原因】{message}", result.Message); } - _logger.LogInformation("【点赞直播间】{romeId}完成情况:{success}/{total}", info.RoomId, successCount, - failedCount + successCount); + var delay = new Random().Next(5000, 8000); + await Task.Delay(delay); } } From faf438006088fc364647c678b6cb40685865b7b4 Mon Sep 17 00:00:00 2001 From: Polaris_cn Date: Mon, 5 Aug 2024 23:16:44 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E6=A0=B9=E6=8D=AEB=E7=AB=99=E6=9C=80?= =?UTF-8?q?=E6=96=B0=E4=BA=B2=E5=AF=86=E5=BA=A6=E8=A7=84=E5=88=99=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Options/LiveFansMedalTaskOptions.cs | 8 ++++---- src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs b/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs index 0e5a7eb82..3581df1fc 100644 --- a/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs +++ b/src/Ray.BiliBiliTool.Config/Options/LiveFansMedalTaskOptions.cs @@ -37,18 +37,18 @@ public class LiveFansMedalTaskOptions public const int HeartBeatInterval = 60; /// - /// 点赞次数 + /// 点赞次数,默认值为30(用于点亮粉丝勋章) /// - public int LikeNumber { get; set; } = 50; + public int LikeNumber { get; set; } = 30; /// /// 发送弹幕次数 /// - public int SendDanmakuNumber { get; set; } = 15; + public int SendDanmakuNumber { get; set; } = 1; /// /// 弹幕发送失败多少次时放弃 /// - public int SendDanmakugiveUpThreshold { get; set; } = 5; + public int SendDanmakugiveUpThreshold { get; set; } = 3; } } \ No newline at end of file diff --git a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs index 8863269fe..704e93d89 100644 --- a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs +++ b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs @@ -461,7 +461,7 @@ public async Task SendHeartBeatToFansMedalLive() if (!await CheckLiveCookie()) return; var infoList = new List(); - (await GetFansMedalInfoList()).ForEach(medal => + (await GetFansMedalInfoList()).FindAll(info => info.LiveRoomInfo.Live_Status != 0).ForEach(medal => infoList.Add(new(medal.RoomId, medal.LiveRoomInfo, new(), 0, 0)) ); From a890c5738f678d7d86c44c6097ab8454b85606fd Mon Sep 17 00:00:00 2001 From: liuweiqing Date: Thu, 8 Aug 2024 08:42:38 +0800 Subject: [PATCH 07/10] =?UTF-8?q?fix:=20=E5=8E=BB=E6=8E=89=E4=BA=86?= =?UTF-8?q?=E5=A4=9A=E5=87=BA=E7=9A=84cd=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/runInLocal.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/runInLocal.md b/docs/runInLocal.md index e7d3ed0df..c45da5b27 100644 --- a/docs/runInLocal.md +++ b/docs/runInLocal.md @@ -42,7 +42,7 @@ P.S.这里的运行环境指的是 `.NET Runtime 6.0.0` ,安装方法可详见 ``` wget https://github.com/RayWangQvQ/BiliBiliToolPro/releases/download/0.3.1/bilibili-tool-pro-v0.3.1-linux-x64.zip unzip bilibili-tool-pro-v0.3.1-linux-x64.zip -cd cd ./linux-x64/ +cd ./linux-x64/ ./Ray.BiliBiliTool.Console --runTasks=Login ``` From 6417962a8b052b3ec32867b5877564c2fd692439 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 24 Dec 2024 22:54:54 +0800 Subject: [PATCH 08/10] fix null reference --- CHANGELOG.md | 2 + common.props | 2 +- .../LiveDomainService.cs | 1089 +++++++++-------- 3 files changed, 548 insertions(+), 545 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d118ecca..cc29e47c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## 2.1.3 +- Code refactory ## 2.1.2 - Feature: enhancement CICD scripts - Fix[#728]: compatible with qinglong history versions diff --git a/common.props b/common.props index 34810691c..e3a3f38b0 100644 --- a/common.props +++ b/common.props @@ -1,7 +1,7 @@ Ray - 2.1.2 + 2.1.3 $(NoWarn);CS1591;CS0436 diff --git a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs index 704e93d89..93e438fff 100644 --- a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs +++ b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs @@ -15,683 +15,684 @@ using Ray.BiliBiliTool.Config.Options; using Ray.BiliBiliTool.DomainService.Dtos; using Ray.BiliBiliTool.DomainService.Interfaces; -using Ray.BiliBiliTool.Infrastructure.Cookie; -namespace Ray.BiliBiliTool.DomainService +namespace Ray.BiliBiliTool.DomainService; + +/// +/// 直播 +/// +public class LiveDomainService : ILiveDomainService { + private readonly ILogger _logger; + private readonly ILiveApi _liveApi; + private readonly IRelationApi _relationApi; + private readonly ILiveTraceApi _liveTraceApi; + private readonly IUserInfoApi _userInfoApi; + private readonly LiveLotteryTaskOptions _liveLotteryTaskOptions; + private readonly LiveFansMedalTaskOptions _liveFansMedalTaskOptions; + private readonly DailyTaskOptions _dailyTaskOptions; + private readonly SecurityOptions _securityOptions; + private readonly BiliCookie _biliCookie; + private readonly IWbiService _wbiService; + + public LiveDomainService(ILogger logger, + ILiveApi liveApi, + IRelationApi relationApi, + ILiveTraceApi liveTraceApi, + IUserInfoApi userInfoApi, + IOptionsMonitor dailyTaskOptions, + IOptionsMonitor liveLotteryTaskOptions, + IOptionsMonitor liveFansMedalTaskOptions, + IOptionsMonitor securityOptions, + IWbiService wbiService, + BiliCookie biliCookie) + { + _logger = logger; + _liveApi = liveApi; + _relationApi = relationApi; + _liveTraceApi = liveTraceApi; + _userInfoApi = userInfoApi; + _liveLotteryTaskOptions = liveLotteryTaskOptions.CurrentValue; + _dailyTaskOptions = dailyTaskOptions.CurrentValue; + _liveFansMedalTaskOptions = liveFansMedalTaskOptions.CurrentValue; + _securityOptions = securityOptions.CurrentValue; + _wbiService = wbiService; + _biliCookie = biliCookie; + } + /// - /// 直播 + /// 本次通过天选关注的主播 /// - public class LiveDomainService : ILiveDomainService - { - private readonly ILogger _logger; - private readonly ILiveApi _liveApi; - private readonly IRelationApi _relationApi; - private readonly ILiveTraceApi _liveTraceApi; - private readonly IUserInfoApi _userInfoApi; - private readonly LiveLotteryTaskOptions _liveLotteryTaskOptions; - private readonly LiveFansMedalTaskOptions _liveFansMedalTaskOptions; - private readonly DailyTaskOptions _dailyTaskOptions; - private readonly SecurityOptions _securityOptions; - private readonly BiliCookie _biliCookie; - private readonly IWbiService _wbiService; - - public LiveDomainService(ILogger logger, - ILiveApi liveApi, - IRelationApi relationApi, - ILiveTraceApi liveTraceApi, - IUserInfoApi userInfoApi, - IOptionsMonitor dailyTaskOptions, - IOptionsMonitor liveLotteryTaskOptions, - IOptionsMonitor liveFansMedalTaskOptions, - IOptionsMonitor securityOptions, - IWbiService wbiService, - BiliCookie biliCookie) - { - _logger = logger; - _liveApi = liveApi; - _relationApi = relationApi; - _liveTraceApi = liveTraceApi; - _userInfoApi = userInfoApi; - _liveLotteryTaskOptions = liveLotteryTaskOptions.CurrentValue; - _dailyTaskOptions = dailyTaskOptions.CurrentValue; - _liveFansMedalTaskOptions = liveFansMedalTaskOptions.CurrentValue; - _securityOptions = securityOptions.CurrentValue; - _wbiService = wbiService; - _biliCookie = biliCookie; - } + private List _tianXuanFollowed = new(); - /// - /// 本次通过天选关注的主播 - /// - private List _tianXuanFollowed = new(); + /// + /// 开始抽奖前最后一个关注的up + /// + private long _lastFollowUpId; - /// - /// 开始抽奖前最后一个关注的up - /// - private long _lastFollowUpId; + /// + /// 直播签到 + /// + public async Task LiveSign() + { + var response = await _liveApi.Sign(); - /// - /// 直播签到 - /// - public async Task LiveSign() + if (response.Code == 0) { - var response = await _liveApi.Sign(); - - if (response.Code == 0) - { - _logger.LogInformation("【签到结果】成功"); - _logger.LogInformation("【本次获取】{text},{special}", response.Data.Text, response.Data.SpecialText); - } - else - { - _logger.LogInformation("【签到结果】失败"); - _logger.LogInformation("【原因】{msg}", response.Message); - } + _logger.LogInformation("【签到结果】成功"); + _logger.LogInformation("【本次获取】{text},{special}", response.Data.Text, response.Data.SpecialText); } - - /// - /// 直播中心银瓜子兑换B币 - /// - /// 兑换银瓜子后硬币余额 - public async Task ExchangeSilver2Coin() + else { - var result = false; + _logger.LogInformation("【签到结果】失败"); + _logger.LogInformation("【原因】{msg}", response.Message); + } + } - if (_dailyTaskOptions.DayOfExchangeSilver2Coin == 0) - { - _logger.LogInformation("已配置为关闭,跳过"); - return false; - } + /// + /// 直播中心银瓜子兑换B币 + /// + /// 兑换银瓜子后硬币余额 + public async Task ExchangeSilver2Coin() + { + var result = false; - int targetDay = _dailyTaskOptions.DayOfExchangeSilver2Coin == -2 - ? DateTime.Today.Day - : _dailyTaskOptions.DayOfExchangeSilver2Coin == -1 - ? DateTime.Today.LastDayOfMonth().Day - : _dailyTaskOptions.DayOfExchangeSilver2Coin; + if (_dailyTaskOptions.DayOfExchangeSilver2Coin == 0) + { + _logger.LogInformation("已配置为关闭,跳过"); + return false; + } - _logger.LogInformation("【目标兑换日期】{targetDay}号", targetDay); - _logger.LogInformation("【今天】{day}号", DateTime.Today.Day); + int targetDay = _dailyTaskOptions.DayOfExchangeSilver2Coin == -2 + ? DateTime.Today.Day + : _dailyTaskOptions.DayOfExchangeSilver2Coin == -1 + ? DateTime.Today.LastDayOfMonth().Day + : _dailyTaskOptions.DayOfExchangeSilver2Coin; - if (DateTime.Today.Day != targetDay) - { - _logger.LogInformation("跳过"); - return false; - } + _logger.LogInformation("【目标兑换日期】{targetDay}号", targetDay); + _logger.LogInformation("【今天】{day}号", DateTime.Today.Day); - BiliApiResponse queryStatus = await _liveApi.GetLiveWalletStatus(); - _logger.LogInformation("【银瓜子余额】 {silver}", queryStatus.Data.Silver); - _logger.LogInformation("【硬币余额】 {coin}", queryStatus.Data.Coin); - _logger.LogInformation("【今日剩余兑换次数】 {left}", queryStatus.Data.Silver_2_coin_left); + if (DateTime.Today.Day != targetDay) + { + _logger.LogInformation("跳过"); + return false; + } - if (queryStatus.Data.Silver_2_coin_left <= 0) return false; + BiliApiResponse queryStatus = await _liveApi.GetLiveWalletStatus(); + _logger.LogInformation("【银瓜子余额】 {silver}", queryStatus.Data.Silver); + _logger.LogInformation("【硬币余额】 {coin}", queryStatus.Data.Coin); + _logger.LogInformation("【今日剩余兑换次数】 {left}", queryStatus.Data.Silver_2_coin_left); - _logger.LogInformation("开始尝试兑换..."); - Silver2CoinRequest request = new(_biliCookie.BiliJct); - var response = await _liveApi.Silver2Coin(request); - if (response.Code == 0) - { - result = true; - _logger.LogInformation("【兑换结果】成功兑换 {coin} 枚硬币", response.Data.Coin); - _logger.LogInformation("【银瓜子余额】 {silver}", response.Data.Silver); - } - else - { - _logger.LogInformation("【兑换结果】失败"); - _logger.LogInformation("【原因】{reason}", response.Message); - } + if (queryStatus.Data.Silver_2_coin_left <= 0) return false; - return result; + _logger.LogInformation("开始尝试兑换..."); + Silver2CoinRequest request = new(_biliCookie.BiliJct); + var response = await _liveApi.Silver2Coin(request); + if (response.Code == 0) + { + result = true; + _logger.LogInformation("【兑换结果】成功兑换 {coin} 枚硬币", response.Data.Coin); + _logger.LogInformation("【银瓜子余额】 {silver}", response.Data.Silver); } - - #region 天选时刻抽奖 - - /// - /// 天选抽奖 - /// - public async Task TianXuan() + else { - _tianXuanFollowed = new List(); - - if (_liveLotteryTaskOptions.AutoGroupFollowings) - { - //获取此时最后一个关注的up,此后再新增的关注,与参与成功的抽奖,取交集,就是本地新增的天选关注 - _lastFollowUpId = await GetLastFollowUpId(); - } - - //获取直播的分区 - List areaList = (await _liveApi.GetAreaList()).Data.Data; + _logger.LogInformation("【兑换结果】失败"); + _logger.LogInformation("【原因】{reason}", response.Message); + } - //遍历分区 - int count = 0; - foreach (var area in areaList) - { - _logger.LogInformation("【扫描分区】{area}...{newLine}", area.Name, Environment.NewLine); + return result; + } - string defaultSort = ""; - //每个分区下搜索5页 - for (int i = 1; i < 6; i++) - { - var reData = (await _liveApi.GetList(area.Id, i, sortType: defaultSort)).Data; - foreach (var item in reData.List ?? new List()) - { - if (item.Pendant_info == null || item.Pendant_info.Count == 0) continue; - var suc = item.Pendant_info.TryGetValue("2", out var pendant); - if (!suc) continue; - if (pendant.Pendent_id != 504) continue; - count++; - - await TryJoinTianXuan(item); - } - - if (reData.Has_more != 1) break; - defaultSort = reData.New_tags.FirstOrDefault()?.Sort_type ?? ""; - } + #region 天选时刻抽奖 - defaultSort = ""; - } + /// + /// 天选抽奖 + /// + public async Task TianXuan() + { + _tianXuanFollowed = new List(); - if (count == 0) - { - _logger.LogInformation("未搜索到直播间"); - return; - } + if (_liveLotteryTaskOptions.AutoGroupFollowings) + { + //获取此时最后一个关注的up,此后再新增的关注,与参与成功的抽奖,取交集,就是本地新增的天选关注 + _lastFollowUpId = await GetLastFollowUpId(); } - public async Task TryJoinTianXuan(ListItemDto target) - { - _logger.LogDebug("【房间】{name}", target.Title); - try - { - //黑名单 - if (_liveLotteryTaskOptions.DenyUidList.Contains(target.Uid.ToString())) - { - _logger.LogDebug("黑名单,跳过"); - return; - } + //获取直播的分区 + List areaList = (await _liveApi.GetAreaList()).Data.Data; - CheckTianXuanDto check = (await _liveApi.CheckTianXuan(target.Roomid)).Data; + //遍历分区 + int count = 0; + foreach (var area in areaList) + { + _logger.LogInformation("【扫描分区】{area}...{newLine}", area.Name, Environment.NewLine); - if (check == null) + string defaultSort = ""; + //每个分区下搜索5页 + for (int i = 1; i < 6; i++) + { + var reData = (await _liveApi.GetList(area.Id, i, sortType: defaultSort)).Data; + foreach (var item in reData.List ?? new List()) { - _logger.LogDebug("数据异常,跳过"); - return; - } + if (item.Pendant_info == null || item.Pendant_info.Count == 0) continue; + var suc = item.Pendant_info.TryGetValue("2", out var pendant); + if (!suc) continue; + if (pendant.Pendent_id != 504) continue; + count++; - if (check.Status != TianXuanStatus.Enable) - { - _logger.LogDebug("已开奖,跳过{newLine}", Environment.NewLine); - return; + await TryJoinTianXuan(item); } - //根据配置过滤 - if (!check.AwardNameIsSatisfied(_liveLotteryTaskOptions.IncludeAwardNameList, - _liveLotteryTaskOptions.ExcludeAwardNameList)) - { - _logger.LogDebug("不满足配置的筛选条件,跳过{newLine}", Environment.NewLine); - return; - } + if (reData.Has_more != 1) break; + defaultSort = reData.New_tags.FirstOrDefault()?.Sort_type ?? ""; + } - //是否需要赠礼 - if (check.Gift_price > 0) - { - _logger.LogDebug("【赠礼】{gift}", check.GiftDesc); - _logger.LogDebug("需赠送礼物,跳过{newLine}", Environment.NewLine); - return; - } + defaultSort = ""; + } - //条件 - if (check.Require_type != RequireType.None && check.Require_type != RequireType.Follow) - { - _logger.LogDebug("【条件】{text}", check.Require_text); - _logger.LogDebug("要求粉丝勋章,跳过"); - return; - } + if (count == 0) + { + _logger.LogInformation("未搜索到直播间"); + return; + } + } - _logger.LogInformation("【房间】{name}", target.ShortTitle); - _logger.LogInformation("【主播】{name}({id})", target.Uname, target.Uid); - _logger.LogInformation("【奖品】{name}【条件】{text}", check.Award_name, check.Require_text); + public async Task TryJoinTianXuan(ListItemDto target) + { + _logger.LogDebug("【房间】{name}", target.Title); + try + { + //黑名单 + if (_liveLotteryTaskOptions.DenyUidList.Contains(target.Uid.ToString())) + { + _logger.LogDebug("黑名单,跳过"); + return; + } - var request = new JoinTianXuanRequest - { - Id = check.Id, Gift_id = check.Gift_id, Gift_num = check.Gift_num, Csrf = _biliCookie.BiliJct - }; - var re = await _liveApi.Join(request); - if (re.Code == 0) - { - _logger.LogInformation("【抽奖】成功 √{newLine}", Environment.NewLine); - if (check.Require_type == RequireType.Follow) - _tianXuanFollowed.AddIfNotExist(target, x => x.Uid == target.Uid); - return; - } + CheckTianXuanDto check = (await _liveApi.CheckTianXuan(target.Roomid)).Data; - _logger.LogInformation("【抽奖】失败"); - _logger.LogInformation("【原因】{msg}{newLine}", re.Message, Environment.NewLine); - } - catch (Exception ex) + if (check == null) { - _logger.LogWarning("【异常】{msg},{detail}{newLine}", ex.Message, ex, Environment.NewLine); - //ignore + _logger.LogDebug("数据异常,跳过"); + return; } - } - /// - /// 将本次抽奖新增的关注统一转移到指定分组中 - /// - public async Task GroupFollowing() - { - if (!_tianXuanFollowed.Any()) + if (check.Status != TianXuanStatus.Enable) { - _logger.LogInformation("未关注主播"); + _logger.LogDebug("已开奖,跳过{newLine}", Environment.NewLine); return; } - _logger.LogInformation("【抽奖的主播】{ups}", - string.Join(",", _tianXuanFollowed.Select(x => x.Uname))); - - //目标分组up集合 - List targetUps = await GetNeedGroup(); - _logger.LogInformation("【将自动分组】{ups}", - string.Join(",", targetUps.Select(x => x.Uname))); + //根据配置过滤 + if (!check.AwardNameIsSatisfied(_liveLotteryTaskOptions.IncludeAwardNameList, + _liveLotteryTaskOptions.ExcludeAwardNameList)) + { + _logger.LogDebug("不满足配置的筛选条件,跳过{newLine}", Environment.NewLine); + return; + } - if (!targetUps.Any()) + //是否需要赠礼 + if (check.Gift_price > 0) { + _logger.LogDebug("【赠礼】{gift}", check.GiftDesc); + _logger.LogDebug("需赠送礼物,跳过{newLine}", Environment.NewLine); return; } - //目标分组Id - long targetGroupId = await GetOrCreateTianXuanGroupId(); + //条件 + if (check.Require_type != RequireType.None && check.Require_type != RequireType.Follow) + { + _logger.LogDebug("【条件】{text}", check.Require_text); + _logger.LogDebug("要求粉丝勋章,跳过"); + return; + } - //执行批量分组 - var referer = string.Format(RelationApiConstant.CopyReferer, _biliCookie.UserId); - var req = new CopyUserToGroupRequest( - targetUps.Select(x => x.Uid).ToList(), - targetGroupId.ToString(), - _biliCookie.BiliJct); - var re = await _relationApi.CopyUpsToGroup(req, referer); + _logger.LogInformation("【房间】{name}", target.ShortTitle); + _logger.LogInformation("【主播】{name}({id})", target.Uname, target.Uid); + _logger.LogInformation("【奖品】{name}【条件】{text}", check.Award_name, check.Require_text); - if (re.Code == 0) + var request = new JoinTianXuanRequest { - _logger.LogInformation("【分组结果】全部成功"); - } - else + Id = check.Id, + Gift_id = check.Gift_id, + Gift_num = check.Gift_num, + Csrf = _biliCookie.BiliJct + }; + var re = await _liveApi.Join(request); + if (re.Code == 0) { - _logger.LogWarning("【分组结果】失败"); - _logger.LogWarning("【原因】{msg}", re.Message); + _logger.LogInformation("【抽奖】成功 √{newLine}", Environment.NewLine); + if (check.Require_type == RequireType.Follow) + _tianXuanFollowed.AddIfNotExist(target, x => x.Uid == target.Uid); + return; } - } - - /// - /// 获取抽奖前最后一个关注的up - /// - /// - private async Task GetLastFollowUpId() + _logger.LogInformation("【抽奖】失败"); + _logger.LogInformation("【原因】{msg}{newLine}", re.Message, Environment.NewLine); + } + catch (Exception ex) { - var followings = await _relationApi - .GetFollowings(new GetFollowingsRequest(long.Parse(_biliCookie.UserId), FollowingsOrderType.TimeDesc)); - return followings.Data.List.FirstOrDefault()?.Mid ?? 0; + _logger.LogWarning("【异常】{msg},{detail}{newLine}", ex.Message, ex, Environment.NewLine); + //ignore } + } - /// - /// 获取本次需要自动分组的主播 - /// - /// - private async Task> GetNeedGroup() + /// + /// 将本次抽奖新增的关注统一转移到指定分组中 + /// + public async Task GroupFollowing() + { + if (!_tianXuanFollowed.Any()) { - List addUpIds = new(); + _logger.LogInformation("未关注主播"); + return; + } - //获取最后一个upId之后关注的所有upId - var followings = await _relationApi - .GetFollowings(new GetFollowingsRequest(long.Parse(_biliCookie.UserId), FollowingsOrderType.TimeDesc)); + _logger.LogInformation("【抽奖的主播】{ups}", + string.Join(",", _tianXuanFollowed.Select(x => x.Uname))); - foreach (UpInfo item in followings.Data.List) - { - if (item.Mid == _lastFollowUpId) - { - break; - } + //目标分组up集合 + List targetUps = await GetNeedGroup(); + _logger.LogInformation("【将自动分组】{ups}", + string.Join(",", targetUps.Select(x => x.Uname))); - addUpIds.Add(item.Mid); - } + if (!targetUps.Any()) + { + return; + } - //和成功抽奖的主播取交集 - List target = new(); - foreach (var listItemDto in _tianXuanFollowed) - { - if (addUpIds.Contains(listItemDto.Uid)) - target.Add(listItemDto); - } + //目标分组Id + long targetGroupId = await GetOrCreateTianXuanGroupId(); - return target; - } + //执行批量分组 + var referer = string.Format(RelationApiConstant.CopyReferer, _biliCookie.UserId); + var req = new CopyUserToGroupRequest( + targetUps.Select(x => x.Uid).ToList(), + targetGroupId.ToString(), + _biliCookie.BiliJct); + var re = await _relationApi.CopyUpsToGroup(req, referer); - /// - /// 获取或创建天选时刻分组 - /// - /// - private async Task GetOrCreateTianXuanGroupId() + if (re.Code == 0) { - //获取天选分组Id,没有就创建 - long groupId = 0; - string referer = string.Format(RelationApiConstant.GetTagsReferer, _biliCookie.UserId); - var groups = await _relationApi.GetTags(referer); - var tianXuanGroup = groups.Data.FirstOrDefault(x => x.Name == "天选时刻"); - if (tianXuanGroup == null) - { - _logger.LogInformation("“天选时刻”分组不存在,尝试创建..."); - //创建一个 - var createRe = - await _relationApi.CreateTag(new CreateTagRequest { Tag = "天选时刻", Csrf = _biliCookie.BiliJct }); - groupId = createRe.Data.Tagid; - _logger.LogInformation("创建成功"); - } - else - { - _logger.LogInformation("“天选时刻”分组已存在"); - groupId = tianXuanGroup.Tagid; - } - - return groupId; + _logger.LogInformation("【分组结果】全部成功"); + } + else + { + _logger.LogWarning("【分组结果】失败"); + _logger.LogWarning("【原因】{msg}", re.Message); } + } - #endregion - public async Task SendDanmakuToFansMedalLive() - { - if (!await CheckLiveCookie()) return; + /// + /// 获取抽奖前最后一个关注的up + /// + /// + private async Task GetLastFollowUpId() + { + var followings = await _relationApi + .GetFollowings(new GetFollowingsRequest(long.Parse(_biliCookie.UserId), FollowingsOrderType.TimeDesc)); + return followings.Data.List.FirstOrDefault()?.Mid ?? 0; + } + + /// + /// 获取本次需要自动分组的主播 + /// + /// + private async Task> GetNeedGroup() + { + List addUpIds = new(); - var infoList = await GetFansMedalInfoList(); + //获取最后一个upId之后关注的所有upId + var followings = await _relationApi + .GetFollowings(new GetFollowingsRequest(long.Parse(_biliCookie.UserId), FollowingsOrderType.TimeDesc)); - foreach (var info in infoList) + foreach (UpInfo item in followings.Data.List) + { + if (item.Mid == _lastFollowUpId) { - var medal = info.MedalInfo; + break; + } - _logger.LogInformation("【直播间】{liveRoomName}", medal.Target_name); - _logger.LogInformation("【粉丝牌】{medalName}", medal.Medal_info.Medal_name); - _logger.LogInformation("正在发送弹幕..."); + addUpIds.Add(item.Mid); + } - // 通过空间主页信息获取直播间 id - var liveHostUserId = medal.Medal_info.Target_id; - var req = new GetSpaceInfoDto() { mid = liveHostUserId }; - await _wbiService.SetWridAsync(req); + //和成功抽奖的主播取交集 + List target = new(); + foreach (var listItemDto in _tianXuanFollowed) + { + if (addUpIds.Contains(listItemDto.Uid)) + target.Add(listItemDto); + } - var spaceInfo = await _userInfoApi.GetSpaceInfo(req); - if (spaceInfo.Code != 0) - { - _logger.LogError("【获取直播间信息】失败"); - _logger.LogError("【原因】{message}", spaceInfo.Message); - return; - } + return target; + } - var successCount = 0; - var failedCount = 0; + /// + /// 获取或创建天选时刻分组 + /// + /// + private async Task GetOrCreateTianXuanGroupId() + { + //获取天选分组Id,没有就创建 + long groupId = 0; + string referer = string.Format(RelationApiConstant.GetTagsReferer, _biliCookie.UserId); + var groups = await _relationApi.GetTags(referer); + var tianXuanGroup = groups.Data.FirstOrDefault(x => x.Name == "天选时刻"); + if (tianXuanGroup == null) + { + _logger.LogInformation("“天选时刻”分组不存在,尝试创建..."); + //创建一个 + var createRe = + await _relationApi.CreateTag(new CreateTagRequest { Tag = "天选时刻", Csrf = _biliCookie.BiliJct }); + groupId = createRe.Data.Tagid; + _logger.LogInformation("创建成功"); + } + else + { + _logger.LogInformation("“天选时刻”分组已存在"); + groupId = tianXuanGroup.Tagid; + } - // 发送弹幕 + return groupId; + } - while (successCount < _liveFansMedalTaskOptions.SendDanmakuNumber && - failedCount < _liveFansMedalTaskOptions.SendDanmakugiveUpThreshold) - { - var sendResult = await _liveApi.SendLiveDanmuku(new SendLiveDanmukuRequest( - _biliCookie.BiliJct, - spaceInfo.Data.Live_room.Roomid, - _liveFansMedalTaskOptions.DanmakuContent)); - - if (sendResult.Code != 0) - { - _logger.LogError("【弹幕发送】失败"); - _logger.LogError("【原因】{message}", sendResult.Message); - failedCount++; - } - else - successCount++; - - var delay = new Random().Next(2000, 4000); - await Task.Delay(delay); - } + #endregion + public async Task SendDanmakuToFansMedalLive() + { + if (!await CheckLiveCookie()) return; - _logger.LogInformation("【弹幕发送】发送情况:你向主播 {name} 发送弹幕{success}/{total}", spaceInfo.Data.Name, - successCount, successCount + failedCount); - } - } + var infoList = await GetFansMedalInfoList(); - public async Task SendHeartBeatToFansMedalLive() + foreach (var info in infoList) { - if (!await CheckLiveCookie()) return; + var medal = info.MedalInfo; - var infoList = new List(); - (await GetFansMedalInfoList()).FindAll(info => info.LiveRoomInfo.Live_Status != 0).ForEach(medal => - infoList.Add(new(medal.RoomId, medal.LiveRoomInfo, new(), 0, 0)) - ); + _logger.LogInformation("【直播间】{liveRoomName}", medal.Target_name); + _logger.LogInformation("【粉丝牌】{medalName}", medal.Medal_info.Medal_name); + _logger.LogInformation("正在发送弹幕..."); - if (infoList.Count == 0) + // 通过空间主页信息获取直播间 id + var liveHostUserId = medal.Medal_info.Target_id; + var req = new GetSpaceInfoDto() { mid = liveHostUserId }; + await _wbiService.SetWridAsync(req); + + var spaceInfo = await _userInfoApi.GetSpaceInfo(req); + if (spaceInfo.Code != 0) { - _logger.LogInformation("【直播观看时长】跳过,未检测到符合条件的主播"); + _logger.LogError("【获取直播间信息】失败"); + _logger.LogError("【原因】{message}", spaceInfo.Message); return; } - var Now = () => new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds(); + var successCount = 0; + var failedCount = 0; + + // 发送弹幕 - while (infoList.Min( - info => info.FailedTimes >= _liveFansMedalTaskOptions.HeartBeatSendGiveUpThreshold - ? int.MaxValue - : info.HeartBeatCount) - < _liveFansMedalTaskOptions.HeartBeatNumber) + while (successCount < _liveFansMedalTaskOptions.SendDanmakuNumber && + failedCount < _liveFansMedalTaskOptions.SendDanmakugiveUpThreshold) { - foreach (var info in infoList) + var sendResult = await _liveApi.SendLiveDanmuku(new SendLiveDanmukuRequest( + _biliCookie.BiliJct, + spaceInfo.Data.Live_room.Roomid, + _liveFansMedalTaskOptions.DanmakuContent)); + + if (sendResult.Code != 0) { - // 忽略连续失败超过上限的直播间 - if (info.FailedTimes >= _liveFansMedalTaskOptions.HeartBeatSendGiveUpThreshold) continue; - - string uuid = Guid.NewGuid().ToString(); - var current = Now(); - if (current - info.LastBeatTime <= (LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000) - { - int sleepTime = (int)((LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000 - - (current - info.LastBeatTime)); - _logger.LogDebug("【休眠】{time} 毫秒", sleepTime); - Thread.Sleep(sleepTime); - } - - // Heart Beat 接口 - var timestamp = Now(); - BiliApiResponse heartBeatResult = null; - if (info.HeartBeatCount == 0) - { - heartBeatResult = await _liveTraceApi.EnterRoom( - new EnterRoomRequest( - info.RoomId, - info.RoomInfo.Parent_area_id, - info.RoomInfo.Area_id, - info.HeartBeatCount, - timestamp, - _securityOptions.UserAgent, - _biliCookie.BiliJct, - info.RoomInfo.Uid, - $"[\"{_biliCookie.LiveBuvid}\",\"{uuid}\"]") - ); - } - else - { - heartBeatResult = await _liveTraceApi.HeartBeat( - new HeartBeatRequest( - info.RoomId, - info.RoomInfo.Parent_area_id, - info.RoomInfo.Area_id, - info.HeartBeatCount, - _biliCookie.LiveBuvid, - timestamp, - info.HeartBeatInfo.Timestamp, - _securityOptions.UserAgent, - info.HeartBeatInfo.Secret_rule, - info.HeartBeatInfo.Secret_key, - _biliCookie.BiliJct, - uuid, - $"[\"{_biliCookie.LiveBuvid}\",\"{uuid}\"]") - ); - } - - info.LastBeatTime = Now(); - - if (heartBeatResult != null && heartBeatResult.Data != null) - { - info.HeartBeatInfo.Secret_key = heartBeatResult.Data.Secret_key; - info.HeartBeatInfo.Secret_rule = heartBeatResult.Data.Secret_rule; - info.HeartBeatInfo.Timestamp = heartBeatResult.Data.Timestamp; - } - - if (heartBeatResult == null || heartBeatResult.Code != 0) - { - _logger.LogError("【心跳包】直播间 {room} 发送失败", info.RoomId); - _logger.LogError("【原因】{message}", heartBeatResult != null ? heartBeatResult.Message : ""); - info.FailedTimes += 1; - continue; - } - - info.HeartBeatCount += 1; - info.FailedTimes = 0; - - _logger.LogInformation("【直播间】{roomId} 的第 {index} 个心跳包发送成功", info.RoomId, info.HeartBeatCount); + _logger.LogError("【弹幕发送】失败"); + _logger.LogError("【原因】{message}", sendResult.Message); + failedCount++; } + else + successCount++; + + var delay = new Random().Next(2000, 4000); + await Task.Delay(delay); } - var successCount = infoList.Count(info => info.HeartBeatCount >= _liveFansMedalTaskOptions.HeartBeatNumber); - _logger.LogInformation("【直播观看时长】完成情况:{success}/{total} ", successCount, infoList.Count); + + _logger.LogInformation("【弹幕发送】发送情况:你向主播 {name} 发送弹幕{success}/{total}", spaceInfo.Data.Name, + successCount, successCount + failedCount); } + } - /// - /// 点赞直播间 - /// - public async Task LikeFansMedalLive() + public async Task SendHeartBeatToFansMedalLive() + { + if (!await CheckLiveCookie()) return; + + var infoList = new List(); + (await GetFansMedalInfoList()).FindAll(info => info.LiveRoomInfo.Live_Status != 0).ForEach(medal => + infoList.Add(new(medal.RoomId, medal.LiveRoomInfo, new(), 0, 0)) + ); + + if (infoList.Count == 0) { - if (!await CheckLiveCookie()) return; + _logger.LogInformation("【直播观看时长】跳过,未检测到符合条件的主播"); + return; + } - var infoList = await GetFansMedalInfoList(); - infoList = infoList.FindAll(info => info.LiveRoomInfo.Live_Status != 0); - _logger.LogInformation("当前开播直播间数量:{num}", infoList.Count); + var Now = () => new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds(); + + while (infoList.Min( + info => info.FailedTimes >= _liveFansMedalTaskOptions.HeartBeatSendGiveUpThreshold + ? int.MaxValue + : info.HeartBeatCount) + < _liveFansMedalTaskOptions.HeartBeatNumber) + { foreach (var info in infoList) { - // Clike_Time 暂时设置为等于设置的LikeNumber,不清楚是否会被风控,我自己抓包最大值为10 - var request = new LikeLiveRoomRequest(info.RoomId, _biliCookie.BiliJct, - _liveFansMedalTaskOptions.LikeNumber, - info.LiveRoomInfo.Uid, _biliCookie.UserId); + // 忽略连续失败超过上限的直播间 + if (info.FailedTimes >= _liveFansMedalTaskOptions.HeartBeatSendGiveUpThreshold) continue; - var result = await _liveApi.LikeLiveRoom(request.RawTextBuild()); - if (result.Code == 0) + string uuid = Guid.NewGuid().ToString(); + var current = Now(); + if (current - info.LastBeatTime <= (LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000) { - _logger.LogInformation("【点赞直播间】{roomId} 完成", info.RoomId); + int sleepTime = (int)((LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000 - + (current - info.LastBeatTime)); + _logger.LogDebug("【休眠】{time} 毫秒", sleepTime); + Thread.Sleep(sleepTime); } - else + + // Heart Beat 接口 + var timestamp = Now(); + BiliApiResponse heartBeatResult = null; + if (info.HeartBeatCount == 0) { - _logger.LogError("【点赞直播间】{roomId} 时候出现错误", info.RoomId); - _logger.LogError("【原因】{message}", result.Message); + heartBeatResult = await _liveTraceApi.EnterRoom( + new EnterRoomRequest( + info.RoomId, + info.RoomInfo.Parent_area_id, + info.RoomInfo.Area_id, + info.HeartBeatCount, + timestamp, + _securityOptions.UserAgent, + _biliCookie.BiliJct, + info.RoomInfo.Uid, + $"[\"{_biliCookie.LiveBuvid}\",\"{uuid}\"]") + ); } - - var delay = new Random().Next(5000, 8000); - await Task.Delay(delay); - } - } - - private async Task> GetFansMedalInfoList() - { - _logger.LogInformation("【获取直播列表】获取拥有粉丝牌的直播列表"); - var medalWallInfo = await _liveApi.GetMedalWall(_biliCookie.UserId); - - if (medalWallInfo.Code != 0) - { - _logger.LogError("【获取直播列表】失败"); - _logger.LogError("【原因】{message}", medalWallInfo.Message); - return null; - } - - var infoList = new List(); - foreach (var medal in medalWallInfo.Data.List) - { - _logger.LogInformation("【主播】{name} ", medal.Target_name); - if (_liveFansMedalTaskOptions.IsSkipLevel20Medal && medal.Medal_info.Level >= 20) + else { - _logger.LogInformation("粉丝牌等级为 {level},观看将不再增长亲密度,跳过", medal.Medal_info.Level); - continue; + heartBeatResult = await _liveTraceApi.HeartBeat( + new HeartBeatRequest( + info.RoomId, + info.RoomInfo.Parent_area_id, + info.RoomInfo.Area_id, + info.HeartBeatCount, + _biliCookie.LiveBuvid, + timestamp, + info.HeartBeatInfo.Timestamp, + _securityOptions.UserAgent, + info.HeartBeatInfo.Secret_rule, + info.HeartBeatInfo.Secret_key, + _biliCookie.BiliJct, + uuid, + $"[\"{_biliCookie.LiveBuvid}\",\"{uuid}\"]") + ); } - // 通过空间主页信息获取直播间 id - var liveHostUserId = medal.Medal_info.Target_id; - var req = new GetSpaceInfoDto() { mid = liveHostUserId }; - await _wbiService.SetWridAsync(req); + info.LastBeatTime = Now(); - var spaceInfo = await _userInfoApi.GetSpaceInfo(req); - if (spaceInfo.Code != 0) + if (heartBeatResult != null && heartBeatResult.Data != null) { - _logger.LogError("【获取空间信息】失败"); - _logger.LogError("【原因】{message}", spaceInfo.Message); - continue; + info.HeartBeatInfo.Secret_key = heartBeatResult.Data.Secret_key; + info.HeartBeatInfo.Secret_rule = heartBeatResult.Data.Secret_rule; + info.HeartBeatInfo.Timestamp = heartBeatResult.Data.Timestamp; } - // 用以排除有牌子无直播间的up主 - if (spaceInfo.Data.Live_room is null) + if (heartBeatResult == null || heartBeatResult.Code != 0) { - _logger.LogInformation("【主播】{name} 直播间id获取失败,已跳过", medal.Target_name); + _logger.LogError("【心跳包】直播间 {room} 发送失败", info.RoomId); + _logger.LogError("【原因】{message}", heartBeatResult != null ? heartBeatResult.Message : ""); + info.FailedTimes += 1; continue; } + info.HeartBeatCount += 1; + info.FailedTimes = 0; - var roomId = spaceInfo.Data.Live_room.Roomid; + _logger.LogInformation("【直播间】{roomId} 的第 {index} 个心跳包发送成功", info.RoomId, info.HeartBeatCount); + } + } - // 获取直播间详细信息 - var liveRoomInfo = await _liveApi.GetLiveRoomInfo(roomId); - if (liveRoomInfo.Code != 0) - { - _logger.LogError("【获取直播间信息】失败"); - _logger.LogError("【原因】{message}", liveRoomInfo.Message); - continue; - } + var successCount = infoList.Count(info => info.HeartBeatCount >= _liveFansMedalTaskOptions.HeartBeatNumber); + _logger.LogInformation("【直播观看时长】完成情况:{success}/{total} ", successCount, infoList.Count); + } + + /// + /// 点赞直播间 + /// + public async Task LikeFansMedalLive() + { + if (!await CheckLiveCookie()) return; + + var infoList = await GetFansMedalInfoList(); + infoList = infoList.FindAll(info => info.LiveRoomInfo.Live_Status != 0); + _logger.LogInformation("当前开播直播间数量:{num}", infoList.Count); + foreach (var info in infoList) + { + // Clike_Time 暂时设置为等于设置的LikeNumber,不清楚是否会被风控,我自己抓包最大值为10 + var request = new LikeLiveRoomRequest(info.RoomId, _biliCookie.BiliJct, + _liveFansMedalTaskOptions.LikeNumber, + info.LiveRoomInfo.Uid, _biliCookie.UserId); - infoList.Add(new FansMedalInfoDto(roomId, medal, liveRoomInfo.Data)); + var result = await _liveApi.LikeLiveRoom(request.RawTextBuild()); + if (result.Code == 0) + { + _logger.LogInformation("【点赞直播间】{roomId} 完成", info.RoomId); } + else + { + _logger.LogError("【点赞直播间】{roomId} 时候出现错误", info.RoomId); + _logger.LogError("【原因】{message}", result.Message); + } + + var delay = new Random().Next(5000, 8000); + await Task.Delay(delay); + } + } + + private async Task> GetFansMedalInfoList() + { + _logger.LogInformation("【获取直播列表】获取拥有粉丝牌的直播列表"); + var medalWallInfo = await _liveApi.GetMedalWall(_biliCookie.UserId); - return infoList; + if (medalWallInfo.Code != 0) + { + _logger.LogError("【获取直播列表】失败"); + _logger.LogError("【原因】{message}", medalWallInfo.Message); + return new List(); } - /// - /// 自动配置直播相关 Cookie,来兼容较低版本中保存的 Cookie 配置 - /// - /// - /// bool 成功配置 or not - /// - private async Task CheckLiveCookie() + var infoList = new List(); + foreach (var medal in medalWallInfo.Data.List) { - // 检测 _biliCookie 是否正确配置 - if (!string.IsNullOrWhiteSpace(_biliCookie.LiveBuvid)) return true; + _logger.LogInformation("【主播】{name} ", medal.Target_name); + if (_liveFansMedalTaskOptions.IsSkipLevel20Medal && medal.Medal_info.Level >= 20) + { + _logger.LogInformation("粉丝牌等级为 {level},观看将不再增长亲密度,跳过", medal.Medal_info.Level); + continue; + } - try + // 通过空间主页信息获取直播间 id + var liveHostUserId = medal.Medal_info.Target_id; + var req = new GetSpaceInfoDto() { mid = liveHostUserId }; + await _wbiService.SetWridAsync(req); + + var spaceInfo = await _userInfoApi.GetSpaceInfo(req); + if (spaceInfo.Code != 0) { - _logger.LogInformation("检测到直播 Cookie 未正确配置,尝试自动配置中..."); + _logger.LogError("【获取空间信息】失败"); + _logger.LogError("【原因】{message}", spaceInfo.Message); + continue; + } - // 请求主播主页来正确配置 cookie - var liveHome = await _liveApi.GetLiveHome(); - var liveHomeContent = - JsonConvert.DeserializeObject(await liveHome.Content.ReadAsStringAsync()); - if (liveHomeContent.Code != 0) - { - throw new Exception(liveHomeContent.Message); - } + // 用以排除有牌子无直播间的up主 + if (spaceInfo.Data.Live_room is null) + { + _logger.LogInformation("【主播】{name} 直播间id获取失败,已跳过", medal.Target_name); + continue; + } - List liveCookies = liveHome.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value - .ToList(); - _biliCookie.MergeCurrentCookie(liveCookies); - _logger.LogDebug("LiveBuvid {value}", _biliCookie.LiveBuvid); - _logger.LogInformation("直播 Cookie 配置成功!"); + var roomId = spaceInfo.Data.Live_room.Roomid; + + // 获取直播间详细信息 + var liveRoomInfo = await _liveApi.GetLiveRoomInfo(roomId); + if (liveRoomInfo.Code != 0) + { + _logger.LogError("【获取直播间信息】失败"); + _logger.LogError("【原因】{message}", liveRoomInfo.Message); + continue; } - catch (Exception exception) + + infoList.Add(new FansMedalInfoDto(roomId, medal, liveRoomInfo.Data)); + } + + return infoList; + } + + /// + /// 自动配置直播相关 Cookie,来兼容较低版本中保存的 Cookie 配置 + /// + /// + /// bool 成功配置 or not + /// + private async Task CheckLiveCookie() + { + // 检测 _biliCookie 是否正确配置 + if (!string.IsNullOrWhiteSpace(_biliCookie.LiveBuvid)) return true; + + try + { + _logger.LogInformation("检测到直播 Cookie 未正确配置,尝试自动配置中..."); + + // 请求主播主页来正确配置 cookie + var liveHome = await _liveApi.GetLiveHome(); + var liveHomeContent = + JsonConvert.DeserializeObject(await liveHome.Content.ReadAsStringAsync()); + if (liveHomeContent.Code != 0) { - _logger.LogError("【配置直播Cookie】失败,放弃执行后续任务..."); - _logger.LogError("【原因】{message}", exception.Message); - return false; + throw new Exception(liveHomeContent.Message); } - return true; + List liveCookies = liveHome.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value + .ToList(); + _biliCookie.MergeCurrentCookie(liveCookies); + + _logger.LogDebug("LiveBuvid {value}", _biliCookie.LiveBuvid); + _logger.LogInformation("直播 Cookie 配置成功!"); } + catch (Exception exception) + { + _logger.LogError("【配置直播Cookie】失败,放弃执行后续任务..."); + _logger.LogError("【原因】{message}", exception.Message); + return false; + } + + return true; } } \ No newline at end of file From 36ebfcadece7f052d11882d3359841c237503182 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 24 Dec 2024 23:16:05 +0800 Subject: [PATCH 09/10] fix[#806]:remove live login which was obsolete --- .../DailyTaskAppService.cs | 435 +++++++++--------- test/AppServiceTest/VipServiceTest.cs | 1 - 2 files changed, 210 insertions(+), 226 deletions(-) diff --git a/src/Ray.BiliBiliTool.Application/DailyTaskAppService.cs b/src/Ray.BiliBiliTool.Application/DailyTaskAppService.cs index f7e6ccc84..191c080f2 100644 --- a/src/Ray.BiliBiliTool.Application/DailyTaskAppService.cs +++ b/src/Ray.BiliBiliTool.Application/DailyTaskAppService.cs @@ -12,278 +12,263 @@ using Ray.BiliBiliTool.Config; using Ray.BiliBiliTool.Config.Options; using Ray.BiliBiliTool.DomainService.Interfaces; -using Ray.BiliBiliTool.Infrastructure; -using Ray.BiliBiliTool.Infrastructure.Cookie; using Ray.BiliBiliTool.Infrastructure.Enums; -namespace Ray.BiliBiliTool.Application +namespace Ray.BiliBiliTool.Application; + +public class DailyTaskAppService : AppService, IDailyTaskAppService { - public class DailyTaskAppService : AppService, IDailyTaskAppService + private readonly ILogger _logger; + private readonly IAccountDomainService _accountDomainService; + private readonly IVideoDomainService _videoDomainService; + private readonly IArticleDomainService _articleDomainService; + private readonly IDonateCoinDomainService _donateCoinDomainService; + private readonly IMangaDomainService _mangaDomainService; + private readonly ILiveDomainService _liveDomainService; + private readonly IVipPrivilegeDomainService _vipPrivilegeDomainService; + private readonly IChargeDomainService _chargeDomainService; + private readonly DailyTaskOptions _dailyTaskOptions; + private readonly ICoinDomainService _coinDomainService; + private readonly Dictionary _expDic; + private readonly ILoginDomainService _loginDomainService; + private readonly IConfiguration _configuration; + private readonly BiliCookie _biliCookie; + + public DailyTaskAppService( + ILogger logger, + IOptionsMonitor> dicOptions, + IAccountDomainService accountDomainService, + IVideoDomainService videoDomainService, + IArticleDomainService articleDomainService, + IDonateCoinDomainService donateCoinDomainService, + IMangaDomainService mangaDomainService, + ILiveDomainService liveDomainService, + IVipPrivilegeDomainService vipPrivilegeDomainService, + IChargeDomainService chargeDomainService, + IOptionsMonitor dailyTaskOptions, + ICoinDomainService coinDomainService, + ILoginDomainService loginDomainService, + IConfiguration configuration, + BiliCookie biliCookie) { - private readonly ILogger _logger; - private readonly IAccountDomainService _accountDomainService; - private readonly IVideoDomainService _videoDomainService; - private readonly IArticleDomainService _articleDomainService; - private readonly IDonateCoinDomainService _donateCoinDomainService; - private readonly IMangaDomainService _mangaDomainService; - private readonly ILiveDomainService _liveDomainService; - private readonly IVipPrivilegeDomainService _vipPrivilegeDomainService; - private readonly IChargeDomainService _chargeDomainService; - private readonly DailyTaskOptions _dailyTaskOptions; - private readonly ICoinDomainService _coinDomainService; - private readonly Dictionary _expDic; - private readonly ILoginDomainService _loginDomainService; - private readonly IConfiguration _configuration; - private readonly CookieStrFactory _cookieStrFactory; - private BiliCookie _biliCookie; - - public DailyTaskAppService( - ILogger logger, - IOptionsMonitor> dicOptions, - IAccountDomainService accountDomainService, - IVideoDomainService videoDomainService, - IArticleDomainService articleDomainService, - IDonateCoinDomainService donateCoinDomainService, - IMangaDomainService mangaDomainService, - ILiveDomainService liveDomainService, - IVipPrivilegeDomainService vipPrivilegeDomainService, - IChargeDomainService chargeDomainService, - IOptionsMonitor dailyTaskOptions, - ICoinDomainService coinDomainService, - ILoginDomainService loginDomainService, IConfiguration configuration, - CookieStrFactory cookieStrFactory, - BiliCookie biliCookie) - { - _logger = logger; - _expDic = dicOptions.Get(Constants.OptionsNames.ExpDictionaryName); - _accountDomainService = accountDomainService; - _videoDomainService = videoDomainService; - _articleDomainService = articleDomainService; - _donateCoinDomainService = donateCoinDomainService; - _mangaDomainService = mangaDomainService; - _liveDomainService = liveDomainService; - _vipPrivilegeDomainService = vipPrivilegeDomainService; - _chargeDomainService = chargeDomainService; - _dailyTaskOptions = dailyTaskOptions.CurrentValue; - _coinDomainService = coinDomainService; - _loginDomainService = loginDomainService; - _configuration = configuration; - _cookieStrFactory = cookieStrFactory; - _biliCookie = biliCookie; - } + _logger = logger; + _expDic = dicOptions.Get(Constants.OptionsNames.ExpDictionaryName); + _accountDomainService = accountDomainService; + _videoDomainService = videoDomainService; + _articleDomainService = articleDomainService; + _donateCoinDomainService = donateCoinDomainService; + _mangaDomainService = mangaDomainService; + _liveDomainService = liveDomainService; + _vipPrivilegeDomainService = vipPrivilegeDomainService; + _chargeDomainService = chargeDomainService; + _dailyTaskOptions = dailyTaskOptions.CurrentValue; + _coinDomainService = coinDomainService; + _loginDomainService = loginDomainService; + _configuration = configuration; + _biliCookie = biliCookie; + } - [TaskInterceptor("每日任务", TaskLevel.One)] - public override async Task DoTaskAsync(CancellationToken cancellationToken) - { - await SetCookiesAsync(_biliCookie, cancellationToken); + [TaskInterceptor("每日任务", TaskLevel.One)] + public override async Task DoTaskAsync(CancellationToken cancellationToken = default) + { + await SetCookiesAsync(_biliCookie, cancellationToken); - //每日任务赚经验: - UserInfo userInfo = await Login(); + //每日任务赚经验: + UserInfo userInfo = await Login(); - DailyTaskInfo dailyTaskInfo = await GetDailyTaskStatus(); - await WatchAndShareVideo(dailyTaskInfo); + DailyTaskInfo dailyTaskInfo = await GetDailyTaskStatus(); + await WatchAndShareVideo(dailyTaskInfo); - await AddCoins(userInfo); + await AddCoins(userInfo); - //签到: - await LiveSign(); - await MangaSign(); - await MangaRead(); - await ExchangeSilver2Coin(); + //签到: + await MangaSign(); + await MangaRead(); + await ExchangeSilver2Coin(); - //领福利: - await ReceiveVipPrivilege(userInfo); - await ReceiveMangaVipReward(userInfo); + //领福利: + await ReceiveVipPrivilege(userInfo); + await ReceiveMangaVipReward(userInfo); - await Charge(userInfo); - } + await Charge(userInfo); + } - [TaskInterceptor("Set Cookie", TaskLevel.Two)] - protected async Task SetCookiesAsync(BiliCookie biliCookie, CancellationToken cancellationToken) + [TaskInterceptor("Set Cookie", TaskLevel.Two)] + protected async Task SetCookiesAsync(BiliCookie biliCookie, CancellationToken cancellationToken) + { + //判断cookie是否完整 + if (biliCookie.Buvid.IsNotNullOrEmpty()) { - //判断cookie是否完整 - if (biliCookie.Buvid.IsNotNullOrEmpty()) - { - _logger.LogInformation("Cookie完整,不需要Set Cookie"); - return biliCookie; - } + _logger.LogInformation("Cookie完整,不需要Set Cookie"); + return biliCookie; + } - //Set - _logger.LogInformation("开始Set Cookie"); - var ck = await _loginDomainService.SetCookieAsync(biliCookie, cancellationToken); + //Set + _logger.LogInformation("开始Set Cookie"); + var ck = await _loginDomainService.SetCookieAsync(biliCookie, cancellationToken); - //持久化 - _logger.LogInformation("持久化Cookie"); - await SaveCookieAsync(ck, cancellationToken); + //持久化 + _logger.LogInformation("持久化Cookie"); + await SaveCookieAsync(ck, cancellationToken); - return ck; - } + return ck; + } - /// - /// 登录 - /// - /// - [TaskInterceptor("登录")] - private async Task Login() - { - UserInfo userInfo = await _accountDomainService.LoginByCookie(); - if (userInfo == null) throw new Exception("登录失败,请检查Cookie"); //终止流程 + /// + /// 登录 + /// + /// + [TaskInterceptor("登录")] + private async Task Login() + { + UserInfo userInfo = await _accountDomainService.LoginByCookie(); + if (userInfo == null) throw new Exception("登录失败,请检查Cookie"); //终止流程 - _expDic.TryGetValue("每日登录", out int exp); - _logger.LogInformation("登录成功,经验+{exp} √", exp); + _expDic.TryGetValue("每日登录", out int exp); + _logger.LogInformation("登录成功,经验+{exp} √", exp); - return userInfo; - } + return userInfo; + } - /// - /// 获取任务完成情况 - /// - /// - [TaskInterceptor(null, rethrowWhenException: false)] - private async Task GetDailyTaskStatus() + /// + /// 获取任务完成情况 + /// + /// + [TaskInterceptor(null, rethrowWhenException: false)] + private async Task GetDailyTaskStatus() + { + return await _accountDomainService.GetDailyTaskStatus(); + } + + /// + /// 观看、分享视频 + /// + [TaskInterceptor("观看、分享视频", rethrowWhenException: false)] + private async Task WatchAndShareVideo(DailyTaskInfo dailyTaskInfo) + { + if (!_dailyTaskOptions.IsWatchVideo && !_dailyTaskOptions.IsShareVideo) { - return await _accountDomainService.GetDailyTaskStatus(); + _logger.LogInformation("已配置为关闭,跳过任务"); + return; } - /// - /// 观看、分享视频 - /// - [TaskInterceptor("观看、分享视频", rethrowWhenException: false)] - private async Task WatchAndShareVideo(DailyTaskInfo dailyTaskInfo) - { - if (!_dailyTaskOptions.IsWatchVideo && !_dailyTaskOptions.IsShareVideo) - { - _logger.LogInformation("已配置为关闭,跳过任务"); - return; - } + await _videoDomainService.WatchAndShareVideo(dailyTaskInfo); + } - await _videoDomainService.WatchAndShareVideo(dailyTaskInfo); + /// + /// 投币任务 + /// + [TaskInterceptor("投币", rethrowWhenException: false)] + private async Task AddCoins(UserInfo userInfo) + { + if (_dailyTaskOptions.SaveCoinsWhenLv6 && userInfo.Level_info.Current_level >= 6) + { + _logger.LogInformation("已经为LV6大佬,开始白嫖"); + return; } - /// - /// 投币任务 - /// - [TaskInterceptor("投币", rethrowWhenException: false)] - private async Task AddCoins(UserInfo userInfo) + if (_dailyTaskOptions.IsDonateCoinForArticle) { - if (_dailyTaskOptions.SaveCoinsWhenLv6 && userInfo.Level_info.Current_level >= 6) - { - _logger.LogInformation("已经为LV6大佬,开始白嫖"); - return; - } + _logger.LogInformation("专栏投币已开启"); - if (_dailyTaskOptions.IsDonateCoinForArticle) - { - _logger.LogInformation("专栏投币已开启"); - - if (!await _articleDomainService.AddCoinForArticles()) - { - _logger.LogInformation("专栏投币结束,转入视频投币"); - await _donateCoinDomainService.AddCoinsForVideos(); - } - } - else + if (!await _articleDomainService.AddCoinForArticles()) { + _logger.LogInformation("专栏投币结束,转入视频投币"); await _donateCoinDomainService.AddCoinsForVideos(); } } - - /// - /// 直播中心签到 - /// - [TaskInterceptor("直播签到", rethrowWhenException: false)] - private async Task LiveSign() + else { - await _liveDomainService.LiveSign(); + await _donateCoinDomainService.AddCoinsForVideos(); } + } - /// - /// 直播中心的银瓜子兑换硬币 - /// - [TaskInterceptor("银瓜子兑换硬币", rethrowWhenException: false)] - private async Task ExchangeSilver2Coin() - { - var success = await _liveDomainService.ExchangeSilver2Coin(); - if (!success) return; + /// + /// 直播中心的银瓜子兑换硬币 + /// + [TaskInterceptor("银瓜子兑换硬币", rethrowWhenException: false)] + private async Task ExchangeSilver2Coin() + { + var success = await _liveDomainService.ExchangeSilver2Coin(); + if (!success) return; - //如果兑换成功,则打印硬币余额 - var coinBalance = _coinDomainService.GetCoinBalance(); - _logger.LogInformation("【硬币余额】 {coin}", coinBalance); - } + //如果兑换成功,则打印硬币余额 + var coinBalance = _coinDomainService.GetCoinBalance(); + _logger.LogInformation("【硬币余额】 {coin}", coinBalance); + } - /// - /// 每月领取大会员福利 - /// - [TaskInterceptor("领取大会员福利", rethrowWhenException: false)] - private async Task ReceiveVipPrivilege(UserInfo userInfo) - { - var suc = await _vipPrivilegeDomainService.ReceiveVipPrivilege(userInfo); + /// + /// 每月领取大会员福利 + /// + [TaskInterceptor("领取大会员福利", rethrowWhenException: false)] + private async Task ReceiveVipPrivilege(UserInfo userInfo) + { + var suc = await _vipPrivilegeDomainService.ReceiveVipPrivilege(userInfo); - //如果领取成功,需要刷新账户信息(比如B币余额) - if (suc) + //如果领取成功,需要刷新账户信息(比如B币余额) + if (suc) + { + try { - try - { - userInfo = await _accountDomainService.LoginByCookie(); - } - catch (Exception ex) - { - _logger.LogError("领取福利成功,但之后刷新用户信息时异常,信息:{msg}", ex.Message); - } + userInfo = await _accountDomainService.LoginByCookie(); + } + catch (Exception ex) + { + _logger.LogError("领取福利成功,但之后刷新用户信息时异常,信息:{msg}", ex.Message); } } + } - /// - /// 每月为自己充电 - /// - [TaskInterceptor("B币券充电", rethrowWhenException: false)] - private async Task Charge(UserInfo userInfo) - { - await _chargeDomainService.Charge(userInfo); - } - - /// - /// 漫画签到 - /// - [TaskInterceptor("漫画签到", rethrowWhenException: false)] - private async Task MangaSign() - { - await _mangaDomainService.MangaSign(); - } + /// + /// 每月为自己充电 + /// + [TaskInterceptor("B币券充电", rethrowWhenException: false)] + private async Task Charge(UserInfo userInfo) + { + await _chargeDomainService.Charge(userInfo); + } - /// - /// 漫画阅读 - /// - [TaskInterceptor("漫画阅读", rethrowWhenException: false)] - private async Task MangaRead() - { - await _mangaDomainService.MangaRead(); - } + /// + /// 漫画签到 + /// + [TaskInterceptor("漫画签到", rethrowWhenException: false)] + private async Task MangaSign() + { + await _mangaDomainService.MangaSign(); + } - /// - /// 每月获取大会员漫画权益 - /// - [TaskInterceptor("领取大会员漫画权益", rethrowWhenException: false)] - private async Task ReceiveMangaVipReward(UserInfo userInfo) - { - await _mangaDomainService.ReceiveMangaVipReward(1, userInfo); - } + /// + /// 漫画阅读 + /// + [TaskInterceptor("漫画阅读", rethrowWhenException: false)] + private async Task MangaRead() + { + await _mangaDomainService.MangaRead(); + } - private async Task SaveCookieAsync(BiliCookie ckInfo, CancellationToken cancellationToken) - { - var platformType = _configuration.GetSection("PlateformType").Get(); - _logger.LogInformation("当前运行平台:{platform}", platformType); + /// + /// 每月获取大会员漫画权益 + /// + [TaskInterceptor("领取大会员漫画权益", rethrowWhenException: false)] + private async Task ReceiveMangaVipReward(UserInfo userInfo) + { + await _mangaDomainService.ReceiveMangaVipReward(1, userInfo); + } - //更新cookie到青龙env - if (platformType == PlatformType.QingLong) - { - await _loginDomainService.SaveCookieToQinLongAsync(ckInfo, cancellationToken); - return; - } + private async Task SaveCookieAsync(BiliCookie ckInfo, CancellationToken cancellationToken) + { + var platformType = _configuration.GetSection("PlateformType").Get(); + _logger.LogInformation("当前运行平台:{platform}", platformType); - //更新cookie到json - await _loginDomainService.SaveCookieToJsonFileAsync(ckInfo, cancellationToken); + //更新cookie到青龙env + if (platformType == PlatformType.QingLong) + { + await _loginDomainService.SaveCookieToQinLongAsync(ckInfo, cancellationToken); + return; } + + //更新cookie到json + await _loginDomainService.SaveCookieToJsonFileAsync(ckInfo, cancellationToken); } -} +} \ No newline at end of file diff --git a/test/AppServiceTest/VipServiceTest.cs b/test/AppServiceTest/VipServiceTest.cs index ca5da50ce..216aea8a9 100644 --- a/test/AppServiceTest/VipServiceTest.cs +++ b/test/AppServiceTest/VipServiceTest.cs @@ -28,7 +28,6 @@ public async Task WatchVideo() using var scope = Global.ServiceProviderRoot.CreateScope(); var appService = scope.ServiceProvider.GetRequiredService(); var res = await appService.WatchBangumi(); - Assert.True(res); } From dbe91b5914dcf5de20002c9ef5b7115698035791 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 25 Dec 2024 00:42:57 +0800 Subject: [PATCH 10/10] fix[#791]: fix VipBigPoint interupt when exception --- CHANGELOG.md | 1 + .../VipBigPointAppService.cs | 271 ++++++++++-------- 2 files changed, 146 insertions(+), 126 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc29e47c1..c0b04a622 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## 2.1.3 - Code refactory +- Fix[#791]:修复VipBigPoint任务异常导致终止的问题 ## 2.1.2 - Feature: enhancement CICD scripts - Fix[#728]: compatible with qinglong history versions diff --git a/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs b/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs index bd8276b31..73979d46c 100644 --- a/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs +++ b/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs @@ -2,12 +2,10 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Ray.BiliBiliTool.Agent; using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos; -using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Video; using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.ViewMall; using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.VipTask; using Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces; @@ -22,7 +20,6 @@ namespace Ray.BiliBiliTool.Application; public class VipBigPointAppService : AppService, IVipBigPointAppService { private readonly ILogger _logger; - private readonly IConfiguration _configuration; private readonly IVipBigPointApi _vipApi; private readonly IAccountDomainService _loginDomainService; private readonly IVideoDomainService _videoDomainService; @@ -33,7 +30,6 @@ public class VipBigPointAppService : AppService, IVipBigPointAppService private readonly VipBigPointOptions _vipBigPointOptions; public VipBigPointAppService( - IConfiguration configuration, ILogger logger, IVipBigPointApi vipApi, IAccountDomainService loginDomainService, @@ -44,7 +40,6 @@ public VipBigPointAppService( IVideoApi videoApi, IOptionsMonitor vipBigPointOptions) { - _configuration = configuration; _logger = logger; _vipApi = vipApi; _loginDomainService = loginDomainService; @@ -56,58 +51,8 @@ public VipBigPointAppService( _vipBigPointOptions = vipBigPointOptions.CurrentValue; } - /// - /// 领取大会员专属经验包 - /// - public async Task VipExpress() - { - _logger.LogInformation("大会员经验领取任务开始"); - var re = await _vipApi.GetVouchersInfoAsync(); - if (re.Code == 0) - { - var state = re.Data.List.Find(x => x.Type == 9).State; - - switch (state) - { - case 2: - _logger.LogInformation("大会员经验观看任务未完成"); - _logger.LogInformation("开始观看视频"); - // 观看视频,暂时没有好办法解决,先这样使着 - DailyTaskInfo dailyTaskInfo = await _accountDomainService.GetDailyTaskStatus(); - await _videoDomainService.WatchAndShareVideo(dailyTaskInfo); - // 跳转到未兑换,执行兑换任务 - goto case 0; - - case 1: - _logger.LogInformation("大会员经验已兑换"); - break; - - case 0: - _logger.LogInformation("大会员经验未兑换"); - //兑换api - var response = await _vipApi.ObtainVipExperienceAsync(new VipExperienceRequest() - { - csrf = _biliCookie.BiliJct - }); - if (response.Code != 0) - { - _logger.LogInformation("大会员经验领取失败,错误信息:{message}", response.Message); - break; - } - - _logger.LogInformation("领取成功,经验+10 √"); - break; - - default: - _logger.LogDebug("大会员经验领取失败,未知错误"); - break; - } - } - } - - [TaskInterceptor("大会员大积分", TaskLevel.One)] - public override async Task DoTaskAsync(CancellationToken cancellationToken) + public override async Task DoTaskAsync(CancellationToken cancellationToken = default) { // TODO 解决taskInfo在一个任务出错后,后续的任务均会报空引用错误 var ui = await GetUserInfo(); @@ -157,6 +102,55 @@ public override async Task DoTaskAsync(CancellationToken cancellationToken) taskInfo.LogInfo(_logger); } + /// + /// 领取大会员专属经验包 + /// + public async Task VipExpress() + { + _logger.LogInformation("大会员经验领取任务开始"); + var re = await _vipApi.GetVouchersInfoAsync(); + if (re.Code == 0) + { + var state = re.Data.List.Find(x => x.Type == 9).State; + + switch (state) + { + case 2: + _logger.LogInformation("大会员经验观看任务未完成"); + _logger.LogInformation("开始观看视频"); + // 观看视频,暂时没有好办法解决,先这样使着 + DailyTaskInfo dailyTaskInfo = await _accountDomainService.GetDailyTaskStatus(); + await _videoDomainService.WatchAndShareVideo(dailyTaskInfo); + // 跳转到未兑换,执行兑换任务 + goto case 0; + + case 1: + _logger.LogInformation("大会员经验已兑换"); + break; + + case 0: + _logger.LogInformation("大会员经验未兑换"); + //兑换api + var response = await _vipApi.ObtainVipExperienceAsync(new VipExperienceRequest() + { + csrf = _biliCookie.BiliJct + }); + if (response.Code != 0) + { + _logger.LogInformation("大会员经验领取失败,错误信息:{message}", response.Message); + break; + } + + _logger.LogInformation("领取成功,经验+10 √"); + break; + + default: + _logger.LogDebug("大会员经验领取失败,未知错误"); + break; + } + } + } + [TaskInterceptor("测试Cookie")] private async Task GetUserInfo() { @@ -195,7 +189,16 @@ private async Task Sign(VipTaskInfo info) [TaskInterceptor("福利任务", TaskLevel.Two, false)] private async Task Bonus(VipTaskInfo info) { - var bonusTask = GetTarget(info); + const string moduleCode = "福利任务"; + const string taskCode = "bonus"; + + var bonusTask = GetTarget(info, moduleCode, taskCode); + + if (bonusTask == null) + { + _logger.LogInformation("任务失效"); + return info; + } //如果状态不等于3,则做 if (bonusTask.state == 3) @@ -220,25 +223,27 @@ private async Task Bonus(VipTaskInfo info) var infoResult = await _vipApi.GetTaskListAsync(); if (infoResult.Code != 0) throw new Exception(infoResult.ToJsonStr()); info = infoResult.Data; - bonusTask = GetTarget(info); + bonusTask = GetTarget(info, moduleCode, taskCode); _logger.LogInformation("确认:{re}", bonusTask.state == 3 && bonusTask.complete_times >= 1); } return info; - - CommonTaskItem GetTarget(VipTaskInfo info) - { - return info.Task_info.Modules.First(x => x.module_title == "福利任务") - .common_task_item - .First(x => x.task_code == "bonus"); - } } [TaskInterceptor("体验任务", TaskLevel.Two, false)] private async Task Privilege(VipTaskInfo info) { - var privilegeTask = GetTarget(info); + const string moduleCode = "体验任务"; + const string taskCode = "privilege"; + + var privilegeTask = GetTarget(info, moduleCode, taskCode); + + if (privilegeTask == null) + { + _logger.LogInformation("任务失效"); + return info; + } //如果状态不等于3,则做 if (privilegeTask.state == 3) @@ -263,27 +268,29 @@ private async Task Privilege(VipTaskInfo info) var infoResult = await _vipApi.GetTaskListAsync(); if (infoResult.Code != 0) throw new Exception(infoResult.ToJsonStr()); info = infoResult.Data; - privilegeTask = GetTarget(info); + privilegeTask = GetTarget(info, moduleCode, taskCode); _logger.LogInformation("确认:{re}", privilegeTask.state == 3 && privilegeTask.complete_times >= 1); } - CommonTaskItem GetTarget(VipTaskInfo info) - { - return info.Task_info.Modules.First(x => x.module_title == "体验任务") - .common_task_item - .First(x => x.task_code == "privilege"); - } - return info; } [TaskInterceptor("浏览追番频道页10秒", TaskLevel.Two, false)] private async Task ViewAnimate(VipTaskInfo info) { + const string moduleCode = "日常任务"; + const string taskCode = "animatetab"; + var code = "jp_channel"; - CommonTaskItem targetTask = GetTarget(info); + CommonTaskItem targetTask = GetTarget(info, moduleCode, taskCode); + + if (targetTask == null) + { + _logger.LogInformation("任务失效"); + return info; + } //如果状态不等于3,则做 if (targetTask.state == 3) @@ -308,25 +315,27 @@ private async Task ViewAnimate(VipTaskInfo info) var infoResult = await _vipApi.GetTaskListAsync(); if (infoResult.Code != 0) throw new Exception(infoResult.ToJsonStr()); info = infoResult.Data; - targetTask = GetTarget(info); + targetTask = GetTarget(info, moduleCode, taskCode); _logger.LogInformation("确认:{re}", targetTask.state == 3 && targetTask.complete_times >= 1); } - CommonTaskItem GetTarget(VipTaskInfo info) - { - return info.Task_info.Modules.First(x => x.module_title == "日常任务") - .common_task_item - .First(x => x.task_code == "animatetab"); - } - return info; } [TaskInterceptor("浏览会员购页面10秒", TaskLevel.Two, false)] private async Task ViewVipMall(VipTaskInfo info) { - CommonTaskItem targetTask = GetTarget(info); + const string moduleCode = "日常任务"; + const string taskCode = "vipmallview"; + + CommonTaskItem targetTask = GetTarget(info, moduleCode, taskCode); + + if (targetTask == null) + { + _logger.LogInformation("任务失效"); + return info; + } //如果状态不等于3,则做 if (targetTask.state == 3) @@ -355,25 +364,27 @@ private async Task ViewVipMall(VipTaskInfo info) var infoResult = await _vipApi.GetTaskListAsync(); if (infoResult.Code != 0) throw new Exception(infoResult.ToJsonStr()); info = infoResult.Data; - targetTask = GetTarget(info); + targetTask = GetTarget(info, moduleCode, taskCode); _logger.LogInformation("确认:{re}", targetTask.state == 3 && targetTask.complete_times >= 1); } - CommonTaskItem GetTarget(VipTaskInfo info) - { - return info.Task_info.Modules.First(x => x.module_title == "日常任务") - .common_task_item - .First(x => x.task_code == "vipmallview"); - } - return info; } [TaskInterceptor("观看剧集内容", TaskLevel.Two, false)] private async Task ViewVideo(VipTaskInfo info) { - CommonTaskItem targetTask = GetTarget(info); + const string moduleCode = "日常任务"; + const string taskCode = "ogvwatchnew"; + + CommonTaskItem targetTask = GetTarget(info, moduleCode, taskCode); + + if (targetTask == null) + { + _logger.LogInformation("任务失效"); + return info; + } // 如果状态不等于3,则做 if (targetTask.state == 3) @@ -394,20 +405,22 @@ private async Task ViewVideo(VipTaskInfo info) // 观看剧集内容 _logger.LogInformation("api变更,暂未实现"); - CommonTaskItem GetTarget(VipTaskInfo info) - { - return info.Task_info.Modules.First(x => x.module_title == "日常任务") - .common_task_item - .First(x => x.task_code == "ogvwatchnew"); - } - return info; } [TaskInterceptor("购买单点付费影片(仅领取)", TaskLevel.Two, false)] private async Task BuyVipVideo(VipTaskInfo info) { - CommonTaskItem targetTask = GetTarget(info); + const string moduleCode = "日常任务"; + const string taskCode = "tvodbuy"; + + CommonTaskItem targetTask = GetTarget(info, moduleCode, taskCode); + + if (targetTask == null) + { + _logger.LogInformation("任务失效"); + return info; + } if (targetTask.state is 3 or 1) { @@ -424,19 +437,21 @@ private async Task BuyVipVideo(VipTaskInfo info) } return info; - - CommonTaskItem GetTarget(VipTaskInfo info) - { - return info.Task_info.Modules.First(x => x.module_title == "日常任务") - .common_task_item - .First(x => x.task_code == "tvodbuy"); - } } [TaskInterceptor("购买指定会员购商品(仅领取)", TaskLevel.Two, false)] private async Task BuyVipMall(VipTaskInfo info) { - CommonTaskItem targetTask = GetTarget(info); + const string moduleCode = "日常任务"; + const string taskCode = "vipmallbuy"; + + CommonTaskItem targetTask = GetTarget(info, moduleCode, taskCode); + + if (targetTask == null) + { + _logger.LogInformation("任务失效"); + return info; + } if (targetTask.state is 3 or 1) { @@ -453,22 +468,23 @@ private async Task BuyVipMall(VipTaskInfo info) } return info; - - CommonTaskItem GetTarget(VipTaskInfo info) - { - return info.Task_info.Modules.First(x => x.module_title == "日常任务") - .common_task_item - .First(x => x.task_code == "vipmallbuy"); - } } [TaskInterceptor("浏览装扮商城主页", TaskLevel.Two, false)] private async Task ViewDressMall(VipTaskInfo info) { + const string moduleCode = "日常任务"; + const string taskCode = "dress-view"; + //var code = "dress-view"; - CommonTaskItem targetTask = GetTarget(info); + CommonTaskItem targetTask = GetTarget(info, moduleCode, taskCode); + if (targetTask == null) + { + _logger.LogInformation("任务失效"); + return info; + } //如果状态不等于3,则做 if (targetTask.state == 3) @@ -493,21 +509,23 @@ private async Task ViewDressMall(VipTaskInfo info) var infoResult = await _vipApi.GetTaskListAsync(); if (infoResult.Code != 0) throw new Exception(infoResult.ToJsonStr()); info = infoResult.Data; - targetTask = GetTarget(info); + targetTask = GetTarget(info, moduleCode, taskCode); _logger.LogInformation("确认:{re}", targetTask.state == 3 && targetTask.complete_times >= 1); } - CommonTaskItem GetTarget(VipTaskInfo info) - { - return info.Task_info.Modules.First(x => x.module_title == "日常任务") - .common_task_item - .First(x => x.task_code == "dress-view"); - } - return info; } + #region private + + private static CommonTaskItem GetTarget(VipTaskInfo info, string moduleCode, string taskCode) + { + var module = info.Task_info.Modules.FirstOrDefault(x => x.module_title == moduleCode); + return module? + .common_task_item + .FirstOrDefault(x => x.task_code == taskCode); + } /// /// 领取任务 @@ -548,7 +566,6 @@ private async Task Complete(string taskCode) } } - private async Task CompleteV2(string taskCode) { var request = new ReceiveOrCompleteTaskRequest(taskCode); @@ -665,4 +682,6 @@ public async Task WatchBangumi() return null; } + + #endregion }