feat: implement M5 moments and rich messages

This commit is contained in:
2026-09-04 23:48:28 +08:00
parent 77e1e9dc2b
commit 1bd0344e8b
7 changed files with 806 additions and 0 deletions
+66
View File
@@ -62,6 +62,34 @@ try
});
return report.Errors.Count == 0 ? 0 : 2;
}
case "m5-smoke":
{
var momentsWindow = await WechatChatClient.OpenMomentsAsync(cancellationToken);
await WechatChatClient.RefreshMomentsAsync(cancellationToken);
var moments = await WechatChatClient.GetMomentsAsync(50, cancellationToken: cancellationToken);
await WechatChatClient.CloseMomentsAsync(cancellationToken);
var sample = new ChatMessageSnapshot("文档 https://example.com", "m5-smoke", 0, ChatMessageType.Link);
var confirmationGuarded = false;
try
{
WechatOperationPolicy.RequireConfirmation(null, "m5 smoke write operation");
}
catch (WxAgentException exception) when (exception.Code == WxAgentErrorCode.InvalidArgument)
{
confirmationGuarded = true;
}
WriteJson(new
{
scope = "M5",
momentsWindow = momentsWindow.Kind,
momentCount = moments.Count,
urlParsed = WechatMessageContentParser.GetUrl(sample)?.Host == "example.com",
markdownRendered = WechatMessageContentParser.ToMarkdown(sample).Contains("https://example.com", StringComparison.Ordinal),
confirmationGuarded,
privacy = "moment authors and content omitted"
});
return confirmationGuarded ? 0 : 2;
}
case "m4-smoke":
{
var windows = await WechatChatClient.GetSubWindowsAsync(cancellationToken);
@@ -121,6 +149,29 @@ try
WriteJson(new { found, checkedMessages = history.Count, privacy = "message text omitted" });
return found ? 0 : 2;
}
case "chat" when args[1] == "send-url-card":
{
var recipient = GetRequiredOption(args, "--to");
var url = new Uri(GetRequiredOption(args, "--url"), UriKind.Absolute);
var result = await WechatChatClient.SendUrlCardAsync(
url,
[recipient],
GetOption(args, "--message"),
GetRequiredOption(args, "--confirm"),
cancellationToken);
WriteJson(result);
return result.Success ? 0 : 2;
}
case "chat" when args[1] == "send-audio":
{
var result = await WechatChatClient.SendAudioAsync(
GetRequiredOption(args, "--to"),
GetRequiredOption(args, "--path"),
GetRequiredOption(args, "--confirm"),
cancellationToken);
WriteJson(result);
return result.Success ? 0 : 2;
}
case "chat" when args[1] == "send":
{
var message = await WechatChatClient.SendTextAsync(GetRequiredOption(args, "--text"), cancellationToken);
@@ -333,6 +384,12 @@ static int ValidateCommandLine(string[] values)
return 30;
}
if (values[0] == "m5-smoke")
{
ValidateOptions(values, 1, ["--timeout"], []);
return 60;
}
if (values[0] == "m4-smoke")
{
ValidateOptions(values, 1, ["--timeout"], []);
@@ -355,6 +412,12 @@ static int ValidateCommandLine(string[] values)
{
switch (values[1])
{
case "send-url-card":
ValidateOptions(values, 2, ["--to", "--url", "--message", "--confirm", "--timeout"], []);
return 60;
case "send-audio":
ValidateOptions(values, 2, ["--to", "--path", "--confirm", "--timeout"], []);
return 60;
case "send":
ValidateOptions(values, 2, ["--text", "--timeout"], []);
return 30;
@@ -526,8 +589,11 @@ WxAgent.Host commands:
inspect-ui --output <path> [--timeout 30]
smoke [--output <path>] [--timeout 30]
m4-smoke [--timeout 60]
m5-smoke [--timeout 60]
group at-all --group <name> --message <text> --confirm CONFIRM [--timeout 30]
group verify-at-all --group <name> --message <text> [--timeout 30]
chat send-url-card --to <name> --url <http-url> [--message <text>] --confirm CONFIRM [--timeout 60]
chat send-audio --to <name> --path <audio-file> --confirm CONFIRM [--timeout 60]
chat send --text <one-line-text> [--timeout 30]
chat reply-latest --text <one-line-text> [--timeout 60]
chat send-file --path <file> [--timeout 60]