From e65469c965294c7147ab9417e83e26a9ceda9661 Mon Sep 17 00:00:00 2001 From: Zero Ash Date: Sat, 3 Oct 2026 03:35:06 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat(painter):=20=E6=94=AF=E6=8C=81=20-1=20?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E4=B8=8D=E9=99=90=E5=88=B6=E6=AF=8F=E4=BA=BA?= =?UTF-8?q?=E6=AF=8F=E6=97=A5=E7=BB=98=E5=9B=BE=E6=AC=A1=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PainterQuota.IsValidDailyLimit 接受 -1 - TryConsumeQuotaAsync 在 limit 为 -1 时跳过上限判断 - 同步更新 PainterQuotaTest 用例 --- src/plugins/ZeroBot.Painter/PaintCommandHandler.cs | 2 +- src/plugins/ZeroBot.Painter/PainterQuota.cs | 2 +- test/ZeroBot.Core.Test/PainterQuotaTest.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/ZeroBot.Painter/PaintCommandHandler.cs b/src/plugins/ZeroBot.Painter/PaintCommandHandler.cs index 812229a..e0ad5c4 100644 --- a/src/plugins/ZeroBot.Painter/PaintCommandHandler.cs +++ b/src/plugins/ZeroBot.Painter/PaintCommandHandler.cs @@ -212,7 +212,7 @@ private async ValueTask TryConsumeQuotaAsync(long peerId, long senderId, i value.DailyQuotas[key] = quota = new DailyQuota(today, 0); } - if (quota.Count >= limit) return false; + if (limit > -1 && quota.Count >= limit) return false; value.DailyQuotas[key] = quota with { Count = quota.Count + 1 }; await config.SaveAsync(value, token); diff --git a/src/plugins/ZeroBot.Painter/PainterQuota.cs b/src/plugins/ZeroBot.Painter/PainterQuota.cs index 74c75c2..3bae91b 100644 --- a/src/plugins/ZeroBot.Painter/PainterQuota.cs +++ b/src/plugins/ZeroBot.Painter/PainterQuota.cs @@ -24,5 +24,5 @@ public static DateOnly Today(DateTimeOffset now) => /// /// 启用指令 number 合法性:1 <= number <= max。 /// - public static bool IsValidDailyLimit(int number, int max) => number >= 1 && number <= max; + public static bool IsValidDailyLimit(int number, int max) => number == -1 || (number >= 1 && number <= max); } diff --git a/test/ZeroBot.Core.Test/PainterQuotaTest.cs b/test/ZeroBot.Core.Test/PainterQuotaTest.cs index 1d4c3d2..d3f1ffc 100644 --- a/test/ZeroBot.Core.Test/PainterQuotaTest.cs +++ b/test/ZeroBot.Core.Test/PainterQuotaTest.cs @@ -29,7 +29,7 @@ public void Key_ShouldCombinePeerAndSender() [InlineData(1, true)] [InlineData(5, true)] [InlineData(6, false)] - [InlineData(-1, false)] + [InlineData(-1, true)] public void IsValidDailyLimit_ShouldRespectBoundaries(int number, bool expected) { Assert.Equal(expected, PainterQuota.IsValidDailyLimit(number, 5)); From 7237dbae9fd4ca029e3055df634d514f47f17777 Mon Sep 17 00:00:00 2001 From: Zero Ash Date: Sat, 3 Oct 2026 03:42:07 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix(painter):=20=E5=90=AF=E7=94=A8=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E4=BB=85=E6=8C=89=E5=86=92=E5=8F=B7=E5=88=87=E5=88=86?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E4=BB=A5=E6=94=AF=E6=8C=81=20-1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 默认 argumentSplitters 含连字符,会把 /小画家:启用:-1 的负号当作参数分隔符;改为仅按全角/半角冒号切分。 --- src/plugins/ZeroBot.Painter/PainterManageCommandHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/ZeroBot.Painter/PainterManageCommandHandler.cs b/src/plugins/ZeroBot.Painter/PainterManageCommandHandler.cs index 235db44..aeb81c7 100644 --- a/src/plugins/ZeroBot.Painter/PainterManageCommandHandler.cs +++ b/src/plugins/ZeroBot.Painter/PainterManageCommandHandler.cs @@ -40,7 +40,7 @@ protected override async ValueTask PredicateAsync(Event m protected override async ValueTask HandleAsync(Event message, CancellationToken cancellationToken = default) { - var command = message.ToTextCommands().FirstOrDefault(); + var command = message.ToTextCommands(argumentSplitters: "::").FirstOrDefault(); var arguments = command?.Arguments ?? []; var peerId = message.Data.PeerId; From 0622277ee42c9fc403d5bac230bf54b006bde9f1 Mon Sep 17 00:00:00 2001 From: Zero Ash Date: Fri, 9 Oct 2026 03:36:05 +0800 Subject: [PATCH 3/3] =?UTF-8?q?refactor(workflow):=20=E7=BE=A4=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E4=B8=8A=E4=BC=A0=E4=B8=8B=E6=B2=89=E8=87=B3=20IBotCo?= =?UTF-8?q?ntext/IBotService?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 抽象层新增 UploadFileToGroupAsync,MilkyBot 实现并经 BotContext 透传 - Workflow 插件改用 bot.UploadFileToGroupAsync,移除对 Milky.Net.Client 的直接依赖 - 同步 TestBotService 桩实现 --- src/ZeroBot.Abstraction/Bot/IBotContext.cs | 3 +++ src/ZeroBot.Abstraction/Bot/IBotService.cs | 3 +++ src/ZeroBot.Core/Services/BotContext.cs | 8 ++++++++ src/plugins/ZeroBot.Milky/Bot/MilkyBot.cs | 6 ++++++ src/plugins/ZeroBot.Workflow/WorkflowCommandHandler.cs | 9 +++++---- src/plugins/ZeroBot.Workflow/ZeroBot.Workflow.csproj | 1 - test/ZeroBot.Core.Test/TestBotService.cs | 6 ++++++ 7 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/ZeroBot.Abstraction/Bot/IBotContext.cs b/src/ZeroBot.Abstraction/Bot/IBotContext.cs index 31ac989..ee2cedd 100644 --- a/src/ZeroBot.Abstraction/Bot/IBotContext.cs +++ b/src/ZeroBot.Abstraction/Bot/IBotContext.cs @@ -38,4 +38,7 @@ ValueTask UpdateGroupReactionAsync(long accountId, long groupId, long messageId, void SetEventRepository(IBotEventRepository repository); ValueTask GetTempResourceUrlAsync(long accountId, string id, CancellationToken cancellationToken = default); + + ValueTask UploadFileToGroupAsync(long accountId, long groupId, string fileName, MilkyUri fileUri, + CancellationToken cancellationToken = default); } diff --git a/src/ZeroBot.Abstraction/Bot/IBotService.cs b/src/ZeroBot.Abstraction/Bot/IBotService.cs index 045d059..e0bc241 100644 --- a/src/ZeroBot.Abstraction/Bot/IBotService.cs +++ b/src/ZeroBot.Abstraction/Bot/IBotService.cs @@ -31,4 +31,7 @@ ValueTask GetGroupInformationAsync(long groupId, ValueTask GetTempResourceUrlAsync(string id, CancellationToken cancellationToken = default); ValueTask AcceptFriendRequestAsync(string uid, CancellationToken cancellationToken = default); + + ValueTask UploadFileToGroupAsync(long accountId, long groupId, string fileName, MilkyUri fileUri, + CancellationToken cancellationToken = default); } diff --git a/src/ZeroBot.Core/Services/BotContext.cs b/src/ZeroBot.Core/Services/BotContext.cs index 1cdd7b6..fb29da2 100644 --- a/src/ZeroBot.Core/Services/BotContext.cs +++ b/src/ZeroBot.Core/Services/BotContext.cs @@ -153,6 +153,14 @@ public ValueTask GetTempResourceUrlAsync(long accountId, string id, : botService.GetTempResourceUrlAsync(id, cancellationToken); } + public ValueTask UploadFileToGroupAsync(long accountId, long groupId, string fileName, MilkyUri fileUri, + CancellationToken cancellationToken = default) + { + return !_services.TryGetValue(accountId, out var botService) + ? default + : botService.UploadFileToGroupAsync(accountId, groupId, fileName, fileUri, cancellationToken); + } + public async ValueTask UpdateGroupReactionAsync(long accountId, long groupId, long messageId, string reactionId, bool add, CancellationToken cancellationToken = default) { diff --git a/src/plugins/ZeroBot.Milky/Bot/MilkyBot.cs b/src/plugins/ZeroBot.Milky/Bot/MilkyBot.cs index 832df43..284fb2e 100644 --- a/src/plugins/ZeroBot.Milky/Bot/MilkyBot.cs +++ b/src/plugins/ZeroBot.Milky/Bot/MilkyBot.cs @@ -49,6 +49,12 @@ public async ValueTask AcceptFriendRequestAsync(string uid, CancellationToken ca await milky.Friend.AcceptFriendRequestAsync(param, cancellationToken); } + public async ValueTask UploadFileToGroupAsync(long accountId, long groupId, string fileName, MilkyUri fileUri, + CancellationToken cancellationToken = default) + { + await milky.File.UploadGroupFileAsync(new UploadGroupFileInput(groupId, "/", fileUri, fileName), cancellationToken); + } + public async ValueTask GetCurrentAccountAsync(CancellationToken cancellationToken = default) { return await botInfos.GetAccountInfoAsync(cancellationToken); diff --git a/src/plugins/ZeroBot.Workflow/WorkflowCommandHandler.cs b/src/plugins/ZeroBot.Workflow/WorkflowCommandHandler.cs index 1139a8f..4841c97 100644 --- a/src/plugins/ZeroBot.Workflow/WorkflowCommandHandler.cs +++ b/src/plugins/ZeroBot.Workflow/WorkflowCommandHandler.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Milky.Net.Client; using Milky.Net.Model; using ZeroBot.Abstraction.Bot; using ZeroBot.Abstraction.Service; @@ -20,7 +19,6 @@ public class WorkflowCommandHandler( IPermission permission, IOptions options, WorkflowApi api, - MilkyClient milky, ILogger logger) : CommandQueuedHandler(dispatcher) { private const string CommandPrefix = "/workflow"; @@ -146,8 +144,11 @@ private async ValueTask SendResultAsync(Event @event, string si } var fileName = GuessFileName(data); - await milky.File.UploadGroupFileAsync( - new UploadGroupFileInput(@event.Data.PeerId, "/", new MilkyUri($"base64://{base64}"), fileName), + await bot.UploadFileToGroupAsync( + @event.SelfId, + @event.Data.PeerId, + fileName, + new MilkyUri($"base64://{base64}"), cancellationToken); } diff --git a/src/plugins/ZeroBot.Workflow/ZeroBot.Workflow.csproj b/src/plugins/ZeroBot.Workflow/ZeroBot.Workflow.csproj index f513da8..12b1a57 100644 --- a/src/plugins/ZeroBot.Workflow/ZeroBot.Workflow.csproj +++ b/src/plugins/ZeroBot.Workflow/ZeroBot.Workflow.csproj @@ -10,7 +10,6 @@ - diff --git a/test/ZeroBot.Core.Test/TestBotService.cs b/test/ZeroBot.Core.Test/TestBotService.cs index 5782d94..10b14cd 100644 --- a/test/ZeroBot.Core.Test/TestBotService.cs +++ b/test/ZeroBot.Core.Test/TestBotService.cs @@ -70,4 +70,10 @@ public ValueTask AcceptFriendRequestAsync(string uid, CancellationToken cancella { throw new NotImplementedException(); } + + public ValueTask UploadFileToGroupAsync(long accountId, long groupId, string fileName, MilkyUri fileUri, + CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } } \ No newline at end of file