From 626e0a53040cd6163f593001cd9abc2871316aa9 Mon Sep 17 00:00:00 2001 From: genteure Date: Thu, 25 Aug 2022 18:44:35 +0800 Subject: [PATCH] feat: use Windows 10 notification center api --- .../BililiveRecorder.WPF.csproj | 6 +- BililiveRecorder.WPF/Pages/RootPage.xaml.cs | 3 + BililiveRecorder.WPF/Program.cs | 7 ++ .../StreamStartedNotification.cs | 81 +++++++++++++++++++ 4 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 BililiveRecorder.WPF/StreamStartedNotification.cs diff --git a/BililiveRecorder.WPF/BililiveRecorder.WPF.csproj b/BililiveRecorder.WPF/BililiveRecorder.WPF.csproj index 07a062f..2fc69f8 100644 --- a/BililiveRecorder.WPF/BililiveRecorder.WPF.csproj +++ b/BililiveRecorder.WPF/BililiveRecorder.WPF.csproj @@ -160,6 +160,7 @@ True Strings.resx + @@ -344,6 +345,9 @@ 6.0.0 + + 7.1.2 + 0.9.4 @@ -411,4 +415,4 @@ - + \ No newline at end of file diff --git a/BililiveRecorder.WPF/Pages/RootPage.xaml.cs b/BililiveRecorder.WPF/Pages/RootPage.xaml.cs index e60ff08..7eab970 100644 --- a/BililiveRecorder.WPF/Pages/RootPage.xaml.cs +++ b/BililiveRecorder.WPF/Pages/RootPage.xaml.cs @@ -273,6 +273,9 @@ You can uninstall me in system settings.", "安装成功 Installed", MessageBoxB if (!recorder.Config.Global.WpfNotifyStreamStart) return; + _ = StreamStartedNotification.ShowAsync(room); + + return; _ = this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { if (Application.Current.MainWindow is NewMainWindow nmw) diff --git a/BililiveRecorder.WPF/Program.cs b/BililiveRecorder.WPF/Program.cs index 676f7fc..5fc2c5f 100644 --- a/BililiveRecorder.WPF/Program.cs +++ b/BililiveRecorder.WPF/Program.cs @@ -14,6 +14,7 @@ using BililiveRecorder.Flv.Pipeline; using BililiveRecorder.ToolBox; using Esprima; using Jint.Runtime; +using Microsoft.Toolkit.Uwp.Notifications; using Sentry; using Sentry.Extensibility; using Serilog; @@ -221,6 +222,12 @@ namespace BililiveRecorder.WPF } finally { + try + { + ToastNotificationManagerCompat.Uninstall(); + } + catch (Exception) + { } cancel.Cancel(); #pragma warning disable VSTHRD002 // Avoid problematic synchronous waits update.WaitForUpdatesOnShutdownAsync().GetAwaiter().GetResult(); diff --git a/BililiveRecorder.WPF/StreamStartedNotification.cs b/BililiveRecorder.WPF/StreamStartedNotification.cs new file mode 100644 index 0000000..461e292 --- /dev/null +++ b/BililiveRecorder.WPF/StreamStartedNotification.cs @@ -0,0 +1,81 @@ +using System; +using System.IO; +using System.Net.Http; +using System.Threading.Tasks; +using BililiveRecorder.Core; +using Microsoft.Toolkit.Uwp.Notifications; + +#nullable enable +namespace BililiveRecorder.WPF +{ + internal static class StreamStartedNotification + { + public static async Task ShowAsync(IRoom room) + { + var tempPath = Path.Combine(Path.GetTempPath(), "brec-notifi"); + Uri? cover = null, face = null; + DateTime? time = null; + try + { + Directory.CreateDirectory(tempPath); + + var json = room.RawBilibiliApiJsonData; + + var live_start_time = json?["room_info"]?["live_start_time"]?.ToObject(); + if (live_start_time.HasValue && live_start_time > 0) + { + time = DateTimeOffset.FromUnixTimeSeconds(live_start_time.Value).LocalDateTime; + } + + var coverUrl = json?["room_info"]?["cover"]?.ToObject(); + var faceUrl = json?["anchor_info"]?["base_info"]?["face"]?.ToObject(); + + var coverFile = Path.Combine(tempPath, Path.GetFileName(coverUrl)); + var faceFile = Path.Combine(tempPath, Path.GetFileName(faceUrl)); + + using var client = new HttpClient(); + client.Timeout = TimeSpan.FromSeconds(5); + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.UserAgent.Clear(); + + if (!string.IsNullOrEmpty(faceUrl)) + { + using var faceFs = new FileStream(faceFile, FileMode.Create, FileAccess.Write, FileShare.None); + await (await client.GetStreamAsync(faceUrl).ConfigureAwait(false)).CopyToAsync(faceFs).ConfigureAwait(false); + face = new Uri(faceFile); + } + + if (!string.IsNullOrWhiteSpace(coverUrl)) + { + using var coverFs = new FileStream(coverFile, FileMode.Create, FileAccess.Write, FileShare.None); + await (await client.GetStreamAsync(coverUrl).ConfigureAwait(false)).CopyToAsync(coverFs).ConfigureAwait(false); + cover = new Uri(coverFile); + } + } + catch (Exception) + { } + + var roomUrl = new Uri("https://live.bilibili.com/" + room.RoomConfig.RoomId); + var builder = new ToastContentBuilder() + .AddHeader("BililiveRecorder-StreamStarted", "B站录播姬开播通知", "") + .AddText(room.Name + " 开播了") + .AddText(room.Title) + .AddText($"{room.AreaNameParent} · {room.AreaNameChild}") + .SetProtocolActivation(roomUrl) + .SetToastDuration(ToastDuration.Long) + .AddButton(new ToastButton().SetContent("打开直播间").SetProtocolActivation(roomUrl)) + ; + + if (time.HasValue) + builder.AddCustomTimeStamp(time.Value); + + if (face is not null) + builder.AddAppLogoOverride(face, ToastGenericAppLogoCrop.Circle); + + if (cover is not null) + builder.AddInlineImage(cover); + + builder.Show(); + } + } +}