using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Xml.Linq; using Microsoft.Windows.AppNotifications; namespace XFEEDToolBox; public partial class App { private static async Task SendAnnouncementOnceAsync(string path) { path=Path.GetFullPath(path);uint notificationId=0;var inHistory=false;string? failure=null;var registered=false; try { using var document=JsonDocument.Parse(await File.ReadAllTextAsync(path));var source=document.RootElement; var title=source.GetProperty("title").GetString()??"游戏公告"; var message=source.GetProperty("message").GetString()??throw new InvalidDataException("公告内容为空。"); var detail=source.TryGetProperty("detail",out var extra)?extra.GetString()??"":""; if(string.IsNullOrWhiteSpace(message)||title.Length>100||message.Length>8000||detail.Length>1000)throw new InvalidDataException("公告内容长度无效。"); if(!AppNotificationManager.IsSupported())throw new PlatformNotSupportedException("当前 Windows 通知接口不可用。"); var content=new XElement("toast",new XAttribute("launch","action=announcement&page=home"), new XElement("visual",new XElement("binding",new XAttribute("template","ToastGeneric"), new XElement("text",title),new XElement("text",message),new XElement("text",detail))), new XElement("audio",new XAttribute("src","ms-winsoundevent:Notification.Default"))); var manager=AppNotificationManager.Default; manager.Register("XFE ED 工具箱",new Uri(Path.Combine(AppContext.BaseDirectory,"Assets","icon.png")));registered=true; var tag=Convert.ToHexStringLower(SHA256.HashData(Encoding.UTF8.GetBytes(title+message+detail)))[..16]; var notification=new AppNotification(content.ToString(SaveOptions.DisableFormatting)) {Tag=tag,Group="game-announcements",Expiration=DateTimeOffset.UtcNow.AddHours(2)}; manager.Show(notification);notificationId=notification.Id; inHistory=(await manager.GetAllAsync()).Any(n=>n.Id==notificationId&¬ificationId>0); if(!inHistory)throw new IOException("尚未确认 Windows 接收公告通知。"); Runtime.Log("游戏公告",message+" "+detail); } catch(Exception error){failure=error.ToString();} finally { await File.WriteAllTextAsync(path+".result.json",JsonSerializer.Serialize(new{at=DateTimeOffset.UtcNow,application="XFE ED 工具箱",notificationId,inHistory,failure},new JsonSerializerOptions{WriteIndented=true})); if(registered)AppNotificationManager.Default.Unregister(); MainWindow.Close(); } } }