feat(cli/core): add TitleFilterPatterns option (#619)

* add custom title filter

* Use regex instead of string matching

* feat(ui): add title filter settings for recording conditions

---------

Co-authored-by: genteure <genteure@gmail.com>
This commit is contained in:
AquanJSW 2024-11-10 14:55:48 +08:00 committed by GitHub
parent 629e24488c
commit f05d8c3c0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 127 additions and 2 deletions

View File

@ -28,6 +28,7 @@ namespace BililiveRecorder.Cli.Configure
FileNameRecordTemplate, FileNameRecordTemplate,
FlvProcessorSplitOnScriptTag, FlvProcessorSplitOnScriptTag,
FlvWriteMetadata, FlvWriteMetadata,
TitleFilterPatterns,
WebHookUrls, WebHookUrls,
WebHookUrlsV2, WebHookUrlsV2,
WpfShowTitleAndArea, WpfShowTitleAndArea,
@ -65,7 +66,8 @@ namespace BililiveRecorder.Cli.Configure
RecordDanmakuGuard, RecordDanmakuGuard,
SaveStreamCover, SaveStreamCover,
RecordingQuality, RecordingQuality,
FlvProcessorSplitOnScriptTag FlvProcessorSplitOnScriptTag,
TitleFilterPatterns
} }
public static class ConfigInstructions public static class ConfigInstructions
{ {
@ -88,6 +90,7 @@ namespace BililiveRecorder.Cli.Configure
GlobalConfig.Add(GlobalConfigProperties.FileNameRecordTemplate, new ConfigInstruction<GlobalConfig, string>(config => config.HasFileNameRecordTemplate = false, (config, value) => config.FileNameRecordTemplate = value) { Name = "FileNameRecordTemplate", CanBeOptional = true }); GlobalConfig.Add(GlobalConfigProperties.FileNameRecordTemplate, new ConfigInstruction<GlobalConfig, string>(config => config.HasFileNameRecordTemplate = false, (config, value) => config.FileNameRecordTemplate = value) { Name = "FileNameRecordTemplate", CanBeOptional = true });
GlobalConfig.Add(GlobalConfigProperties.FlvProcessorSplitOnScriptTag, new ConfigInstruction<GlobalConfig, bool>(config => config.HasFlvProcessorSplitOnScriptTag = false, (config, value) => config.FlvProcessorSplitOnScriptTag = value) { Name = "FlvProcessorSplitOnScriptTag", CanBeOptional = true }); GlobalConfig.Add(GlobalConfigProperties.FlvProcessorSplitOnScriptTag, new ConfigInstruction<GlobalConfig, bool>(config => config.HasFlvProcessorSplitOnScriptTag = false, (config, value) => config.FlvProcessorSplitOnScriptTag = value) { Name = "FlvProcessorSplitOnScriptTag", CanBeOptional = true });
GlobalConfig.Add(GlobalConfigProperties.FlvWriteMetadata, new ConfigInstruction<GlobalConfig, bool>(config => config.HasFlvWriteMetadata = false, (config, value) => config.FlvWriteMetadata = value) { Name = "FlvWriteMetadata", CanBeOptional = true }); GlobalConfig.Add(GlobalConfigProperties.FlvWriteMetadata, new ConfigInstruction<GlobalConfig, bool>(config => config.HasFlvWriteMetadata = false, (config, value) => config.FlvWriteMetadata = value) { Name = "FlvWriteMetadata", CanBeOptional = true });
GlobalConfig.Add(GlobalConfigProperties.TitleFilterPatterns, new ConfigInstruction<GlobalConfig, string>(config => config.HasTitleFilterPatterns = false, (config, value) => config.TitleFilterPatterns = value) { Name = "TitleFilterPatterns", CanBeOptional = true });
GlobalConfig.Add(GlobalConfigProperties.WebHookUrls, new ConfigInstruction<GlobalConfig, string>(config => config.HasWebHookUrls = false, (config, value) => config.WebHookUrls = value) { Name = "WebHookUrls", CanBeOptional = true }); GlobalConfig.Add(GlobalConfigProperties.WebHookUrls, new ConfigInstruction<GlobalConfig, string>(config => config.HasWebHookUrls = false, (config, value) => config.WebHookUrls = value) { Name = "WebHookUrls", CanBeOptional = true });
GlobalConfig.Add(GlobalConfigProperties.WebHookUrlsV2, new ConfigInstruction<GlobalConfig, string>(config => config.HasWebHookUrlsV2 = false, (config, value) => config.WebHookUrlsV2 = value) { Name = "WebHookUrlsV2", CanBeOptional = true }); GlobalConfig.Add(GlobalConfigProperties.WebHookUrlsV2, new ConfigInstruction<GlobalConfig, string>(config => config.HasWebHookUrlsV2 = false, (config, value) => config.WebHookUrlsV2 = value) { Name = "WebHookUrlsV2", CanBeOptional = true });
GlobalConfig.Add(GlobalConfigProperties.WpfShowTitleAndArea, new ConfigInstruction<GlobalConfig, bool>(config => config.HasWpfShowTitleAndArea = false, (config, value) => config.WpfShowTitleAndArea = value) { Name = "WpfShowTitleAndArea", CanBeOptional = true }); GlobalConfig.Add(GlobalConfigProperties.WpfShowTitleAndArea, new ConfigInstruction<GlobalConfig, bool>(config => config.HasWpfShowTitleAndArea = false, (config, value) => config.WpfShowTitleAndArea = value) { Name = "WpfShowTitleAndArea", CanBeOptional = true });
@ -122,6 +125,7 @@ namespace BililiveRecorder.Cli.Configure
RoomConfig.Add(RoomConfigProperties.SaveStreamCover, new ConfigInstruction<RoomConfig, bool>(config => config.HasSaveStreamCover = false, (config, value) => config.SaveStreamCover = value) { Name = "SaveStreamCover", CanBeOptional = true }); RoomConfig.Add(RoomConfigProperties.SaveStreamCover, new ConfigInstruction<RoomConfig, bool>(config => config.HasSaveStreamCover = false, (config, value) => config.SaveStreamCover = value) { Name = "SaveStreamCover", CanBeOptional = true });
RoomConfig.Add(RoomConfigProperties.RecordingQuality, new ConfigInstruction<RoomConfig, string>(config => config.HasRecordingQuality = false, (config, value) => config.RecordingQuality = value) { Name = "RecordingQuality", CanBeOptional = true }); RoomConfig.Add(RoomConfigProperties.RecordingQuality, new ConfigInstruction<RoomConfig, string>(config => config.HasRecordingQuality = false, (config, value) => config.RecordingQuality = value) { Name = "RecordingQuality", CanBeOptional = true });
RoomConfig.Add(RoomConfigProperties.FlvProcessorSplitOnScriptTag, new ConfigInstruction<RoomConfig, bool>(config => config.HasFlvProcessorSplitOnScriptTag = false, (config, value) => config.FlvProcessorSplitOnScriptTag = value) { Name = "FlvProcessorSplitOnScriptTag", CanBeOptional = true }); RoomConfig.Add(RoomConfigProperties.FlvProcessorSplitOnScriptTag, new ConfigInstruction<RoomConfig, bool>(config => config.HasFlvProcessorSplitOnScriptTag = false, (config, value) => config.FlvProcessorSplitOnScriptTag = value) { Name = "FlvProcessorSplitOnScriptTag", CanBeOptional = true });
RoomConfig.Add(RoomConfigProperties.TitleFilterPatterns, new ConfigInstruction<RoomConfig, string>(config => config.HasTitleFilterPatterns = false, (config, value) => config.TitleFilterPatterns = value) { Name = "TitleFilterPatterns", CanBeOptional = true });
} }
} }

View File

@ -125,6 +125,14 @@ namespace BililiveRecorder.Core.Config.V3
[JsonProperty(nameof(FlvProcessorSplitOnScriptTag)), EditorBrowsable(EditorBrowsableState.Never)] [JsonProperty(nameof(FlvProcessorSplitOnScriptTag)), EditorBrowsable(EditorBrowsableState.Never)]
public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvProcessorSplitOnScriptTag)); set => this.SetPropertyValueOptional(value, nameof(this.FlvProcessorSplitOnScriptTag)); } public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvProcessorSplitOnScriptTag)); set => this.SetPropertyValueOptional(value, nameof(this.FlvProcessorSplitOnScriptTag)); }
/// <summary>
/// 不录制的标题匹配正则
/// </summary>
public string? TitleFilterPatterns { get => this.GetPropertyValue<string>(); set => this.SetPropertyValue(value); }
public bool HasTitleFilterPatterns { get => this.GetPropertyHasValue(nameof(this.TitleFilterPatterns)); set => this.SetPropertyHasValue<string>(value, nameof(this.TitleFilterPatterns)); }
[JsonProperty(nameof(TitleFilterPatterns)), EditorBrowsable(EditorBrowsableState.Never)]
public Optional<string?> OptionalTitleFilterPatterns { get => this.GetPropertyValueOptional<string>(nameof(this.TitleFilterPatterns)); set => this.SetPropertyValueOptional(value, nameof(this.TitleFilterPatterns)); }
/// <summary> /// <summary>
/// 录制文件名模板 /// 录制文件名模板
/// </summary> /// </summary>
@ -347,6 +355,14 @@ namespace BililiveRecorder.Core.Config.V3
[JsonProperty(nameof(FlvWriteMetadata)), EditorBrowsable(EditorBrowsableState.Never)] [JsonProperty(nameof(FlvWriteMetadata)), EditorBrowsable(EditorBrowsableState.Never)]
public Optional<bool> OptionalFlvWriteMetadata { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvWriteMetadata)); set => this.SetPropertyValueOptional(value, nameof(this.FlvWriteMetadata)); } public Optional<bool> OptionalFlvWriteMetadata { get => this.GetPropertyValueOptional<bool>(nameof(this.FlvWriteMetadata)); set => this.SetPropertyValueOptional(value, nameof(this.FlvWriteMetadata)); }
/// <summary>
/// 不录制的标题匹配正则
/// </summary>
public string? TitleFilterPatterns { get => this.GetPropertyValue<string>(); set => this.SetPropertyValue(value); }
public bool HasTitleFilterPatterns { get => this.GetPropertyHasValue(nameof(this.TitleFilterPatterns)); set => this.SetPropertyHasValue<string>(value, nameof(this.TitleFilterPatterns)); }
[JsonProperty(nameof(TitleFilterPatterns)), EditorBrowsable(EditorBrowsableState.Never)]
public Optional<string?> OptionalTitleFilterPatterns { get => this.GetPropertyValueOptional<string>(nameof(this.TitleFilterPatterns)); set => this.SetPropertyValueOptional(value, nameof(this.TitleFilterPatterns)); }
/// <summary> /// <summary>
/// WebhookV1 /// WebhookV1
/// </summary> /// </summary>
@ -534,6 +550,8 @@ namespace BililiveRecorder.Core.Config.V3
public bool FlvWriteMetadata => true; public bool FlvWriteMetadata => true;
public string TitleFilterPatterns => @"";
public string WebHookUrls => @""; public string WebHookUrls => @"";
public string WebHookUrlsV2 => @""; public string WebHookUrlsV2 => @"";

View File

@ -4,6 +4,7 @@ using System.ComponentModel;
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using BililiveRecorder.Core.Api; using BililiveRecorder.Core.Api;
@ -228,6 +229,27 @@ namespace BililiveRecorder.Core
} }
} }
private static readonly TimeSpan TitleRegexMatchTimeout = TimeSpan.FromSeconds(0.5);
/// <exception cref="ArgumentException" />
/// <exception cref="RegexMatchTimeoutException" />
private bool DoesTitleAllowRecord()
{
// 按新行分割的正则表达式
var patterns = this.RoomConfig.TitleFilterPatterns?.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
if (patterns is null || patterns.Length == 0)
return true;
foreach (var pattern in patterns)
{
if (Regex.IsMatch(input: this.Title, pattern: pattern, options: RegexOptions.None, matchTimeout: TitleRegexMatchTimeout))
return false;
}
return true;
}
/// ///
private void CreateAndStartNewRecordTask(bool skipFetchRoomInfo = false) private void CreateAndStartNewRecordTask(bool skipFetchRoomInfo = false)
{ {
@ -242,6 +264,19 @@ namespace BililiveRecorder.Core
if (this.recordTask != null) if (this.recordTask != null)
return; return;
try
{
if (!this.DoesTitleAllowRecord())
{
this.logger.Information("标题匹配到跳过录制设置中的规则,不录制");
return;
}
}
catch (Exception ex)
{
this.logger.Warning(ex, "检查标题是否匹配跳过录制正则表达式时出错");
}
var task = this.recordTaskFactory.CreateRecordTask(this); var task = this.recordTaskFactory.CreateRecordTask(this);
task.IOStats += this.RecordTask_IOStats; task.IOStats += this.RecordTask_IOStats;
task.RecordingStats += this.RecordTask_RecordingStats; task.RecordingStats += this.RecordTask_RecordingStats;
@ -653,6 +688,7 @@ retry:
} }
} }
private void Room_PropertyChanged(object? sender, PropertyChangedEventArgs e) private void Room_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{ {
switch (e.PropertyName) switch (e.PropertyName)
@ -670,7 +706,8 @@ retry:
} }
break; break;
case nameof(this.Title): case nameof(this.Title):
if (this.RoomConfig.CuttingByTitle){ if (this.RoomConfig.CuttingByTitle)
{
this.SplitOutput(); this.SplitOutput();
} }
break; break;

View File

@ -113,6 +113,15 @@
</local:SettingWithDefault> </local:SettingWithDefault>
</StackPanel> </StackPanel>
</GroupBox> </GroupBox>
<GroupBox Header="录制条件">
<StackPanel>
<TextBlock Margin="5" Text="跳过录制的直播标题正则匹配表达式,每行一个" />
<local:SettingWithDefault IsSettingNotUsingDefault="{Binding HasTitleFilterPatterns}">
<TextBox Margin="5" AcceptsReturn="True" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible"
Text="{Binding TitleFilterPatterns,UpdateSourceTrigger=PropertyChanged,Delay=1000}" ui:TextBoxHelper.IsDeleteButtonVisible="False"/>
</local:SettingWithDefault>
</StackPanel>
</GroupBox>
</ui:SimpleStackPanel> </ui:SimpleStackPanel>
</ScrollViewer> </ScrollViewer>
</Grid> </Grid>

View File

@ -131,6 +131,13 @@
</c:SettingWithDefault> </c:SettingWithDefault>
</StackPanel> </StackPanel>
</GroupBox> </GroupBox>
<GroupBox Header="录制条件">
<StackPanel>
<TextBlock Margin="5" Text="跳过录制的直播标题正则匹配表达式,每行一个" />
<TextBox Margin="5" AcceptsReturn="True" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible"
Text="{Binding TitleFilterPatterns,UpdateSourceTrigger=PropertyChanged,Delay=1000}" ui:TextBoxHelper.IsDeleteButtonVisible="False"/>
</StackPanel>
</GroupBox>
<GroupBox Header="{l:Loc Settings_Webhook_Title}"> <GroupBox Header="{l:Loc Settings_Webhook_Title}">
<StackPanel MaxWidth="400" HorizontalAlignment="Left"> <StackPanel MaxWidth="400" HorizontalAlignment="Left">
<TextBlock Text="{l:Loc Settings_Webhook_Address}" Margin="0,0,0,10"/> <TextBlock Text="{l:Loc Settings_Webhook_Address}" Margin="0,0,0,10"/>

View File

@ -25,6 +25,7 @@ namespace BililiveRecorder.Web.Models
public Optional<bool>? OptionalSaveStreamCover { get; set; } public Optional<bool>? OptionalSaveStreamCover { get; set; }
public Optional<string?>? OptionalRecordingQuality { get; set; } public Optional<string?>? OptionalRecordingQuality { get; set; }
public Optional<bool>? OptionalFlvProcessorSplitOnScriptTag { get; set; } public Optional<bool>? OptionalFlvProcessorSplitOnScriptTag { get; set; }
public Optional<string?>? OptionalTitleFilterPatterns { get; set; }
public void ApplyTo(RoomConfig config) public void ApplyTo(RoomConfig config)
{ {
@ -41,6 +42,7 @@ namespace BililiveRecorder.Web.Models
if (this.OptionalSaveStreamCover.HasValue) config.OptionalSaveStreamCover = this.OptionalSaveStreamCover.Value; if (this.OptionalSaveStreamCover.HasValue) config.OptionalSaveStreamCover = this.OptionalSaveStreamCover.Value;
if (this.OptionalRecordingQuality.HasValue) config.OptionalRecordingQuality = this.OptionalRecordingQuality.Value; if (this.OptionalRecordingQuality.HasValue) config.OptionalRecordingQuality = this.OptionalRecordingQuality.Value;
if (this.OptionalFlvProcessorSplitOnScriptTag.HasValue) config.OptionalFlvProcessorSplitOnScriptTag = this.OptionalFlvProcessorSplitOnScriptTag.Value; if (this.OptionalFlvProcessorSplitOnScriptTag.HasValue) config.OptionalFlvProcessorSplitOnScriptTag = this.OptionalFlvProcessorSplitOnScriptTag.Value;
if (this.OptionalTitleFilterPatterns.HasValue) config.OptionalTitleFilterPatterns = this.OptionalTitleFilterPatterns.Value;
} }
} }
@ -60,6 +62,7 @@ namespace BililiveRecorder.Web.Models
public Optional<string?>? OptionalFileNameRecordTemplate { get; set; } public Optional<string?>? OptionalFileNameRecordTemplate { get; set; }
public Optional<bool>? OptionalFlvProcessorSplitOnScriptTag { get; set; } public Optional<bool>? OptionalFlvProcessorSplitOnScriptTag { get; set; }
public Optional<bool>? OptionalFlvWriteMetadata { get; set; } public Optional<bool>? OptionalFlvWriteMetadata { get; set; }
public Optional<string?>? OptionalTitleFilterPatterns { get; set; }
public Optional<string?>? OptionalWebHookUrls { get; set; } public Optional<string?>? OptionalWebHookUrls { get; set; }
public Optional<string?>? OptionalWebHookUrlsV2 { get; set; } public Optional<string?>? OptionalWebHookUrlsV2 { get; set; }
public Optional<bool>? OptionalWpfShowTitleAndArea { get; set; } public Optional<bool>? OptionalWpfShowTitleAndArea { get; set; }
@ -96,6 +99,7 @@ namespace BililiveRecorder.Web.Models
if (this.OptionalFileNameRecordTemplate.HasValue) config.OptionalFileNameRecordTemplate = this.OptionalFileNameRecordTemplate.Value; if (this.OptionalFileNameRecordTemplate.HasValue) config.OptionalFileNameRecordTemplate = this.OptionalFileNameRecordTemplate.Value;
if (this.OptionalFlvProcessorSplitOnScriptTag.HasValue) config.OptionalFlvProcessorSplitOnScriptTag = this.OptionalFlvProcessorSplitOnScriptTag.Value; if (this.OptionalFlvProcessorSplitOnScriptTag.HasValue) config.OptionalFlvProcessorSplitOnScriptTag = this.OptionalFlvProcessorSplitOnScriptTag.Value;
if (this.OptionalFlvWriteMetadata.HasValue) config.OptionalFlvWriteMetadata = this.OptionalFlvWriteMetadata.Value; if (this.OptionalFlvWriteMetadata.HasValue) config.OptionalFlvWriteMetadata = this.OptionalFlvWriteMetadata.Value;
if (this.OptionalTitleFilterPatterns.HasValue) config.OptionalTitleFilterPatterns = this.OptionalTitleFilterPatterns.Value;
if (this.OptionalWebHookUrls.HasValue) config.OptionalWebHookUrls = this.OptionalWebHookUrls.Value; if (this.OptionalWebHookUrls.HasValue) config.OptionalWebHookUrls = this.OptionalWebHookUrls.Value;
if (this.OptionalWebHookUrlsV2.HasValue) config.OptionalWebHookUrlsV2 = this.OptionalWebHookUrlsV2.Value; if (this.OptionalWebHookUrlsV2.HasValue) config.OptionalWebHookUrlsV2 = this.OptionalWebHookUrlsV2.Value;
if (this.OptionalWpfShowTitleAndArea.HasValue) config.OptionalWpfShowTitleAndArea = this.OptionalWpfShowTitleAndArea.Value; if (this.OptionalWpfShowTitleAndArea.HasValue) config.OptionalWpfShowTitleAndArea = this.OptionalWpfShowTitleAndArea.Value;
@ -137,6 +141,7 @@ namespace BililiveRecorder.Web.Models.Rest
public Optional<bool> OptionalSaveStreamCover { get; set; } public Optional<bool> OptionalSaveStreamCover { get; set; }
public Optional<string?> OptionalRecordingQuality { get; set; } public Optional<string?> OptionalRecordingQuality { get; set; }
public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; } public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; }
public Optional<string?> OptionalTitleFilterPatterns { get; set; }
} }
public class GlobalConfigDto public class GlobalConfigDto
@ -155,6 +160,7 @@ namespace BililiveRecorder.Web.Models.Rest
public Optional<string?> OptionalFileNameRecordTemplate { get; set; } public Optional<string?> OptionalFileNameRecordTemplate { get; set; }
public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; } public Optional<bool> OptionalFlvProcessorSplitOnScriptTag { get; set; }
public Optional<bool> OptionalFlvWriteMetadata { get; set; } public Optional<bool> OptionalFlvWriteMetadata { get; set; }
public Optional<string?> OptionalTitleFilterPatterns { get; set; }
public Optional<string?> OptionalWebHookUrls { get; set; } public Optional<string?> OptionalWebHookUrls { get; set; }
public Optional<string?> OptionalWebHookUrlsV2 { get; set; } public Optional<string?> OptionalWebHookUrlsV2 { get; set; }
public Optional<bool> OptionalWpfShowTitleAndArea { get; set; } public Optional<bool> OptionalWpfShowTitleAndArea { get; set; }
@ -198,6 +204,7 @@ namespace BililiveRecorder.Web.Models.Graphql
this.Field(x => x.OptionalSaveStreamCover, type: typeof(HierarchicalOptionalType<bool>)); this.Field(x => x.OptionalSaveStreamCover, type: typeof(HierarchicalOptionalType<bool>));
this.Field(x => x.OptionalRecordingQuality, type: typeof(HierarchicalOptionalType<string>)); this.Field(x => x.OptionalRecordingQuality, type: typeof(HierarchicalOptionalType<string>));
this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, type: typeof(HierarchicalOptionalType<bool>)); this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, type: typeof(HierarchicalOptionalType<bool>));
this.Field(x => x.OptionalTitleFilterPatterns, type: typeof(HierarchicalOptionalType<string>));
} }
} }
@ -219,6 +226,7 @@ namespace BililiveRecorder.Web.Models.Graphql
this.Field(x => x.OptionalFileNameRecordTemplate, type: typeof(HierarchicalOptionalType<string>)); this.Field(x => x.OptionalFileNameRecordTemplate, type: typeof(HierarchicalOptionalType<string>));
this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, type: typeof(HierarchicalOptionalType<bool>)); this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, type: typeof(HierarchicalOptionalType<bool>));
this.Field(x => x.OptionalFlvWriteMetadata, type: typeof(HierarchicalOptionalType<bool>)); this.Field(x => x.OptionalFlvWriteMetadata, type: typeof(HierarchicalOptionalType<bool>));
this.Field(x => x.OptionalTitleFilterPatterns, type: typeof(HierarchicalOptionalType<string>));
this.Field(x => x.OptionalWebHookUrls, type: typeof(HierarchicalOptionalType<string>)); this.Field(x => x.OptionalWebHookUrls, type: typeof(HierarchicalOptionalType<string>));
this.Field(x => x.OptionalWebHookUrlsV2, type: typeof(HierarchicalOptionalType<string>)); this.Field(x => x.OptionalWebHookUrlsV2, type: typeof(HierarchicalOptionalType<string>));
this.Field(x => x.OptionalWpfShowTitleAndArea, type: typeof(HierarchicalOptionalType<bool>)); this.Field(x => x.OptionalWpfShowTitleAndArea, type: typeof(HierarchicalOptionalType<bool>));
@ -259,6 +267,7 @@ namespace BililiveRecorder.Web.Models.Graphql
this.Field(x => x.FileNameRecordTemplate); this.Field(x => x.FileNameRecordTemplate);
this.Field(x => x.FlvProcessorSplitOnScriptTag); this.Field(x => x.FlvProcessorSplitOnScriptTag);
this.Field(x => x.FlvWriteMetadata); this.Field(x => x.FlvWriteMetadata);
this.Field(x => x.TitleFilterPatterns);
this.Field(x => x.WebHookUrls); this.Field(x => x.WebHookUrls);
this.Field(x => x.WebHookUrlsV2); this.Field(x => x.WebHookUrlsV2);
this.Field(x => x.WpfShowTitleAndArea); this.Field(x => x.WpfShowTitleAndArea);
@ -298,6 +307,7 @@ namespace BililiveRecorder.Web.Models.Graphql
this.Field(x => x.OptionalSaveStreamCover, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>)); this.Field(x => x.OptionalSaveStreamCover, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
this.Field(x => x.OptionalRecordingQuality, nullable: true, type: typeof(HierarchicalOptionalInputType<string>)); this.Field(x => x.OptionalRecordingQuality, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>)); this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
this.Field(x => x.OptionalTitleFilterPatterns, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
} }
} }
@ -319,6 +329,7 @@ namespace BililiveRecorder.Web.Models.Graphql
this.Field(x => x.OptionalFileNameRecordTemplate, nullable: true, type: typeof(HierarchicalOptionalInputType<string>)); this.Field(x => x.OptionalFileNameRecordTemplate, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>)); this.Field(x => x.OptionalFlvProcessorSplitOnScriptTag, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
this.Field(x => x.OptionalFlvWriteMetadata, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>)); this.Field(x => x.OptionalFlvWriteMetadata, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));
this.Field(x => x.OptionalTitleFilterPatterns, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
this.Field(x => x.OptionalWebHookUrls, nullable: true, type: typeof(HierarchicalOptionalInputType<string>)); this.Field(x => x.OptionalWebHookUrls, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
this.Field(x => x.OptionalWebHookUrlsV2, nullable: true, type: typeof(HierarchicalOptionalInputType<string>)); this.Field(x => x.OptionalWebHookUrlsV2, nullable: true, type: typeof(HierarchicalOptionalInputType<string>));
this.Field(x => x.OptionalWpfShowTitleAndArea, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>)); this.Field(x => x.OptionalWpfShowTitleAndArea, nullable: true, type: typeof(HierarchicalOptionalInputType<bool>));

View File

@ -577,6 +577,22 @@
"default": false "default": false
} }
} }
},
"TitleFilterPatterns": {
"description": "不录制的标题匹配正则\n默认: ",
"markdownDescription": "不录制的标题匹配正则 \n默认: ` `\n\n",
"type": "object",
"additionalProperties": false,
"properties": {
"HasValue": {
"type": "boolean",
"default": true
},
"Value": {
"type": "string",
"default": ""
}
}
} }
} }
}, },
@ -822,6 +838,22 @@
"default": false "default": false
} }
} }
},
"TitleFilterPatterns": {
"description": "不录制的标题匹配正则\n默认: ",
"markdownDescription": "不录制的标题匹配正则 \n默认: ` `\n\n",
"type": "object",
"additionalProperties": false,
"properties": {
"HasValue": {
"type": "boolean",
"default": true
},
"Value": {
"type": "string",
"default": ""
}
}
} }
} }
} }

View File

@ -115,6 +115,13 @@ export const data: Array<ConfigEntry> = [
advancedConfig: true, advancedConfig: true,
default: true default: true
}, },
{
id: "TitleFilterPatterns",
name: "不录制的标题匹配正则",
type: "string?",
configType: "room",
default: ""
},
{ {
id: "WebHookUrls", id: "WebHookUrls",
name: "WebhookV1", name: "WebhookV1",