diff --git a/BililiveRecorder.Core/Api/Danmaku/DanmakuClient.cs b/BililiveRecorder.Core/Api/Danmaku/DanmakuClient.cs index 3d93fac..ac2ccc4 100644 --- a/BililiveRecorder.Core/Api/Danmaku/DanmakuClient.cs +++ b/BililiveRecorder.Core/Api/Danmaku/DanmakuClient.cs @@ -153,7 +153,7 @@ namespace BililiveRecorder.Core.Api.Danmaku } #pragma warning disable VSTHRD100 // Avoid async void methods - private async void SendPingMessageTimerCallback(object sender, ElapsedEventArgs e) + private async void SendPingMessageTimerCallback(object? sender, ElapsedEventArgs e) #pragma warning restore VSTHRD100 // Avoid async void methods { try @@ -248,9 +248,9 @@ namespace BililiveRecorder.Core.Api.Danmaku if (this.danmakuTransport is not { } transport) return; - var playload = ((body?.Length ?? 0) > 0) ? Encoding.UTF8.GetBytes(body) : Array.Empty(); + var payload = Encoding.UTF8.GetBytes(body); const int headerLength = 16; - var totalLength = playload.Length + headerLength; + var totalLength = payload.Length + headerLength; var buffer = ArrayPool.Shared.Rent(totalLength); try @@ -261,8 +261,8 @@ namespace BililiveRecorder.Core.Api.Danmaku BinaryPrimitives.WriteUInt32BigEndian(new Span(buffer, 8, 4), (uint)action); BinaryPrimitives.WriteUInt32BigEndian(new Span(buffer, 12, 4), 1); - if (playload.Length > 0) - Array.Copy(playload, 0, buffer, headerLength, playload.Length); + if (payload.Length > 0) + Array.Copy(payload, 0, buffer, headerLength, payload.Length); await transport.SendAsync(buffer, 0, totalLength).ConfigureAwait(false); } diff --git a/BililiveRecorder.Core/Api/Http/HttpApiClient.cs b/BililiveRecorder.Core/Api/Http/HttpApiClient.cs index 3997901..ce971c5 100644 --- a/BililiveRecorder.Core/Api/Http/HttpApiClient.cs +++ b/BililiveRecorder.Core/Api/Http/HttpApiClient.cs @@ -77,7 +77,7 @@ namespace BililiveRecorder.Core.Api.Http old?.Dispose(); } - private void Config_PropertyChanged(object sender, PropertyChangedEventArgs e) + private void Config_PropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName is (nameof(this.config.Cookie)) or (nameof(this.config.TimingApiTimeout))) this.UpdateHttpClient(); diff --git a/BililiveRecorder.Core/Config/ConfigParser.cs b/BililiveRecorder.Core/Config/ConfigParser.cs index 31ba787..61df8e6 100644 --- a/BililiveRecorder.Core/Config/ConfigParser.cs +++ b/BililiveRecorder.Core/Config/ConfigParser.cs @@ -155,7 +155,7 @@ namespace BililiveRecorder.Core.Config var ext = Path.GetExtension(path); - var tempPath = Path.Combine(Path.GetDirectoryName(path), Path.ChangeExtension(path, RandomString(6) + ext)); + var tempPath = Path.Combine(Path.GetDirectoryName(path)!, Path.ChangeExtension(path, RandomString(6) + ext)); var backupPath = Path.ChangeExtension(path, "backup" + ext); // delete any existing backups diff --git a/BililiveRecorder.Core/Danmaku/BasicDanmakuWriter.cs b/BililiveRecorder.Core/Danmaku/BasicDanmakuWriter.cs index d4e2063..d1939a4 100644 --- a/BililiveRecorder.Core/Danmaku/BasicDanmakuWriter.cs +++ b/BililiveRecorder.Core/Danmaku/BasicDanmakuWriter.cs @@ -58,7 +58,7 @@ namespace BililiveRecorder.Core.Danmaku this.xmlWriter = null; } - try { Directory.CreateDirectory(Path.GetDirectoryName(path)); } catch (Exception) { } + try { Directory.CreateDirectory(Path.GetDirectoryName(path)!); } catch (Exception) { } var stream = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read); this.config = room.RoomConfig; diff --git a/BililiveRecorder.Core/Recorder.cs b/BililiveRecorder.Core/Recorder.cs index 2006558..99c441c 100644 --- a/BililiveRecorder.Core/Recorder.cs +++ b/BililiveRecorder.Core/Recorder.cs @@ -125,48 +125,48 @@ namespace BililiveRecorder.Core #region Events - private void Room_IOStats(object sender, IOStatsEventArgs e) + private void Room_IOStats(object? sender, IOStatsEventArgs e) { - var room = (IRoom)sender; + if (sender is not IRoom room) return; IOStats?.Invoke(this, new AggregatedRoomEventArgs(room, e)); } - private void Room_RecordingStats(object sender, RecordingStatsEventArgs e) + private void Room_RecordingStats(object? sender, RecordingStatsEventArgs e) { - var room = (IRoom)sender; + if (sender is not IRoom room) return; RecordingStats?.Invoke(this, new AggregatedRoomEventArgs(room, e)); } - private void Room_RecordFileClosed(object sender, RecordFileClosedEventArgs e) + private void Room_RecordFileClosed(object? sender, RecordFileClosedEventArgs e) { - var room = (IRoom)sender; + if (sender is not IRoom room) return; _ = Task.Run(async () => await this.basicWebhookV2.SendFileClosedAsync(e).ConfigureAwait(false)); _ = Task.Run(async () => await this.basicWebhookV1.SendAsync(new RecordEndData(e)).ConfigureAwait(false)); RecordFileClosed?.Invoke(this, new AggregatedRoomEventArgs(room, e)); } - private void Room_RecordFileOpening(object sender, RecordFileOpeningEventArgs e) + private void Room_RecordFileOpening(object? sender, RecordFileOpeningEventArgs e) { - var room = (IRoom)sender; + if (sender is not IRoom room) return; _ = Task.Run(async () => await this.basicWebhookV2.SendFileOpeningAsync(e).ConfigureAwait(false)); RecordFileOpening?.Invoke(this, new AggregatedRoomEventArgs(room, e)); } - private void Room_RecordSessionStarted(object sender, RecordSessionStartedEventArgs e) + private void Room_RecordSessionStarted(object? sender, RecordSessionStartedEventArgs e) { - var room = (IRoom)sender; + if (sender is not IRoom room) return; _ = Task.Run(async () => await this.basicWebhookV2.SendSessionStartedAsync(e).ConfigureAwait(false)); RecordSessionStarted?.Invoke(this, new AggregatedRoomEventArgs(room, e)); } - private void Room_RecordSessionEnded(object sender, RecordSessionEndedEventArgs e) + private void Room_RecordSessionEnded(object? sender, RecordSessionEndedEventArgs e) { - var room = (IRoom)sender; + if (sender is not IRoom room) return; _ = Task.Run(async () => await this.basicWebhookV2.SendSessionEndedAsync(e).ConfigureAwait(false)); RecordSessionEnded?.Invoke(this, new AggregatedRoomEventArgs(room, e)); } - private void Room_PropertyChanged(object sender, PropertyChangedEventArgs e) + private void Room_PropertyChanged(object? sender, PropertyChangedEventArgs e) { if (sender is not IRoom room) return; diff --git a/BililiveRecorder.Core/Recording/RawDataRecordTask.cs b/BililiveRecorder.Core/Recording/RawDataRecordTask.cs index c005114..b451cc6 100644 --- a/BililiveRecorder.Core/Recording/RawDataRecordTask.cs +++ b/BililiveRecorder.Core/Recording/RawDataRecordTask.cs @@ -31,7 +31,7 @@ namespace BililiveRecorder.Core.Recording var (fullPath, relativePath) = this.CreateFileName(); try - { Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); } + { Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!); } catch (Exception) { } this.fileOpeningEventArgs = new RecordFileOpeningEventArgs(this.room) @@ -110,12 +110,24 @@ namespace BililiveRecorder.Core.Recording recordFileClosedEvent = null; try - { file.Dispose(); } + { +#if NET6_0_OR_GREATER + await file.DisposeAsync(); +#else + file.Dispose(); +#endif + } catch (Exception ex) { this.logger.Warning(ex, "关闭文件时发生错误"); } try - { stream.Dispose(); } + { +#if NET6_0_OR_GREATER + await stream.DisposeAsync(); +#else + stream.Dispose(); +#endif + } catch (Exception) { } try diff --git a/BililiveRecorder.Core/Recording/RecordTaskBase.cs b/BililiveRecorder.Core/Recording/RecordTaskBase.cs index 1c98620..90c666c 100644 --- a/BililiveRecorder.Core/Recording/RecordTaskBase.cs +++ b/BililiveRecorder.Core/Recording/RecordTaskBase.cs @@ -115,9 +115,19 @@ namespace BililiveRecorder.Core.Recording { try { + if (state is not WeakReference weakRef) + return; + await Task.Delay(1000); - if (((WeakReference)state).TryGetTarget(out var weakStream)) + + if (weakRef.TryGetTarget(out var weakStream)) + { +#if NET6_0_OR_GREATER + await weakStream.DisposeAsync(); +#else weakStream.Dispose(); +#endif + } } catch (Exception) { } @@ -128,7 +138,7 @@ namespace BililiveRecorder.Core.Recording protected abstract void StartRecordingLoop(Stream stream); - private void Timer_Elapsed_TriggerIOStats(object sender, ElapsedEventArgs e) + private void Timer_Elapsed_TriggerIOStats(object? sender, ElapsedEventArgs e) { int networkDownloadBytes, diskWriteBytes; TimeSpan durationDiff, diskWriteDuration; @@ -161,7 +171,7 @@ namespace BililiveRecorder.Core.Recording this.OnIOStats(new IOStatsEventArgs { - StreamHost = streamHost, + StreamHost = this.streamHost, NetworkBytesDownloaded = networkDownloadBytes, Duration = durationDiff, StartTime = startTime, @@ -253,7 +263,7 @@ namespace BililiveRecorder.Core.Recording this.logger.Information("没有符合设置要求的画质,稍后再试。设置画质 {QnSettings}, 可用画质 {AcceptQn}", qns, codecItem.AcceptQn); throw new NoMatchingQnValueException(); - match_qn_success: +match_qn_success: this.logger.Debug("设置画质 {QnSettings}, 可用画质 {AcceptQn}, 最终选择 {SelectedQn}", qns, codecItem.AcceptQn, selected_qn); if (selected_qn != DefaultQn) @@ -373,7 +383,7 @@ namespace BililiveRecorder.Core.Recording request.Headers.Host = originalUri.IsDefaultPort ? originalUri.Host : originalUri.Host + ":" + originalUri.Port; } - sendRequest: +sendRequest: var resp = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, @@ -392,8 +402,8 @@ namespace BililiveRecorder.Core.Recording case HttpStatusCode.Moved: case HttpStatusCode.Redirect: { - fullUrl = new Uri(originalUri, resp.Headers.Location).ToString(); - this.logger.Debug("跳转到 {Url}, 原文本 {Location}", fullUrl, resp.Headers.Location.OriginalString); + fullUrl = new Uri(originalUri, resp.Headers.Location!).ToString(); + this.logger.Debug("跳转到 {Url}, 原文本 {Location}", fullUrl, resp.Headers.Location!.OriginalString); resp.Dispose(); streamHostInfoBuilder.Append('\n'); break; diff --git a/BililiveRecorder.Core/Recording/StandardRecordTask.cs b/BililiveRecorder.Core/Recording/StandardRecordTask.cs index 0343753..13f5b33 100644 --- a/BililiveRecorder.Core/Recording/StandardRecordTask.cs +++ b/BililiveRecorder.Core/Recording/StandardRecordTask.cs @@ -151,7 +151,11 @@ namespace BililiveRecorder.Core.Recording finally { this.timer.Stop(); +#if NET6_0_OR_GREATER + await stream.DisposeAsync().ConfigureAwait(false); +#else stream.Dispose(); +#endif await writer.CompleteAsync(exception).ConfigureAwait(false); } } @@ -265,7 +269,7 @@ namespace BililiveRecorder.Core.Recording } } - private void StatsRule_StatsUpdated(object sender, RecordingStatsEventArgs e) + private void StatsRule_StatsUpdated(object? sender, RecordingStatsEventArgs e) { switch (this.room.RoomConfig.CuttingMode) { @@ -300,7 +304,7 @@ namespace BililiveRecorder.Core.Recording var paths = this.task.CreateFileName(); try - { _ = Directory.CreateDirectory(Path.GetDirectoryName(paths.fullPath)); } + { _ = Directory.CreateDirectory(Path.GetDirectoryName(paths.fullPath)!); } catch (Exception) { } this.last_path = paths.fullPath; @@ -317,7 +321,7 @@ namespace BililiveRecorder.Core.Recording : Path.ChangeExtension(this.last_path, "txt"); try - { _ = Directory.CreateDirectory(Path.GetDirectoryName(path)); } + { _ = Directory.CreateDirectory(Path.GetDirectoryName(path)!); } catch (Exception) { } var stream = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read); diff --git a/BililiveRecorder.Core/Room.cs b/BililiveRecorder.Core/Room.cs index f54de53..a5fb401 100644 --- a/BililiveRecorder.Core/Room.cs +++ b/BililiveRecorder.Core/Room.cs @@ -402,7 +402,7 @@ namespace BililiveRecorder.Core #region Event Handlers /// - private void RecordTask_IOStats(object sender, IOStatsEventArgs e) + private void RecordTask_IOStats(object? sender, IOStatsEventArgs e) { this.logger.Verbose("IO stats: {@stats}", e); @@ -420,7 +420,7 @@ namespace BililiveRecorder.Core } /// - private void RecordTask_RecordingStats(object sender, RecordingStatsEventArgs e) + private void RecordTask_RecordingStats(object? sender, RecordingStatsEventArgs e) { this.logger.Verbose("Recording stats: {@stats}", e); @@ -454,7 +454,7 @@ namespace BililiveRecorder.Core } /// - private void RecordTask_RecordFileClosed(object sender, RecordFileClosedEventArgs e) + private void RecordTask_RecordFileClosed(object? sender, RecordFileClosedEventArgs e) { this.basicDanmakuWriter.Disable(); @@ -462,7 +462,7 @@ namespace BililiveRecorder.Core } /// - private void RecordTask_RecordFileOpening(object sender, RecordFileOpeningEventArgs e) + private void RecordTask_RecordFileOpening(object? sender, RecordFileOpeningEventArgs e) { if (this.RoomConfig.RecordDanmaku) this.basicDanmakuWriter.EnableWithPath(Path.ChangeExtension(e.FullPath, "xml"), this); @@ -481,7 +481,7 @@ namespace BililiveRecorder.Core { const int MAX_ATTEMPT = 3; var attempt = 0; - retry: +retry: try { var coverUrl = this.RawBilibiliApiJsonData?["room_info"]?["cover"]?.ToObject(); @@ -513,7 +513,7 @@ namespace BililiveRecorder.Core } /// - private void RecordTask_RecordSessionEnded(object sender, EventArgs e) + private void RecordTask_RecordSessionEnded(object? sender, EventArgs e) { Guid id; lock (this.recordStartLock) @@ -570,7 +570,7 @@ namespace BililiveRecorder.Core return this.userScriptRunner.CallOnDanmakuHandshake(this.logger, this, json); } - private void DanmakuClient_DanmakuReceived(object sender, Api.Danmaku.DanmakuReceivedEventArgs e) + private void DanmakuClient_DanmakuReceived(object? sender, Api.Danmaku.DanmakuReceivedEventArgs e) { var d = e.Danmaku; @@ -603,7 +603,7 @@ namespace BililiveRecorder.Core _ = Task.Run(async () => await this.basicDanmakuWriter.WriteAsync(d)); } - private void DanmakuClient_StatusChanged(object sender, Api.Danmaku.StatusChangedEventArgs e) + private void DanmakuClient_StatusChanged(object? sender, Api.Danmaku.StatusChangedEventArgs e) { this.DanmakuConnected = e.Connected; if (e.Connected) @@ -622,7 +622,7 @@ namespace BililiveRecorder.Core } } - private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) + private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e) { this.StartDamakuConnection(delay: false); @@ -645,7 +645,7 @@ namespace BililiveRecorder.Core } } - private void Room_PropertyChanged(object sender, PropertyChangedEventArgs e) + private void Room_PropertyChanged(object? sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { @@ -666,7 +666,7 @@ namespace BililiveRecorder.Core } } - private void RoomConfig_PropertyChanged(object sender, PropertyChangedEventArgs e) + private void RoomConfig_PropertyChanged(object? sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { diff --git a/BililiveRecorder.Core/Scripting/Runtime/JintURLSearchParams.cs b/BililiveRecorder.Core/Scripting/Runtime/JintURLSearchParams.cs index 3e3bc90..5e204a4 100644 --- a/BililiveRecorder.Core/Scripting/Runtime/JintURLSearchParams.cs +++ b/BililiveRecorder.Core/Scripting/Runtime/JintURLSearchParams.cs @@ -43,9 +43,9 @@ namespace BililiveRecorder.Core.Scripting.Runtime this.query.Remove(name); } - public string[][] Entries() + public string?[][] Entries() { - return this.query.Select(x => new string[] { x.Name, x.Value.ToString() }).ToArray(); + return this.query.Select(x => new string?[] { x.Name, x.Value.ToString() }).ToArray(); } public void ForEach(FunctionInstance callback, JsValue thisArg) @@ -63,7 +63,7 @@ namespace BililiveRecorder.Core.Scripting.Runtime return this.query.TryGetFirst(name, out var value) ? value.ToString() : null; } - public string[] GetAll(string name) + public string?[] GetAll(string name) { return this.query.GetAll(name).Select(x => x.ToString()).ToArray(); } @@ -93,7 +93,7 @@ namespace BililiveRecorder.Core.Scripting.Runtime return this.query.ToString(); } - public string[] Values() + public string?[] Values() { return this.query.Select(x => x.Value.ToString()).ToArray(); } diff --git a/BililiveRecorder.Core/Templating/FileNameGenerator.cs b/BililiveRecorder.Core/Templating/FileNameGenerator.cs index 331e98a..570f889 100644 --- a/BililiveRecorder.Core/Templating/FileNameGenerator.cs +++ b/BililiveRecorder.Core/Templating/FileNameGenerator.cs @@ -108,7 +108,7 @@ namespace BililiveRecorder.Core.Templating relativePath = template.Render(context); relativePath = RemoveInvalidFileName(relativePath); - fullPath = skipFullPath ? null : Path.GetFullPath(Path.Combine(workDirectory, relativePath)); + fullPath = workDirectory is null ? null : Path.GetFullPath(Path.Combine(workDirectory, relativePath)); if (!skipFullPath && !CheckIsWithinPath(workDirectory!, fullPath!)) { @@ -138,9 +138,9 @@ namespace BililiveRecorder.Core.Templating return new FileNameTemplateOutput(status, errorMessage, relativePath, fullPath); - returnDefaultPath: +returnDefaultPath: var defaultRelativePath = RemoveInvalidFileName(defaultTemplate.Render(context)); - var defaultFullPath = skipFullPath ? null : Path.GetFullPath(Path.Combine(workDirectory, defaultRelativePath)); + var defaultFullPath = workDirectory is null ? null : Path.GetFullPath(Path.Combine(workDirectory, defaultRelativePath)); return new FileNameTemplateOutput(status, errorMessage, defaultRelativePath, defaultFullPath); } @@ -230,7 +230,7 @@ namespace BililiveRecorder.Core.Templating internal static string RemoveInvalidFileName(string input, bool ignore_slash = true) { foreach (var c in Path.GetInvalidFileNameChars()) - if (!ignore_slash || c != '\\' && c != '/') + if (!ignore_slash || (c != '\\' && c != '/')) input = input.Replace(c, '_'); input = invalidDirectoryNameRegex.Replace(input, "$1_$2"); diff --git a/BililiveRecorder.WPF/Controls/RoomCard.xaml.cs b/BililiveRecorder.WPF/Controls/RoomCard.xaml.cs index 04458a1..babc5e3 100644 --- a/BililiveRecorder.WPF/Controls/RoomCard.xaml.cs +++ b/BililiveRecorder.WPF/Controls/RoomCard.xaml.cs @@ -26,7 +26,9 @@ namespace BililiveRecorder.WPF.Controls private void MenuItem_StopRecording_Click(object sender, RoutedEventArgs e) => (this.DataContext as IRoom)?.StopRecord(); +#pragma warning disable VSTHRD110 // Observe result of async calls private void MenuItem_RefreshInfo_Click(object sender, RoutedEventArgs e) => (this.DataContext as IRoom)?.RefreshRoomInfoAsync(); +#pragma warning restore VSTHRD110 // Observe result of async calls private void MenuItem_StartMonitor_Click(object sender, RoutedEventArgs e) { diff --git a/BililiveRecorder.WPF/SingleInstance.cs b/BililiveRecorder.WPF/SingleInstance.cs index 14568ec..f550e62 100644 --- a/BililiveRecorder.WPF/SingleInstance.cs +++ b/BililiveRecorder.WPF/SingleInstance.cs @@ -68,7 +68,9 @@ namespace BililiveRecorder.WPF private class IPCRemoteService : MarshalByRefObject { +#pragma warning disable VSTHRD110 // Observe result of async calls public void Notify() => Application.Current?.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)ActivateFirstInstanceCallback); +#pragma warning restore VSTHRD110 // Observe result of async calls public override object? InitializeLifetimeService() => null; } }