Core: Change visibility of most types to internal

This commit is contained in:
genteure 2022-05-16 23:28:31 +08:00
parent bc12b720a1
commit 730bc9a4d1
75 changed files with 647 additions and 98 deletions

View File

@ -2,7 +2,7 @@ using Newtonsoft.Json;
namespace BililiveRecorder.Core.Api namespace BililiveRecorder.Core.Api
{ {
public class BilibiliApiResponse<T> where T : class internal class BilibiliApiResponse<T> where T : class
{ {
[JsonProperty("code")] [JsonProperty("code")]
public int? Code { get; set; } public int? Code { get; set; }

View File

@ -3,7 +3,7 @@ using System.Runtime.Serialization;
namespace BililiveRecorder.Core.Api namespace BililiveRecorder.Core.Api
{ {
public class BilibiliApiResponseCodeNotZeroException : Exception internal class BilibiliApiResponseCodeNotZeroException : Exception
{ {
public BilibiliApiResponseCodeNotZeroException() { } public BilibiliApiResponseCodeNotZeroException() { }
public BilibiliApiResponseCodeNotZeroException(string message) : base(message) { } public BilibiliApiResponseCodeNotZeroException(string message) : base(message) { }

View File

@ -17,7 +17,7 @@ using Timer = System.Timers.Timer;
namespace BililiveRecorder.Core.Api.Danmaku namespace BililiveRecorder.Core.Api.Danmaku
{ {
public class DanmakuClient : IDanmakuClient, IDisposable internal class DanmakuClient : IDanmakuClient, IDisposable
{ {
private readonly ILogger logger; private readonly ILogger logger;
private readonly IDanmakuServerApiClient apiClient; private readonly IDanmakuServerApiClient apiClient;

View File

@ -3,7 +3,7 @@ using Newtonsoft.Json.Linq;
#nullable enable #nullable enable
namespace BililiveRecorder.Core.Api.Danmaku namespace BililiveRecorder.Core.Api.Danmaku
{ {
public enum DanmakuMsgType internal enum DanmakuMsgType
{ {
/// <summary> /// <summary>
/// 彈幕 /// 彈幕
@ -39,7 +39,7 @@ namespace BililiveRecorder.Core.Api.Danmaku
RoomChange RoomChange
} }
public class DanmakuModel internal class DanmakuModel
{ {
/// <summary> /// <summary>
/// 消息類型 /// 消息類型

View File

@ -1,8 +1,8 @@
using System; using System;
namespace BililiveRecorder.Core.Api.Danmaku namespace BililiveRecorder.Core.Api.Danmaku
{ {
public class DanmakuReceivedEventArgs : EventArgs internal class DanmakuReceivedEventArgs : EventArgs
{ {
public readonly DanmakuModel Danmaku; public readonly DanmakuModel Danmaku;

View File

@ -1,8 +1,8 @@
using System; using System;
namespace BililiveRecorder.Core.Api.Danmaku namespace BililiveRecorder.Core.Api.Danmaku
{ {
public class StatusChangedEventArgs : EventArgs internal class StatusChangedEventArgs : EventArgs
{ {
public static readonly StatusChangedEventArgs True = new StatusChangedEventArgs public static readonly StatusChangedEventArgs True = new StatusChangedEventArgs
{ {

View File

@ -11,7 +11,7 @@ using Newtonsoft.Json.Linq;
namespace BililiveRecorder.Core.Api.Http namespace BililiveRecorder.Core.Api.Http
{ {
public class HttpApiClient : IApiClient, IDanmakuServerApiClient internal class HttpApiClient : IApiClient, IDanmakuServerApiClient, IHttpClientAccessor
{ {
private const string HttpHeaderAccept = "application/json, text/javascript, */*; q=0.01"; private const string HttpHeaderAccept = "application/json, text/javascript, */*; q=0.01";
private const string HttpHeaderOrigin = "https://live.bilibili.com"; private const string HttpHeaderOrigin = "https://live.bilibili.com";

View File

@ -3,7 +3,7 @@ using System.Runtime.Serialization;
namespace BililiveRecorder.Core.Api namespace BililiveRecorder.Core.Api
{ {
public class Http412Exception : Exception internal class Http412Exception : Exception
{ {
public Http412Exception() { } public Http412Exception() { }
public Http412Exception(string message) : base(message) { } public Http412Exception(string message) : base(message) { }

View File

@ -4,7 +4,7 @@ using BililiveRecorder.Core.Api.Model;
namespace BililiveRecorder.Core.Api namespace BililiveRecorder.Core.Api
{ {
public interface IApiClient : IDisposable internal interface IApiClient : IDisposable
{ {
Task<BilibiliApiResponse<RoomInfo>> GetRoomInfoAsync(int roomid); Task<BilibiliApiResponse<RoomInfo>> GetRoomInfoAsync(int roomid);
Task<BilibiliApiResponse<RoomPlayInfo>> GetStreamUrlAsync(int roomid, int qn); Task<BilibiliApiResponse<RoomPlayInfo>> GetStreamUrlAsync(int roomid, int qn);

View File

@ -5,7 +5,7 @@ using static BililiveRecorder.Core.Api.Model.RoomPlayInfo;
namespace BililiveRecorder.Core.Api namespace BililiveRecorder.Core.Api
{ {
public static class IApiClientExtensions internal static class IApiClientExtensions
{ {
public static async Task<CodecItem?> GetCodecItemInStreamUrlAsync(this IApiClient apiClient, int roomid, int qn) public static async Task<CodecItem?> GetCodecItemInStreamUrlAsync(this IApiClient apiClient, int roomid, int qn)
{ {

View File

@ -5,7 +5,7 @@ using BililiveRecorder.Core.Api.Danmaku;
namespace BililiveRecorder.Core.Api namespace BililiveRecorder.Core.Api
{ {
public interface IDanmakuClient : IDisposable internal interface IDanmakuClient : IDisposable
{ {
bool Connected { get; } bool Connected { get; }

View File

@ -4,7 +4,7 @@ using BililiveRecorder.Core.Api.Model;
namespace BililiveRecorder.Core.Api namespace BililiveRecorder.Core.Api
{ {
public interface IDanmakuServerApiClient : IDisposable internal interface IDanmakuServerApiClient : IDisposable
{ {
Task<BilibiliApiResponse<DanmuInfo>> GetDanmakuServerAsync(int roomid); Task<BilibiliApiResponse<DanmuInfo>> GetDanmakuServerAsync(int roomid);
} }

View File

@ -0,0 +1,9 @@
using System.Net.Http;
namespace BililiveRecorder.Core.Api
{
public interface IHttpClientAccessor
{
HttpClient MainHttpClient { get; }
}
}

View File

@ -3,7 +3,7 @@ using Newtonsoft.Json;
namespace BililiveRecorder.Core.Api.Model namespace BililiveRecorder.Core.Api.Model
{ {
public class DanmuInfo internal class DanmuInfo
{ {
[JsonProperty("host_list")] [JsonProperty("host_list")]
public HostListItem[] HostList { get; set; } = Array.Empty<HostListItem>(); public HostListItem[] HostList { get; set; } = Array.Empty<HostListItem>();

View File

@ -3,7 +3,7 @@ using Newtonsoft.Json.Linq;
namespace BililiveRecorder.Core.Api.Model namespace BililiveRecorder.Core.Api.Model
{ {
public class RoomInfo internal class RoomInfo
{ {
[JsonProperty("room_info")] [JsonProperty("room_info")]
public InnerRoomInfo Room { get; set; } = new InnerRoomInfo(); public InnerRoomInfo Room { get; set; } = new InnerRoomInfo();

View File

@ -3,7 +3,7 @@ using Newtonsoft.Json;
namespace BililiveRecorder.Core.Api.Model namespace BililiveRecorder.Core.Api.Model
{ {
public class RoomPlayInfo internal class RoomPlayInfo
{ {
[JsonProperty("live_status")] [JsonProperty("live_status")]
public int LiveStatus { get; set; } public int LiveStatus { get; set; }

View File

@ -2,7 +2,7 @@ using Newtonsoft.Json;
namespace BililiveRecorder.Core.Api.Model namespace BililiveRecorder.Core.Api.Model
{ {
public class UserInfo internal class UserInfo
{ {
[JsonProperty("info")] [JsonProperty("info")]
public InfoClass? Info { get; set; } public InfoClass? Info { get; set; }

View File

@ -4,7 +4,7 @@ using BililiveRecorder.Core.Api.Model;
namespace BililiveRecorder.Core.Api namespace BililiveRecorder.Core.Api
{ {
public static class ModelExtensions internal static class ModelExtensions
{ {
private static readonly Random random = new Random(); private static readonly Random random = new Random();

View File

@ -6,7 +6,7 @@ using Polly.Registry;
namespace BililiveRecorder.Core.Api namespace BililiveRecorder.Core.Api
{ {
public class PolicyWrappedApiClient<T> : IApiClient, IDanmakuServerApiClient, IDisposable where T : class, IApiClient, IDanmakuServerApiClient, IDisposable internal class PolicyWrappedApiClient<T> : IApiClient, IDanmakuServerApiClient, IDisposable where T : class, IApiClient, IDanmakuServerApiClient, IDisposable
{ {
private readonly T client; private readonly T client;
private readonly IReadOnlyPolicyRegistry<string> policies; private readonly IReadOnlyPolicyRegistry<string> policies;

View File

@ -9,7 +9,7 @@ namespace BililiveRecorder.Core.Config.V1
{ {
[Obsolete] [Obsolete]
[JsonObject(memberSerialization: MemberSerialization.OptIn)] [JsonObject(memberSerialization: MemberSerialization.OptIn)]
public class ConfigV1 : INotifyPropertyChanged internal class ConfigV1 : INotifyPropertyChanged
{ {
//private static readonly Logger logger = LogManager.GetCurrentClassLogger(); //private static readonly Logger logger = LogManager.GetCurrentClassLogger();

View File

@ -3,7 +3,7 @@ using Newtonsoft.Json;
namespace BililiveRecorder.Core.Config.V1 namespace BililiveRecorder.Core.Config.V1
{ {
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] [JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class RoomV1 internal class RoomV1
{ {
[JsonProperty("id")] [JsonProperty("id")]
public int Roomid { get; set; } public int Roomid { get; set; }

View File

@ -11,7 +11,7 @@ using Newtonsoft.Json;
namespace BililiveRecorder.Core.Config.V2 namespace BililiveRecorder.Core.Config.V2
{ {
[JsonObject(MemberSerialization.OptIn)] [JsonObject(MemberSerialization.OptIn)]
public sealed partial class RoomConfig : HierarchicalObject<GlobalConfig, RoomConfig> internal sealed partial class RoomConfig : HierarchicalObject<GlobalConfig, RoomConfig>
{ {
/// <summary> /// <summary>
/// 房间号 /// 房间号
@ -169,7 +169,7 @@ namespace BililiveRecorder.Core.Config.V2
} }
[JsonObject(MemberSerialization.OptIn)] [JsonObject(MemberSerialization.OptIn)]
public sealed partial class GlobalConfig : HierarchicalObject<DefaultConfig, GlobalConfig> internal sealed partial class GlobalConfig : HierarchicalObject<DefaultConfig, GlobalConfig>
{ {
/// <summary> /// <summary>
/// 录制模式 /// 录制模式
@ -349,7 +349,7 @@ namespace BililiveRecorder.Core.Config.V2
} }
public sealed partial class DefaultConfig internal sealed partial class DefaultConfig
{ {
public static readonly DefaultConfig Instance = new DefaultConfig(); public static readonly DefaultConfig Instance = new DefaultConfig();
private DefaultConfig() { } private DefaultConfig() { }

View File

@ -6,7 +6,7 @@ using Newtonsoft.Json;
namespace BililiveRecorder.Core.Config.V2 namespace BililiveRecorder.Core.Config.V2
{ {
[Obsolete("Use Config v3")] [Obsolete("Use Config v3")]
public class ConfigV2 : ConfigBase internal class ConfigV2 : ConfigBase
{ {
public override int Version => 2; public override int Version => 2;
@ -21,7 +21,7 @@ namespace BililiveRecorder.Core.Config.V2
} }
[Obsolete("Use Config v3")] [Obsolete("Use Config v3")]
public partial class RoomConfig internal partial class RoomConfig
{ {
public RoomConfig() : base(x => x.AutoMap(p => new[] { "Has" + p.Name })) public RoomConfig() : base(x => x.AutoMap(p => new[] { "Has" + p.Name }))
{ } { }
@ -32,7 +32,7 @@ namespace BililiveRecorder.Core.Config.V2
} }
[Obsolete("Use Config v3")] [Obsolete("Use Config v3")]
public partial class GlobalConfig internal partial class GlobalConfig
{ {
public GlobalConfig() : base(x => x.AutoMap(p => new[] { "Has" + p.Name })) public GlobalConfig() : base(x => x.AutoMap(p => new[] { "Has" + p.Name }))
{ {

View File

@ -4,7 +4,7 @@ using Newtonsoft.Json;
#nullable enable #nullable enable
namespace BililiveRecorder.Core.Config.V3 namespace BililiveRecorder.Core.Config.V3
{ {
public class ConfigV3 : ConfigBase public sealed class ConfigV3 : ConfigBase
{ {
public override int Version => 3; public override int Version => 3;

View File

@ -12,7 +12,7 @@ using Serilog;
#nullable enable #nullable enable
namespace BililiveRecorder.Core.Danmaku namespace BililiveRecorder.Core.Danmaku
{ {
public class BasicDanmakuWriter : IBasicDanmakuWriter internal class BasicDanmakuWriter : IBasicDanmakuWriter
{ {
private static readonly XmlWriterSettings xmlWriterSettings = new XmlWriterSettings private static readonly XmlWriterSettings xmlWriterSettings = new XmlWriterSettings
{ {

View File

@ -4,7 +4,7 @@ using BililiveRecorder.Core.Api.Danmaku;
namespace BililiveRecorder.Core.Danmaku namespace BililiveRecorder.Core.Danmaku
{ {
public interface IBasicDanmakuWriter : IDisposable internal interface IBasicDanmakuWriter : IDisposable
{ {
void Disable(); void Disable();
void EnableWithPath(string path, IRoom room); void EnableWithPath(string path, IRoom room);

View File

@ -38,6 +38,7 @@ namespace BililiveRecorder.DependencyInjection
public static IServiceCollection AddRecorderApiClients(this IServiceCollection services) => services public static IServiceCollection AddRecorderApiClients(this IServiceCollection services) => services
.AddSingleton<HttpApiClient>() .AddSingleton<HttpApiClient>()
.AddSingleton<IHttpClientAccessor>(sp => sp.GetRequiredService<HttpApiClient>())
.AddSingleton<PolicyWrappedApiClient<HttpApiClient>>() .AddSingleton<PolicyWrappedApiClient<HttpApiClient>>()
.AddSingleton<IApiClient>(sp => sp.GetRequiredService<PolicyWrappedApiClient<HttpApiClient>>()) .AddSingleton<IApiClient>(sp => sp.GetRequiredService<PolicyWrappedApiClient<HttpApiClient>>())
.AddSingleton<IDanmakuServerApiClient>(sp => sp.GetRequiredService<PolicyWrappedApiClient<HttpApiClient>>()) .AddSingleton<IDanmakuServerApiClient>(sp => sp.GetRequiredService<PolicyWrappedApiClient<HttpApiClient>>())

View File

@ -2,7 +2,7 @@ using System;
namespace BililiveRecorder.Core.Event namespace BililiveRecorder.Core.Event
{ {
public class AggregatedRoomEventArgs<T> public sealed class AggregatedRoomEventArgs<T>
{ {
public AggregatedRoomEventArgs(IRoom room, T @event) public AggregatedRoomEventArgs(IRoom room, T @event)
{ {

View File

@ -2,7 +2,7 @@ using System;
namespace BililiveRecorder.Core.Event namespace BililiveRecorder.Core.Event
{ {
public class IOStatsEventArgs : EventArgs public sealed class IOStatsEventArgs : EventArgs
{ {
/// <summary> /// <summary>
/// 当前统计区间的开始时间 /// 当前统计区间的开始时间

View File

@ -3,7 +3,7 @@ using Newtonsoft.Json;
namespace BililiveRecorder.Core.Event namespace BililiveRecorder.Core.Event
{ {
public class RecordFileClosedEventArgs : RecordEventArgsBase public sealed class RecordFileClosedEventArgs : RecordEventArgsBase
{ {
public RecordFileClosedEventArgs() { } public RecordFileClosedEventArgs() { }

View File

@ -3,7 +3,7 @@ using Newtonsoft.Json;
namespace BililiveRecorder.Core.Event namespace BililiveRecorder.Core.Event
{ {
public class RecordFileOpeningEventArgs : RecordEventArgsBase public sealed class RecordFileOpeningEventArgs : RecordEventArgsBase
{ {
public RecordFileOpeningEventArgs() { } public RecordFileOpeningEventArgs() { }

View File

@ -1,6 +1,6 @@
namespace BililiveRecorder.Core.Event namespace BililiveRecorder.Core.Event
{ {
public class RecordSessionEndedEventArgs : RecordEventArgsBase public sealed class RecordSessionEndedEventArgs : RecordEventArgsBase
{ {
public RecordSessionEndedEventArgs() { } public RecordSessionEndedEventArgs() { }

View File

@ -1,6 +1,6 @@
namespace BililiveRecorder.Core.Event namespace BililiveRecorder.Core.Event
{ {
public class RecordSessionStartedEventArgs : RecordEventArgsBase public sealed class RecordSessionStartedEventArgs : RecordEventArgsBase
{ {
public RecordSessionStartedEventArgs() { } public RecordSessionStartedEventArgs() { }

View File

@ -2,7 +2,7 @@ using System;
namespace BililiveRecorder.Core.Event namespace BililiveRecorder.Core.Event
{ {
public class RecordingStatsEventArgs : EventArgs public sealed class RecordingStatsEventArgs : EventArgs
{ {
/// <summary> /// <summary>
/// 从录制开始到现在一共经过的时间,毫秒 /// 从录制开始到现在一共经过的时间,毫秒

View File

@ -2,7 +2,7 @@ using BililiveRecorder.Core.Config.V3;
namespace BililiveRecorder.Core namespace BililiveRecorder.Core
{ {
public interface IRoomFactory internal interface IRoomFactory
{ {
IRoom CreateRoom(RoomConfig roomConfig, int initDelayFactor); IRoom CreateRoom(RoomConfig roomConfig, int initDelayFactor);
} }

View File

@ -1,6 +1,6 @@
namespace BililiveRecorder.Core namespace BililiveRecorder.Core
{ {
public class LoggingContext public static class LoggingContext
{ {
public const string RoomId = nameof(RoomId); public const string RoomId = nameof(RoomId);
} }

View File

@ -3,22 +3,11 @@ using System.Runtime.Serialization;
namespace BililiveRecorder.Core namespace BililiveRecorder.Core
{ {
public class NoMatchingQnValueException : Exception internal class NoMatchingQnValueException : Exception
{ {
public NoMatchingQnValueException() public NoMatchingQnValueException() { }
{ public NoMatchingQnValueException(string message) : base(message) { }
} public NoMatchingQnValueException(string message, Exception innerException) : base(message, innerException) { }
protected NoMatchingQnValueException(SerializationInfo info, StreamingContext context) : base(info, context) { }
public NoMatchingQnValueException(string message) : base(message)
{
}
public NoMatchingQnValueException(string message, Exception innerException) : base(message, innerException)
{
}
protected NoMatchingQnValueException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
} }
} }

View File

@ -15,7 +15,7 @@ namespace BililiveRecorder.Core
{ {
private static readonly ILogger logger = Log.ForContext<PollyPolicy>(); private static readonly ILogger logger = Log.ForContext<PollyPolicy>();
public PollyPolicy() internal PollyPolicy()
{ {
this.IpBlockedHttp412CircuitBreakerPolicy = Policy this.IpBlockedHttp412CircuitBreakerPolicy = Policy
.Handle<Http412Exception>() .Handle<Http412Exception>()

View File

@ -4,7 +4,7 @@ using BililiveRecorder.Flv.Pipeline.Actions;
namespace BililiveRecorder.Core.ProcessingRules namespace BililiveRecorder.Core.ProcessingRules
{ {
public class SplitRule : ISimpleProcessingRule internal class SplitRule : ISimpleProcessingRule
{ {
// 0 = none, 1 = after, 2 = before // 0 = none, 1 = after, 2 = before
private int splitFlag = 0; private int splitFlag = 0;

View File

@ -9,7 +9,7 @@ using StructLinq;
namespace BililiveRecorder.Core.ProcessingRules namespace BililiveRecorder.Core.ProcessingRules
{ {
public class StatsRule : ISimpleProcessingRule internal class StatsRule : ISimpleProcessingRule
{ {
public const string SkipStatsKey = nameof(SkipStatsKey); public const string SkipStatsKey = nameof(SkipStatsKey);

View File

@ -11,7 +11,7 @@ using Serilog;
namespace BililiveRecorder.Core namespace BililiveRecorder.Core
{ {
public class Recorder : IRecorder internal class Recorder : IRecorder
{ {
private readonly object lockObject = new object(); private readonly object lockObject = new object();
private readonly ObservableCollection<IRoom> roomCollection; private readonly ObservableCollection<IRoom> roomCollection;

View File

@ -6,7 +6,7 @@ using Serilog;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public class FlvProcessingContextWriterWithFileWriterFactory : IFlvProcessingContextWriterFactory internal class FlvProcessingContextWriterWithFileWriterFactory : IFlvProcessingContextWriterFactory
{ {
private readonly IServiceProvider serviceProvider; private readonly IServiceProvider serviceProvider;

View File

@ -7,7 +7,7 @@ using Serilog;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public class FlvTagReaderFactory : IFlvTagReaderFactory internal class FlvTagReaderFactory : IFlvTagReaderFactory
{ {
private readonly IServiceProvider serviceProvider; private readonly IServiceProvider serviceProvider;

View File

@ -2,7 +2,7 @@ using BililiveRecorder.Flv;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public interface IFlvProcessingContextWriterFactory internal interface IFlvProcessingContextWriterFactory
{ {
IFlvProcessingContextWriter CreateWriter(IFlvWriterTargetProvider targetProvider); IFlvProcessingContextWriter CreateWriter(IFlvWriterTargetProvider targetProvider);
} }

View File

@ -3,7 +3,7 @@ using BililiveRecorder.Flv;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public interface IFlvTagReaderFactory internal interface IFlvTagReaderFactory
{ {
IFlvTagReader CreateFlvTagReader(PipeReader pipeReader); IFlvTagReader CreateFlvTagReader(PipeReader pipeReader);
} }

View File

@ -4,7 +4,7 @@ using BililiveRecorder.Core.Event;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public interface IRecordTask internal interface IRecordTask
{ {
Guid SessionId { get; } Guid SessionId { get; }

View File

@ -1,6 +1,6 @@
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public interface IRecordTaskFactory internal interface IRecordTaskFactory
{ {
IRecordTask CreateRecordTask(IRoom room); IRecordTask CreateRecordTask(IRoom room);
} }

View File

@ -2,7 +2,7 @@ using BililiveRecorder.Flv;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public interface ITagGroupReaderFactory internal interface ITagGroupReaderFactory
{ {
ITagGroupReader CreateTagGroupReader(IFlvTagReader flvTagReader); ITagGroupReader CreateTagGroupReader(IFlvTagReader flvTagReader);
} }

View File

@ -10,7 +10,7 @@ using Serilog;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public class RawDataRecordTask : RecordTaskBase internal class RawDataRecordTask : RecordTaskBase
{ {
private RecordFileOpeningEventArgs? fileOpeningEventArgs; private RecordFileOpeningEventArgs? fileOpeningEventArgs;

View File

@ -17,7 +17,7 @@ using Timer = System.Timers.Timer;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public abstract class RecordTaskBase : IRecordTask internal abstract class RecordTaskBase : IRecordTask
{ {
private const string HttpHeaderAccept = "*/*"; private const string HttpHeaderAccept = "*/*";
private const string HttpHeaderOrigin = "https://live.bilibili.com"; private const string HttpHeaderOrigin = "https://live.bilibili.com";

View File

@ -5,7 +5,7 @@ using Serilog;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public class RecordTaskFactory : IRecordTaskFactory internal class RecordTaskFactory : IRecordTaskFactory
{ {
private readonly ILogger logger; private readonly ILogger logger;
private readonly IServiceProvider serviceProvider; private readonly IServiceProvider serviceProvider;

View File

@ -19,7 +19,7 @@ using Serilog;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public class StandardRecordTask : RecordTaskBase internal class StandardRecordTask : RecordTaskBase
{ {
private readonly IFlvTagReaderFactory flvTagReaderFactory; private readonly IFlvTagReaderFactory flvTagReaderFactory;
private readonly ITagGroupReaderFactory tagGroupReaderFactory; private readonly ITagGroupReaderFactory tagGroupReaderFactory;

View File

@ -3,7 +3,7 @@ using BililiveRecorder.Flv.Grouping;
namespace BililiveRecorder.Core.Recording namespace BililiveRecorder.Core.Recording
{ {
public class TagGroupReaderFactory : ITagGroupReaderFactory internal class TagGroupReaderFactory : ITagGroupReaderFactory
{ {
public ITagGroupReader CreateTagGroupReader(IFlvTagReader flvTagReader) => public ITagGroupReader CreateTagGroupReader(IFlvTagReader flvTagReader) =>
new TagGroupReader(flvTagReader); new TagGroupReader(flvTagReader);

View File

@ -1,6 +1,6 @@
namespace BililiveRecorder.Core namespace BililiveRecorder.Core
{ {
public enum RestartRecordingReason internal enum RestartRecordingReason
{ {
/// <summary> /// <summary>
/// 普通重试 /// 普通重试

View File

@ -19,7 +19,7 @@ using Timer = System.Timers.Timer;
namespace BililiveRecorder.Core namespace BililiveRecorder.Core
{ {
public class Room : IRoom internal class Room : IRoom
{ {
private readonly object recordStartLock = new object(); private readonly object recordStartLock = new object();
private readonly SemaphoreSlim recordRetryDelaySemaphoreSlim = new SemaphoreSlim(1, 1); private readonly SemaphoreSlim recordRetryDelaySemaphoreSlim = new SemaphoreSlim(1, 1);
@ -51,7 +51,7 @@ namespace BililiveRecorder.Core
private DateTimeOffset danmakuClientConnectTime; private DateTimeOffset danmakuClientConnectTime;
private static readonly TimeSpan danmakuClientReconnectNoDelay = TimeSpan.FromMinutes(1); private static readonly TimeSpan danmakuClientReconnectNoDelay = TimeSpan.FromMinutes(1);
public Room(IServiceScope scope, RoomConfig roomConfig, int initDelayFactor, ILogger logger, IDanmakuClient danmakuClient, IApiClient apiClient, IBasicDanmakuWriter basicDanmakuWriter, IRecordTaskFactory recordTaskFactory) internal Room(IServiceScope scope, RoomConfig roomConfig, int initDelayFactor, ILogger logger, IDanmakuClient danmakuClient, IApiClient apiClient, IBasicDanmakuWriter basicDanmakuWriter, IRecordTaskFactory recordTaskFactory)
{ {
this.scope = scope ?? throw new ArgumentNullException(nameof(scope)); this.scope = scope ?? throw new ArgumentNullException(nameof(scope));
this.RoomConfig = roomConfig ?? throw new ArgumentNullException(nameof(roomConfig)); this.RoomConfig = roomConfig ?? throw new ArgumentNullException(nameof(roomConfig));

View File

@ -4,7 +4,7 @@ using Microsoft.Extensions.DependencyInjection;
namespace BililiveRecorder.Core namespace BililiveRecorder.Core
{ {
public class RoomFactory : IRoomFactory internal class RoomFactory : IRoomFactory
{ {
private readonly IServiceProvider serviceProvider; private readonly IServiceProvider serviceProvider;

View File

@ -15,7 +15,7 @@ using Serilog.Events;
namespace BililiveRecorder.Core.Scripting.Runtime namespace BililiveRecorder.Core.Scripting.Runtime
{ {
public class JintConsole : ObjectInstance internal class JintConsole : ObjectInstance
{ {
private readonly ILogger logger; private readonly ILogger logger;

View File

@ -10,7 +10,7 @@ using Jint.Runtime.Interop;
namespace BililiveRecorder.Core.Scripting.Runtime namespace BililiveRecorder.Core.Scripting.Runtime
{ {
public class JintDns : ObjectInstance internal class JintDns : ObjectInstance
{ {
public JintDns(Engine engine) : base(engine) public JintDns(Engine engine) : base(engine)
{ {

View File

@ -9,7 +9,7 @@ using Jint.Runtime.Interop;
namespace BililiveRecorder.Core.Scripting.Runtime namespace BililiveRecorder.Core.Scripting.Runtime
{ {
public class JintDotnet : ObjectInstance internal class JintDotnet : ObjectInstance
{ {
public JintDotnet(Engine engine) : base(engine) public JintDotnet(Engine engine) : base(engine)
{ {

View File

@ -9,7 +9,7 @@ using Jint.Runtime;
namespace BililiveRecorder.Core.Scripting.Runtime namespace BililiveRecorder.Core.Scripting.Runtime
{ {
public class JintFetchSync : FunctionInstance internal class JintFetchSync : FunctionInstance
{ {
private static readonly JsString functionName = new JsString("fetchSync"); private static readonly JsString functionName = new JsString("fetchSync");

View File

@ -9,7 +9,7 @@ using Serilog;
namespace BililiveRecorder.Core.SimpleWebhook namespace BililiveRecorder.Core.SimpleWebhook
{ {
public class BasicWebhookV1 internal class BasicWebhookV1
{ {
private static readonly ILogger logger = Log.ForContext<BasicWebhookV1>(); private static readonly ILogger logger = Log.ForContext<BasicWebhookV1>();

View File

@ -10,7 +10,7 @@ using Serilog;
namespace BililiveRecorder.Core.SimpleWebhook namespace BililiveRecorder.Core.SimpleWebhook
{ {
public class BasicWebhookV2 internal class BasicWebhookV2
{ {
private static readonly ILogger logger = Log.ForContext<BasicWebhookV2>(); private static readonly ILogger logger = Log.ForContext<BasicWebhookV2>();

View File

@ -4,12 +4,32 @@ using Newtonsoft.Json.Converters;
namespace BililiveRecorder.Core.SimpleWebhook namespace BililiveRecorder.Core.SimpleWebhook
{ {
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public enum EventType internal enum EventType
{ {
Unknown, Unknown,
/// <summary>
/// 录制开始
/// </summary>
SessionStarted, SessionStarted,
/// <summary>
/// 录制结束
/// </summary>
SessionEnded, SessionEnded,
/// <summary>
/// 新建了文件
/// </summary>
FileOpening, FileOpening,
/// <summary>
/// 文件写入结束
/// </summary>
FileClosed, FileClosed,
/// <summary>
/// 直播开始
/// </summary>
StreamStarted,
/// <summary>
/// 直播结束
/// </summary>
StreamEnded,
} }
} }

View File

@ -2,7 +2,7 @@ using System;
namespace BililiveRecorder.Core.SimpleWebhook namespace BililiveRecorder.Core.SimpleWebhook
{ {
public class EventWrapper<T> where T : class internal class EventWrapper<T> where T : class
{ {
public EventWrapper() public EventWrapper()
{ {

View File

@ -4,7 +4,7 @@ using BililiveRecorder.Core.Event;
#nullable enable #nullable enable
namespace BililiveRecorder.Core.SimpleWebhook namespace BililiveRecorder.Core.SimpleWebhook
{ {
public class RecordEndData internal class RecordEndData
{ {
public RecordEndData(RecordFileClosedEventArgs args) public RecordEndData(RecordFileClosedEventArgs args)
{ {

View File

@ -5,7 +5,7 @@ using Fluid.Values;
namespace BililiveRecorder.Core.Templating namespace BililiveRecorder.Core.Templating
{ {
public static class StreamQualityNumber internal static class StreamQualityNumber
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string MapToString(int qn) => qn switch public static string MapToString(int qn) => qn switch
@ -22,7 +22,6 @@ namespace BililiveRecorder.Core.Templating
_ => $"未知({qn})" _ => $"未知({qn})"
}; };
public static ValueTask<FluidValue> MapToStringFilterDelegateAsync(FluidValue input, FilterArguments arguments, TemplateContext context) public static ValueTask<FluidValue> MapToStringFilterDelegateAsync(FluidValue input, FilterArguments arguments, TemplateContext context)
=> new StringValue(MapToString((int)input.ToNumberValue())); => new StringValue(MapToString((int)input.ToNumberValue()));
} }

View File

@ -28,7 +28,7 @@
</ContextMenu> </ContextMenu>
<DataTemplate x:Key="RoomCardStatsPopup" <DataTemplate x:Key="RoomCardStatsPopup"
xmlns:core="clr-namespace:BililiveRecorder.Core;assembly=BililiveRecorder.Core" xmlns:core="clr-namespace:BililiveRecorder.Core;assembly=BililiveRecorder.Core"
DataType="{x:Type core:Room}"> DataType="{x:Type core:IRoom}">
<Grid l:ResxLocalizationProvider.DefaultDictionary="Strings"> <Grid l:ResxLocalizationProvider.DefaultDictionary="Strings">
<TextBlock Visibility="{Binding Stats.DurationRatio,Converter={StaticResource IsNaNToVisibilityCollapsedConverter}}" <TextBlock Visibility="{Binding Stats.DurationRatio,Converter={StaticResource IsNaNToVisibilityCollapsedConverter}}"
TextAlignment="Center" Text="{l:Loc RoomCard_Status_SpeedIndicator_NoData}"/> TextAlignment="Center" Text="{l:Loc RoomCard_Status_SpeedIndicator_NoData}"/>

View File

@ -45,7 +45,7 @@
<Separator Grid.Row="1" Grid.ColumnSpan="2" /> <Separator Grid.Row="1" Grid.ColumnSpan="2" />
<ItemsControl Grid.Row="2" Grid.ColumnSpan="2" Margin="10,0,10,10" ItemsSource="{Binding Recorder.Rooms, Mode=OneWay}"> <ItemsControl Grid.Row="2" Grid.ColumnSpan="2" Margin="10,0,10,10" ItemsSource="{Binding Recorder.Rooms, Mode=OneWay}">
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type core:Room}"> <DataTemplate DataType="{x:Type core:IRoom}">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,5,0,0"> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,5,0,0">
<ui:PathIcon Width="15" Style="{StaticResource PathIconDataAccessPoint}" <ui:PathIcon Width="15" Style="{StaticResource PathIconDataAccessPoint}"
Foreground="{Binding Streaming,Converter={StaticResource BooleanToLiveStatusColorBrushConverter}}"/> Foreground="{Binding Streaming,Converter={StaticResource BooleanToLiveStatusColorBrushConverter}}"/>

View File

@ -24,10 +24,11 @@ namespace BililiveRecorder.WPF.Models
{ {
ExecuteDelegate = _ => ExecuteDelegate = _ =>
{ {
if (this.policy != null) if (this.policy is { } p)
{ {
this.policy.IpBlockedHttp412CircuitBreakerPolicy.Reset(); p.IpBlockedHttp412CircuitBreakerPolicy.Reset();
this.policy.RequestFailedCircuitBreakerPolicy.Reset(); p.RequestFailedCircuitBreakerPolicy.Reset();
p.memoryCache.Compact(1);
} }
} }
}; };

View File

@ -2,7 +2,7 @@ using System;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using BililiveRecorder.Core.Api.Http; using BililiveRecorder.Core.Api;
using BililiveRecorder.Core.Scripting; using BililiveRecorder.Core.Scripting;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Serilog; using Serilog;
@ -16,10 +16,10 @@ namespace BililiveRecorder.WPF.Pages
public partial class AdvancedSettingsPage public partial class AdvancedSettingsPage
{ {
private static readonly ILogger logger = Log.ForContext<AdvancedSettingsPage>(); private static readonly ILogger logger = Log.ForContext<AdvancedSettingsPage>();
private readonly HttpApiClient? httpApiClient; private readonly IHttpClientAccessor? httpApiClient;
private readonly UserScriptRunner? userScriptRunner; private readonly UserScriptRunner? userScriptRunner;
public AdvancedSettingsPage(HttpApiClient? httpApiClient, UserScriptRunner? userScriptRunner) public AdvancedSettingsPage(IHttpClientAccessor? httpApiClient, UserScriptRunner? userScriptRunner)
{ {
this.InitializeComponent(); this.InitializeComponent();
this.httpApiClient = httpApiClient; this.httpApiClient = httpApiClient;
@ -28,7 +28,7 @@ namespace BililiveRecorder.WPF.Pages
public AdvancedSettingsPage() public AdvancedSettingsPage()
: this( : this(
(HttpApiClient?)(RootPage.ServiceProvider?.GetService(typeof(HttpApiClient))), (IHttpClientAccessor?)(RootPage.ServiceProvider?.GetService(typeof(IHttpClientAccessor))),
(UserScriptRunner?)(RootPage.ServiceProvider?.GetService(typeof(UserScriptRunner))) (UserScriptRunner?)(RootPage.ServiceProvider?.GetService(typeof(UserScriptRunner)))
) )
{ } { }

View File

@ -280,7 +280,7 @@ namespace BililiveRecorder.WPF
private class SentryEventProcessor : ISentryEventProcessor private class SentryEventProcessor : ISentryEventProcessor
{ {
private static readonly string JintConsole = typeof(Core.Scripting.Runtime.JintConsole).FullName; private const string JintConsole = "Core.Scripting.Runtime.JintConsole";
private static readonly string UserScriptRunner = typeof(Core.Scripting.UserScriptRunner).FullName; private static readonly string UserScriptRunner = typeof(Core.Scripting.UserScriptRunner).FullName;
public SentryEvent? Process(SentryEvent e) => (e?.Logger == JintConsole || e?.Logger == UserScriptRunner) ? null : e; public SentryEvent? Process(SentryEvent e) => (e?.Logger == JintConsole || e?.Logger == UserScriptRunner) ? null : e;
} }

View File

@ -9,6 +9,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="PublicApiGenerator" Version="10.3.0" />
<PackageReference Include="Spectre.Verify.Extensions" Version="0.5.0" />
<PackageReference Include="Verify.Xunit" Version="13.3.1" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@ -0,0 +1,491 @@
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("BililiveRecorder.Core.UnitTests")]
[assembly: System.Runtime.Versioning.TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName="")]
namespace BililiveRecorder.Core.Api
{
public interface IHttpClientAccessor
{
System.Net.Http.HttpClient MainHttpClient { get; }
}
}
namespace BililiveRecorder.Core.Config
{
public enum AllowedAddressFamily
{
System = -1,
Any = 0,
Ipv4 = 1,
Ipv6 = 2,
}
[Newtonsoft.Json.JsonConverter(typeof(JsonSubTypes.JsonSubtypes?), new object?[]?[] {
"Version"})]
public abstract class ConfigBase
{
protected ConfigBase() { }
[Newtonsoft.Json.JsonProperty("$schema", Order=-2)]
public string? DollarSignSchema { get; set; }
[Newtonsoft.Json.JsonProperty("version")]
public virtual int Version { get; set; }
}
public class ConfigParser
{
public const string CONFIG_FILE_NAME = "config.json";
public ConfigParser() { }
public static BililiveRecorder.Core.Config.V3.ConfigV3? LoadFrom(string directory) { }
public static BililiveRecorder.Core.Config.V3.ConfigV3? LoadJson(string json) { }
public static string? SaveJson(BililiveRecorder.Core.Config.V3.ConfigV3 config) { }
public static bool SaveTo(string directory, BililiveRecorder.Core.Config.V3.ConfigV3 config) { }
public static void WriteAllTextWithBackup(string path, string contents) { }
}
public enum CuttingMode
{
Disabled = 0,
ByTime = 1,
BySize = 2,
}
public enum RecordMode
{
Standard = 0,
RawData = 1,
}
}
namespace BililiveRecorder.Core.Config.V3
{
public sealed class ConfigV3 : BililiveRecorder.Core.Config.ConfigBase
{
public ConfigV3() { }
[Newtonsoft.Json.JsonIgnore]
public bool DisableConfigSave { get; set; }
[Newtonsoft.Json.JsonProperty("global")]
public BililiveRecorder.Core.Config.V3.GlobalConfig Global { get; set; }
[Newtonsoft.Json.JsonProperty("rooms")]
public System.Collections.Generic.List<BililiveRecorder.Core.Config.V3.RoomConfig> Rooms { get; set; }
public override int Version { get; }
}
public sealed class DefaultConfig
{
public static readonly BililiveRecorder.Core.Config.V3.DefaultConfig Instance;
public string Cookie { get; }
public BililiveRecorder.Core.Config.CuttingMode CuttingMode { get; }
public uint CuttingNumber { get; }
public string FileNameRecordTemplate { get; }
public string LiveApiHost { get; }
public BililiveRecorder.Core.Config.AllowedAddressFamily NetworkTransportAllowedAddressFamily { get; }
public bool NetworkTransportUseSystemProxy { get; }
public bool RecordDanmaku { get; }
public uint RecordDanmakuFlushInterval { get; }
public bool RecordDanmakuGift { get; }
public bool RecordDanmakuGuard { get; }
public bool RecordDanmakuRaw { get; }
public bool RecordDanmakuSuperChat { get; }
public BililiveRecorder.Core.Config.RecordMode RecordMode { get; }
public string RecordingQuality { get; }
public uint TimingCheckInterval { get; }
public uint TimingDanmakuRetry { get; }
public uint TimingStreamConnect { get; }
public uint TimingStreamRetry { get; }
public uint TimingStreamRetryNoQn { get; }
public uint TimingWatchdogTimeout { get; }
public string UserScript { get; }
public string WebHookUrls { get; }
public string WebHookUrlsV2 { get; }
public bool WpfShowTitleAndArea { get; }
}
[Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
public sealed class GlobalConfig : HierarchicalPropertyDefault.HierarchicalObject<BililiveRecorder.Core.Config.V3.DefaultConfig, BililiveRecorder.Core.Config.V3.GlobalConfig>
{
public GlobalConfig() { }
public string? Cookie { get; set; }
public BililiveRecorder.Core.Config.CuttingMode CuttingMode { get; set; }
public uint CuttingNumber { get; set; }
public string? FileNameRecordTemplate { get; set; }
public bool HasCookie { get; set; }
public bool HasCuttingMode { get; set; }
public bool HasCuttingNumber { get; set; }
public bool HasFileNameRecordTemplate { get; set; }
public bool HasLiveApiHost { get; set; }
public bool HasNetworkTransportAllowedAddressFamily { get; set; }
public bool HasNetworkTransportUseSystemProxy { get; set; }
public bool HasRecordDanmaku { get; set; }
public bool HasRecordDanmakuFlushInterval { get; set; }
public bool HasRecordDanmakuGift { get; set; }
public bool HasRecordDanmakuGuard { get; set; }
public bool HasRecordDanmakuRaw { get; set; }
public bool HasRecordDanmakuSuperChat { get; set; }
public bool HasRecordMode { get; set; }
public bool HasRecordingQuality { get; set; }
public bool HasTimingCheckInterval { get; set; }
public bool HasTimingDanmakuRetry { get; set; }
public bool HasTimingStreamConnect { get; set; }
public bool HasTimingStreamRetry { get; set; }
public bool HasTimingStreamRetryNoQn { get; set; }
public bool HasTimingWatchdogTimeout { get; set; }
public bool HasUserScript { get; set; }
public bool HasWebHookUrls { get; set; }
public bool HasWebHookUrlsV2 { get; set; }
public bool HasWpfShowTitleAndArea { get; set; }
public string? LiveApiHost { get; set; }
public BililiveRecorder.Core.Config.AllowedAddressFamily NetworkTransportAllowedAddressFamily { get; set; }
public bool NetworkTransportUseSystemProxy { get; set; }
[Newtonsoft.Json.JsonProperty("Cookie")]
public HierarchicalPropertyDefault.Optional<string?> OptionalCookie { get; set; }
[Newtonsoft.Json.JsonProperty("CuttingMode")]
public HierarchicalPropertyDefault.Optional<BililiveRecorder.Core.Config.CuttingMode> OptionalCuttingMode { get; set; }
[Newtonsoft.Json.JsonProperty("CuttingNumber")]
public HierarchicalPropertyDefault.Optional<uint> OptionalCuttingNumber { get; set; }
[Newtonsoft.Json.JsonProperty("FileNameRecordTemplate")]
public HierarchicalPropertyDefault.Optional<string?> OptionalFileNameRecordTemplate { get; set; }
[Newtonsoft.Json.JsonProperty("LiveApiHost")]
public HierarchicalPropertyDefault.Optional<string?> OptionalLiveApiHost { get; set; }
[Newtonsoft.Json.JsonProperty("NetworkTransportAllowedAddressFamily")]
public HierarchicalPropertyDefault.Optional<BililiveRecorder.Core.Config.AllowedAddressFamily> OptionalNetworkTransportAllowedAddressFamily { get; set; }
[Newtonsoft.Json.JsonProperty("NetworkTransportUseSystemProxy")]
public HierarchicalPropertyDefault.Optional<bool> OptionalNetworkTransportUseSystemProxy { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmaku")]
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmaku { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmakuFlushInterval")]
public HierarchicalPropertyDefault.Optional<uint> OptionalRecordDanmakuFlushInterval { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmakuGift")]
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmakuGift { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmakuGuard")]
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmakuGuard { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmakuRaw")]
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmakuRaw { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmakuSuperChat")]
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmakuSuperChat { get; set; }
[Newtonsoft.Json.JsonProperty("RecordMode")]
public HierarchicalPropertyDefault.Optional<BililiveRecorder.Core.Config.RecordMode> OptionalRecordMode { get; set; }
[Newtonsoft.Json.JsonProperty("RecordingQuality")]
public HierarchicalPropertyDefault.Optional<string?> OptionalRecordingQuality { get; set; }
[Newtonsoft.Json.JsonProperty("TimingCheckInterval")]
public HierarchicalPropertyDefault.Optional<uint> OptionalTimingCheckInterval { get; set; }
[Newtonsoft.Json.JsonProperty("TimingDanmakuRetry")]
public HierarchicalPropertyDefault.Optional<uint> OptionalTimingDanmakuRetry { get; set; }
[Newtonsoft.Json.JsonProperty("TimingStreamConnect")]
public HierarchicalPropertyDefault.Optional<uint> OptionalTimingStreamConnect { get; set; }
[Newtonsoft.Json.JsonProperty("TimingStreamRetry")]
public HierarchicalPropertyDefault.Optional<uint> OptionalTimingStreamRetry { get; set; }
[Newtonsoft.Json.JsonProperty("TimingStreamRetryNoQn")]
public HierarchicalPropertyDefault.Optional<uint> OptionalTimingStreamRetryNoQn { get; set; }
[Newtonsoft.Json.JsonProperty("TimingWatchdogTimeout")]
public HierarchicalPropertyDefault.Optional<uint> OptionalTimingWatchdogTimeout { get; set; }
[Newtonsoft.Json.JsonProperty("UserScript")]
public HierarchicalPropertyDefault.Optional<string> OptionalUserScript { get; set; }
[Newtonsoft.Json.JsonProperty("WebHookUrls")]
public HierarchicalPropertyDefault.Optional<string?> OptionalWebHookUrls { get; set; }
[Newtonsoft.Json.JsonProperty("WebHookUrlsV2")]
public HierarchicalPropertyDefault.Optional<string?> OptionalWebHookUrlsV2 { get; set; }
[Newtonsoft.Json.JsonProperty("WpfShowTitleAndArea")]
public HierarchicalPropertyDefault.Optional<bool> OptionalWpfShowTitleAndArea { get; set; }
public bool RecordDanmaku { get; set; }
public uint RecordDanmakuFlushInterval { get; set; }
public bool RecordDanmakuGift { get; set; }
public bool RecordDanmakuGuard { get; set; }
public bool RecordDanmakuRaw { get; set; }
public bool RecordDanmakuSuperChat { get; set; }
public BililiveRecorder.Core.Config.RecordMode RecordMode { get; set; }
public string? RecordingQuality { get; set; }
public uint TimingCheckInterval { get; set; }
public uint TimingDanmakuRetry { get; set; }
public uint TimingStreamConnect { get; set; }
public uint TimingStreamRetry { get; set; }
public uint TimingStreamRetryNoQn { get; set; }
public uint TimingWatchdogTimeout { get; set; }
public string UserScript { get; set; }
public string? WebHookUrls { get; set; }
public string? WebHookUrlsV2 { get; set; }
public string? WorkDirectory { get; set; }
public bool WpfShowTitleAndArea { get; set; }
}
[Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
public sealed class RoomConfig : HierarchicalPropertyDefault.HierarchicalObject<BililiveRecorder.Core.Config.V3.GlobalConfig, BililiveRecorder.Core.Config.V3.RoomConfig>
{
public RoomConfig() { }
public bool AutoRecord { get; set; }
public string? Cookie { get; }
public BililiveRecorder.Core.Config.CuttingMode CuttingMode { get; set; }
public uint CuttingNumber { get; set; }
public string? FileNameRecordTemplate { get; }
public bool HasAutoRecord { get; set; }
public bool HasCuttingMode { get; set; }
public bool HasCuttingNumber { get; set; }
public bool HasRecordDanmaku { get; set; }
public bool HasRecordDanmakuGift { get; set; }
public bool HasRecordDanmakuGuard { get; set; }
public bool HasRecordDanmakuRaw { get; set; }
public bool HasRecordDanmakuSuperChat { get; set; }
public bool HasRecordMode { get; set; }
public bool HasRecordingQuality { get; set; }
public bool HasRoomId { get; set; }
public string? LiveApiHost { get; }
public BililiveRecorder.Core.Config.AllowedAddressFamily NetworkTransportAllowedAddressFamily { get; }
public bool NetworkTransportUseSystemProxy { get; }
[Newtonsoft.Json.JsonProperty("AutoRecord")]
public HierarchicalPropertyDefault.Optional<bool> OptionalAutoRecord { get; set; }
[Newtonsoft.Json.JsonProperty("CuttingMode")]
public HierarchicalPropertyDefault.Optional<BililiveRecorder.Core.Config.CuttingMode> OptionalCuttingMode { get; set; }
[Newtonsoft.Json.JsonProperty("CuttingNumber")]
public HierarchicalPropertyDefault.Optional<uint> OptionalCuttingNumber { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmaku")]
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmaku { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmakuGift")]
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmakuGift { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmakuGuard")]
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmakuGuard { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmakuRaw")]
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmakuRaw { get; set; }
[Newtonsoft.Json.JsonProperty("RecordDanmakuSuperChat")]
public HierarchicalPropertyDefault.Optional<bool> OptionalRecordDanmakuSuperChat { get; set; }
[Newtonsoft.Json.JsonProperty("RecordMode")]
public HierarchicalPropertyDefault.Optional<BililiveRecorder.Core.Config.RecordMode> OptionalRecordMode { get; set; }
[Newtonsoft.Json.JsonProperty("RecordingQuality")]
public HierarchicalPropertyDefault.Optional<string?> OptionalRecordingQuality { get; set; }
[Newtonsoft.Json.JsonProperty("RoomId")]
public HierarchicalPropertyDefault.Optional<int> OptionalRoomId { get; set; }
public bool RecordDanmaku { get; set; }
public uint RecordDanmakuFlushInterval { get; }
public bool RecordDanmakuGift { get; set; }
public bool RecordDanmakuGuard { get; set; }
public bool RecordDanmakuRaw { get; set; }
public bool RecordDanmakuSuperChat { get; set; }
public BililiveRecorder.Core.Config.RecordMode RecordMode { get; set; }
public string? RecordingQuality { get; set; }
public int RoomId { get; set; }
public uint TimingCheckInterval { get; }
public uint TimingDanmakuRetry { get; }
public uint TimingStreamConnect { get; }
public uint TimingStreamRetry { get; }
public uint TimingStreamRetryNoQn { get; }
public uint TimingWatchdogTimeout { get; }
public string UserScript { get; }
public string? WebHookUrls { get; }
public string? WebHookUrlsV2 { get; }
public string? WorkDirectory { get; }
public bool WpfShowTitleAndArea { get; }
}
}
namespace BililiveRecorder.Core.Event
{
public sealed class AggregatedRoomEventArgs<T>
{
public AggregatedRoomEventArgs(BililiveRecorder.Core.IRoom room, T @event) { }
public T Event { get; }
public BililiveRecorder.Core.IRoom Room { get; }
}
public sealed class IOStatsEventArgs : System.EventArgs
{
public IOStatsEventArgs() { }
public int DiskBytesWritten { get; set; }
public double DiskMBps { get; set; }
public System.TimeSpan DiskWriteDuration { get; set; }
public System.TimeSpan Duration { get; set; }
public System.DateTimeOffset EndTime { get; set; }
public int NetworkBytesDownloaded { get; set; }
public double NetworkMbps { get; set; }
public System.DateTimeOffset StartTime { get; set; }
}
public abstract class RecordEventArgsBase : System.EventArgs
{
public RecordEventArgsBase() { }
public RecordEventArgsBase(BililiveRecorder.Core.IRoom room) { }
public string AreaNameChild { get; set; }
public string AreaNameParent { get; set; }
public string Name { get; set; }
public int RoomId { get; set; }
public System.Guid SessionId { get; set; }
public int ShortId { get; set; }
public string Title { get; set; }
}
public sealed class RecordFileClosedEventArgs : BililiveRecorder.Core.Event.RecordEventArgsBase
{
public RecordFileClosedEventArgs() { }
public RecordFileClosedEventArgs(BililiveRecorder.Core.IRoom room) { }
public double Duration { get; set; }
public System.DateTimeOffset FileCloseTime { get; set; }
public System.DateTimeOffset FileOpenTime { get; set; }
public long FileSize { get; set; }
[Newtonsoft.Json.JsonIgnore]
public string FullPath { get; set; }
public string RelativePath { get; set; }
}
public sealed class RecordFileOpeningEventArgs : BililiveRecorder.Core.Event.RecordEventArgsBase
{
public RecordFileOpeningEventArgs() { }
public RecordFileOpeningEventArgs(BililiveRecorder.Core.IRoom room) { }
public System.DateTimeOffset FileOpenTime { get; set; }
[Newtonsoft.Json.JsonIgnore]
public string FullPath { get; set; }
public string RelativePath { get; set; }
}
public sealed class RecordSessionEndedEventArgs : BililiveRecorder.Core.Event.RecordEventArgsBase
{
public RecordSessionEndedEventArgs() { }
public RecordSessionEndedEventArgs(BililiveRecorder.Core.IRoom room) { }
}
public sealed class RecordSessionStartedEventArgs : BililiveRecorder.Core.Event.RecordEventArgsBase
{
public RecordSessionStartedEventArgs() { }
public RecordSessionStartedEventArgs(BililiveRecorder.Core.IRoom room) { }
}
public sealed class RecordingStatsEventArgs : System.EventArgs
{
public RecordingStatsEventArgs() { }
public double AddedDuration { get; set; }
public long CurrentFileSize { get; set; }
public double DurationRatio { get; set; }
public int FileMaxTimestamp { get; set; }
public long InputAudioBytes { get; set; }
public long InputVideoBytes { get; set; }
public long OutputAudioBytes { get; set; }
public int OutputAudioFrames { get; set; }
public long OutputVideoBytes { get; set; }
public int OutputVideoFrames { get; set; }
public double PassedTime { get; set; }
public double SessionDuration { get; set; }
public int SessionMaxTimestamp { get; set; }
public long TotalInputAudioBytes { get; set; }
public long TotalInputBytes { get; set; }
public long TotalInputVideoBytes { get; set; }
public long TotalOutputAudioBytes { get; set; }
public int TotalOutputAudioFrames { get; set; }
public long TotalOutputBytes { get; set; }
public long TotalOutputVideoBytes { get; set; }
public int TotalOutputVideoFrames { get; set; }
}
}
namespace BililiveRecorder.Core
{
public interface IRecorder : System.ComponentModel.INotifyPropertyChanged, System.IDisposable
{
BililiveRecorder.Core.Config.V3.ConfigV3 Config { get; }
System.Collections.ObjectModel.ReadOnlyObservableCollection<BililiveRecorder.Core.IRoom> Rooms { get; }
event System.EventHandler<BililiveRecorder.Core.Event.AggregatedRoomEventArgs<BililiveRecorder.Core.Event.IOStatsEventArgs>>? IOStats;
event System.EventHandler<BililiveRecorder.Core.Event.AggregatedRoomEventArgs<BililiveRecorder.Core.Event.RecordFileClosedEventArgs>>? RecordFileClosed;
event System.EventHandler<BililiveRecorder.Core.Event.AggregatedRoomEventArgs<BililiveRecorder.Core.Event.RecordFileOpeningEventArgs>>? RecordFileOpening;
event System.EventHandler<BililiveRecorder.Core.Event.AggregatedRoomEventArgs<BililiveRecorder.Core.Event.RecordSessionEndedEventArgs>>? RecordSessionEnded;
event System.EventHandler<BililiveRecorder.Core.Event.AggregatedRoomEventArgs<BililiveRecorder.Core.Event.RecordSessionStartedEventArgs>>? RecordSessionStarted;
event System.EventHandler<BililiveRecorder.Core.Event.AggregatedRoomEventArgs<BililiveRecorder.Core.Event.RecordingStatsEventArgs>>? RecordingStats;
BililiveRecorder.Core.IRoom AddRoom(int roomid);
BililiveRecorder.Core.IRoom AddRoom(int roomid, bool enabled);
void RemoveRoom(BililiveRecorder.Core.IRoom room);
void SaveConfig();
}
public interface IRoom : System.ComponentModel.INotifyPropertyChanged, System.IDisposable
{
string AreaNameChild { get; }
string AreaNameParent { get; }
bool AutoRecordForThisSession { get; }
bool DanmakuConnected { get; }
string Name { get; }
System.Guid ObjectId { get; }
Newtonsoft.Json.Linq.JObject? RawBilibiliApiJsonData { get; }
bool Recording { get; }
BililiveRecorder.Core.Config.V3.RoomConfig RoomConfig { get; }
int ShortId { get; }
BililiveRecorder.Core.RoomStats Stats { get; }
bool Streaming { get; }
string Title { get; }
event System.EventHandler<BililiveRecorder.Core.Event.IOStatsEventArgs>? IOStats;
event System.EventHandler<BililiveRecorder.Core.Event.RecordFileClosedEventArgs>? RecordFileClosed;
event System.EventHandler<BililiveRecorder.Core.Event.RecordFileOpeningEventArgs>? RecordFileOpening;
event System.EventHandler<BililiveRecorder.Core.Event.RecordSessionEndedEventArgs>? RecordSessionEnded;
event System.EventHandler<BililiveRecorder.Core.Event.RecordSessionStartedEventArgs>? RecordSessionStarted;
event System.EventHandler<BililiveRecorder.Core.Event.RecordingStatsEventArgs>? RecordingStats;
System.Threading.Tasks.Task RefreshRoomInfoAsync();
void SplitOutput();
void StartRecord();
void StopRecord();
}
public static class LoggingContext
{
public const string RoomId = "RoomId";
}
public class PollyPolicy : Polly.Registry.PolicyRegistry
{
public readonly Polly.CircuitBreaker.AsyncCircuitBreakerPolicy IpBlockedHttp412CircuitBreakerPolicy;
public readonly Polly.CircuitBreaker.AsyncCircuitBreakerPolicy RequestFailedCircuitBreakerPolicy;
public readonly Microsoft.Extensions.Caching.Memory.MemoryCache memoryCache;
}
public class RoomStats : System.ComponentModel.INotifyPropertyChanged
{
public RoomStats() { }
public double AddedDuration { get; set; }
public long CurrentFileSize { get; set; }
public int DiskBytesWritten { get; set; }
public double DiskMBps { get; set; }
public System.TimeSpan DiskWriteDuration { get; set; }
public System.TimeSpan Duration { get; set; }
public double DurationRatio { get; set; }
public System.DateTimeOffset EndTime { get; set; }
public System.TimeSpan FileMaxTimestamp { get; set; }
public long InputAudioBytes { get; set; }
public long InputVideoBytes { get; set; }
public int NetworkBytesDownloaded { get; set; }
public double NetworkMbps { get; set; }
public long OutputAudioBytes { get; set; }
public int OutputAudioFrames { get; set; }
public long OutputVideoBytes { get; set; }
public int OutputVideoFrames { get; set; }
public double PassedTime { get; set; }
public System.TimeSpan SessionDuration { get; set; }
public System.TimeSpan SessionMaxTimestamp { get; set; }
public System.DateTimeOffset StartTime { get; set; }
public long TotalInputAudioBytes { get; set; }
public long TotalInputBytes { get; set; }
public long TotalInputVideoBytes { get; set; }
public long TotalOutputAudioBytes { get; set; }
public int TotalOutputAudioFrames { get; set; }
public long TotalOutputBytes { get; set; }
public long TotalOutputVideoBytes { get; set; }
public int TotalOutputVideoFrames { get; set; }
public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) { }
public void Reset() { }
protected bool SetField<T>(ref T location, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") { }
}
}
namespace BililiveRecorder.Core.Scripting
{
public class UserScriptRunner
{
public UserScriptRunner(BililiveRecorder.Core.Config.V3.GlobalConfig config) { }
public string? CallOnFetchStreamUrl(Serilog.ILogger logger, int roomid, int[] qnSetting) { }
public void CallOnTest(Serilog.ILogger logger, System.Action<string>? alert) { }
[return: System.Runtime.CompilerServices.TupleElementNames(new string[] {
"url",
"ip"})]
public System.ValueTuple<string, string?>? CallOnTransformStreamUrl(Serilog.ILogger logger, string originalUrl) { }
}
}
namespace BililiveRecorder.Core.Templating
{
public class FileNameGenerator
{
public FileNameGenerator(BililiveRecorder.Core.Config.V3.GlobalConfig config) { }
[return: System.Runtime.CompilerServices.TupleElementNames(new string[] {
"fullPath",
"relativePath"})]
public System.ValueTuple<string, string> CreateFilePath(BililiveRecorder.Core.Templating.FileNameGenerator.FileNameContextData data) { }
public class FileNameContextData
{
public FileNameContextData() { }
public string AreaChild { get; set; }
public string AreaParent { get; set; }
public Newtonsoft.Json.Linq.JObject? Json { get; set; }
public string Name { get; set; }
public int Qn { get; set; }
public int RoomId { get; set; }
public int ShortId { get; set; }
public string Title { get; set; }
}
}
}
namespace BililiveRecorder.DependencyInjection
{
public static class DependencyInjectionExtensions
{
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddRecorder(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) { }
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddRecorderApiClients(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) { }
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddRecorderConfig(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, BililiveRecorder.Core.Config.V3.ConfigV3 config) { }
public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddRecorderRecording(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) { }
}
}

View File

@ -0,0 +1,18 @@
using System.Threading.Tasks;
using PublicApiGenerator;
using VerifyXunit;
using Xunit;
namespace BililiveRecorder.Core.UnitTests
{
[UsesVerify]
public class PublicApi
{
[Fact]
public Task HasNoChangesAsync()
{
var publicApi = typeof(Recorder).Assembly.GeneratePublicApi();
return Verifier.Verify(publicApi);
}
}
}

View File

@ -0,0 +1,18 @@
using System.IO;
using System.Runtime.CompilerServices;
using DiffEngine;
using VerifyTests;
namespace BililiveRecorder.Core.UnitTests
{
public static class VerifyConfig
{
[ModuleInitializer]
public static void Init()
{
VerifierSettings.DerivePathInfo(Expectations.Initialize);
VerifierSettings.ModifySerialization(_ => _.IgnoreMembersWithType<Stream>());
DiffRunner.Disabled = true;
}
}
}