Files
wx-win-agent/node-agent/WxAgent.Core/WechatM5.cs
T

98 lines
3.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace WxAgent.Core;
public sealed record WechatMomentSnapshot(
string Author,
string Text,
string Fingerprint,
string? Time = null,
int ImageCount = 0,
bool IsLiked = false);
public sealed record WechatMessageContent(
ChatMessageType Type,
string Text,
Uri? Url = null,
QuotedMessageSnapshot? Quote = null);
public sealed record WechatNoteContentPart(string Kind, string Value);
public sealed record WechatNoteContent(IReadOnlyList<WechatNoteContentPart> Parts)
{
public string ToMarkdown() => string.Join(
Environment.NewLine + Environment.NewLine,
Parts.Select(part => part.Kind == "file" ? $"[{Path.GetFileName(part.Value)}]({part.Value})" : part.Value));
}
public enum WechatMomentPrivacy
{
Public,
TagWhitelist,
TagBlacklist
}
public sealed record WechatMomentPublishOptions(
WechatMomentPrivacy Privacy = WechatMomentPrivacy.Public,
IReadOnlyList<string>? Tags = null)
{
public void Validate()
{
if (!Enum.IsDefined(Privacy))
throw new WxAgentException(WxAgentErrorCode.InvalidArgument, "Unknown moment privacy mode.");
if (Privacy != WechatMomentPrivacy.Public)
WechatOperationPolicy.ValidateNames(Tags ?? [], nameof(Tags));
}
}
public static partial class WechatMessageContentParser
{
[GeneratedRegex(@"https?://[^\s<>\]\[\)]+", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)]
private static partial Regex UrlRegex();
public static Uri? GetUrl(ChatMessageSnapshot message)
{
ArgumentNullException.ThrowIfNull(message);
var match = UrlRegex().Match(message.Text);
return match.Success && Uri.TryCreate(match.Value.TrimEnd('.', ',', '。', ''), UriKind.Absolute, out var uri) ? uri : null;
}
public static WechatMessageContent GetContent(ChatMessageSnapshot message)
{
ArgumentNullException.ThrowIfNull(message);
return new WechatMessageContent(message.Type, message.Text, GetUrl(message), message.Quote);
}
public static string ToMarkdown(ChatMessageSnapshot message)
{
ArgumentNullException.ThrowIfNull(message);
var content = GetContent(message);
var body = content.Type switch
{
ChatMessageType.Image => $"![图片]({content.Url?.AbsoluteUri ?? string.Empty})",
ChatMessageType.Video => $"[视频]({content.Url?.AbsoluteUri ?? string.Empty})",
ChatMessageType.File => $"[文件]({content.Url?.AbsoluteUri ?? string.Empty})",
ChatMessageType.Voice => $"> 语音:{content.Text}",
ChatMessageType.Link when content.Url is not null => $"[{LinkTitle(content.Text, content.Url)}]({content.Url.AbsoluteUri})",
_ => content.Text
};
if (content.Quote is null) return body;
var quote = string.Join(Environment.NewLine, content.Quote.Text.Split('\n').Select(line => $"> {line}"));
return $"{quote}{Environment.NewLine}{Environment.NewLine}{body}";
}
public static string MomentFingerprint(string author, string text, string? time)
{
var bytes = SHA256.HashData(Encoding.UTF8.GetBytes($"{author}\n{text}\n{time}"));
return Convert.ToHexString(bytes).ToLowerInvariant();
}
private static string LinkTitle(string text, Uri url)
{
var title = UrlRegex().Replace(text, string.Empty, 1).Trim();
return string.IsNullOrWhiteSpace(title) ? url.Host : title;
}
}