feat: add live room metadata, uploads, proxies and backups
This commit is contained in:
@@ -14,6 +14,7 @@ namespace LiveRecorder.Application.Services;
|
||||
public sealed class LiveRoomService
|
||||
{
|
||||
private readonly ILiveRoomRepository _liveRoomRepository;
|
||||
private readonly IRecordSessionRepository _recordSessionRepository;
|
||||
private readonly ILivePlatformAdapterFactory _livePlatformAdapterFactory;
|
||||
private readonly LiveRoomStatusService _liveRoomStatusService;
|
||||
private readonly LiveRoomRecordingSettingsResolver _liveRoomRecordingSettingsResolver;
|
||||
@@ -25,6 +26,7 @@ public sealed class LiveRoomService
|
||||
|
||||
public LiveRoomService(
|
||||
ILiveRoomRepository liveRoomRepository,
|
||||
IRecordSessionRepository recordSessionRepository,
|
||||
ILivePlatformAdapterFactory livePlatformAdapterFactory,
|
||||
LiveRoomStatusService liveRoomStatusService,
|
||||
LiveRoomRecordingSettingsResolver liveRoomRecordingSettingsResolver,
|
||||
@@ -35,6 +37,7 @@ public sealed class LiveRoomService
|
||||
ISystemLogService systemLogService)
|
||||
{
|
||||
_liveRoomRepository = liveRoomRepository;
|
||||
_recordSessionRepository = recordSessionRepository;
|
||||
_livePlatformAdapterFactory = livePlatformAdapterFactory;
|
||||
_liveRoomStatusService = liveRoomStatusService;
|
||||
_liveRoomRecordingSettingsResolver = liveRoomRecordingSettingsResolver;
|
||||
@@ -49,9 +52,13 @@ public sealed class LiveRoomService
|
||||
{
|
||||
var rooms = await _liveRoomRepository.ListAsync(cancellationToken);
|
||||
var effectiveSettings = await BuildEffectiveSettingsLookupAsync(rooms, cancellationToken);
|
||||
var activeLiveRoomIds = await _recordSessionRepository.ListActiveLiveRoomIdsAsync(cancellationToken);
|
||||
return rooms
|
||||
.OrderByDescending(static item => item.UpdatedAt)
|
||||
.Select(item => Map(item, effectiveSettings[item.Id]))
|
||||
.OrderByDescending(static item => item.IsPinned)
|
||||
.ThenByDescending(static item => item.IsPriority)
|
||||
.ThenByDescending(item => GetCurrentRecordingState(item, activeLiveRoomIds.Contains(item.Id)))
|
||||
.ThenByDescending(static item => item.UpdatedAt)
|
||||
.Select(item => Map(item, effectiveSettings[item.Id], activeLiveRoomIds.Contains(item.Id)))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
@@ -64,7 +71,8 @@ public sealed class LiveRoomService
|
||||
}
|
||||
|
||||
var effectiveSettings = await _liveRoomRecordingSettingsResolver.ResolveAsync(room, cancellationToken);
|
||||
return Map(room, effectiveSettings);
|
||||
var hasActiveSession = await _recordSessionRepository.GetActiveByLiveRoomIdAsync(room.Id, cancellationToken) is not null;
|
||||
return Map(room, effectiveSettings, hasActiveSession);
|
||||
}
|
||||
|
||||
public async Task<LiveRoomDto> CreateAsync(CreateLiveRoomRequest request, CancellationToken cancellationToken = default)
|
||||
@@ -77,7 +85,8 @@ public sealed class LiveRoomService
|
||||
request.AnchorName,
|
||||
cancellationToken);
|
||||
|
||||
return Map(liveRoom, effectiveSettings);
|
||||
var hasActiveSession = await _recordSessionRepository.GetActiveByLiveRoomIdAsync(liveRoom.Id, cancellationToken) is not null;
|
||||
return Map(liveRoom, effectiveSettings, hasActiveSession);
|
||||
}
|
||||
|
||||
public async Task<ImportLiveRoomsResultDto> ImportAsync(
|
||||
@@ -130,7 +139,10 @@ public sealed class LiveRoomService
|
||||
AnchorName = anchorName,
|
||||
Success = true,
|
||||
Created = created,
|
||||
LiveRoom = Map(liveRoom, effectiveSettings)
|
||||
LiveRoom = Map(
|
||||
liveRoom,
|
||||
effectiveSettings,
|
||||
await _recordSessionRepository.GetActiveByLiveRoomIdAsync(liveRoom.Id, cancellationToken) is not null)
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -247,7 +259,8 @@ public sealed class LiveRoomService
|
||||
await TryAutoStartRecordingAsync(room, liveStatus, cancellationToken);
|
||||
|
||||
var effectiveSettings = await _liveRoomRecordingSettingsResolver.ResolveAsync(room, cancellationToken);
|
||||
return Map(room, effectiveSettings);
|
||||
var hasActiveSession = await _recordSessionRepository.GetActiveByLiveRoomIdAsync(room.Id, cancellationToken) is not null;
|
||||
return Map(room, effectiveSettings, hasActiveSession);
|
||||
}
|
||||
|
||||
public async Task<LiveRoomDto> SetEnabledAsync(Guid id, bool isEnabled, CancellationToken cancellationToken = default)
|
||||
@@ -268,7 +281,8 @@ public sealed class LiveRoomService
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
var effectiveSettings = await _liveRoomRecordingSettingsResolver.ResolveAsync(room, cancellationToken);
|
||||
return Map(room, effectiveSettings);
|
||||
var hasActiveSession = await _recordSessionRepository.GetActiveByLiveRoomIdAsync(room.Id, cancellationToken) is not null;
|
||||
return Map(room, effectiveSettings, hasActiveSession);
|
||||
}
|
||||
|
||||
public async Task<BatchLiveRoomsResultDto> SetEnabledBatchAsync(
|
||||
@@ -340,7 +354,40 @@ public sealed class LiveRoomService
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
var effectiveSettings = await _liveRoomRecordingSettingsResolver.ResolveAsync(room, cancellationToken);
|
||||
return Map(room, effectiveSettings);
|
||||
var hasActiveSession = await _recordSessionRepository.GetActiveByLiveRoomIdAsync(room.Id, cancellationToken) is not null;
|
||||
return Map(room, effectiveSettings, hasActiveSession);
|
||||
}
|
||||
|
||||
public async Task<LiveRoomDto> UpdateMetadataAsync(
|
||||
Guid id,
|
||||
UpdateLiveRoomMetadataRequest request,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(request);
|
||||
|
||||
var room = await _liveRoomRepository.GetByIdAsync(id, cancellationToken)
|
||||
?? throw new KeyNotFoundException("Live room was not found.");
|
||||
|
||||
room.UpdateManagementMetadata(
|
||||
request.Remark,
|
||||
request.IsPinned,
|
||||
request.Alias,
|
||||
request.IsPriority,
|
||||
ClampNullable(request.PollingIntervalSecondsOverride, 10, 3600),
|
||||
DateTimeOffset.UtcNow);
|
||||
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
await _systemLogService.WriteAsync(
|
||||
SystemLogLevel.Info,
|
||||
"LiveRoom",
|
||||
$"Live room metadata updated for room {room.RoomId}.",
|
||||
liveRoomId: room.Id,
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
var effectiveSettings = await _liveRoomRecordingSettingsResolver.ResolveAsync(room, cancellationToken);
|
||||
var hasActiveSession = await _recordSessionRepository.GetActiveByLiveRoomIdAsync(room.Id, cancellationToken) is not null;
|
||||
return Map(room, effectiveSettings, hasActiveSession);
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default)
|
||||
@@ -470,7 +517,7 @@ public sealed class LiveRoomService
|
||||
}
|
||||
}
|
||||
|
||||
private LiveRoomDto Map(LiveRoom room, RecordingExecutionSettings effectiveSettings) => new()
|
||||
private LiveRoomDto Map(LiveRoom room, RecordingExecutionSettings effectiveSettings, bool hasActiveSession) => new()
|
||||
{
|
||||
Id = room.Id,
|
||||
Platform = room.Platform,
|
||||
@@ -483,10 +530,17 @@ public sealed class LiveRoomService
|
||||
AnchorId = room.AnchorId,
|
||||
AvatarUrl = room.AvatarUrl,
|
||||
CoverUrl = room.CoverUrl,
|
||||
Remark = room.Remark,
|
||||
IsPinned = room.IsPinned,
|
||||
Alias = room.Alias,
|
||||
IsPriority = room.IsPriority,
|
||||
PollingIntervalSecondsOverride = room.PollingIntervalSecondsOverride,
|
||||
OriginalLiveRoomUrl = string.IsNullOrWhiteSpace(room.NormalizedUrl) ? room.SourceUrl : room.NormalizedUrl,
|
||||
Overrides = _liveRoomRecordingSettingsResolver.BuildOverridesDto(room),
|
||||
EffectiveSettings = _liveRoomRecordingSettingsResolver.BuildEffectiveDto(effectiveSettings),
|
||||
IsEnabled = room.IsEnabled,
|
||||
AvailabilityStatus = room.AvailabilityStatus,
|
||||
CurrentRecordingState = GetCurrentRecordingState(room, hasActiveSession),
|
||||
LastAutoStartDecisionCode = room.LastAutoStartDecisionCode,
|
||||
LastAutoStartDecisionSummary = room.LastAutoStartDecisionSummary,
|
||||
LastAutoStartDecisionDetail = room.LastAutoStartDecisionDetail,
|
||||
@@ -496,6 +550,18 @@ public sealed class LiveRoomService
|
||||
UpdatedAt = room.UpdatedAt
|
||||
};
|
||||
|
||||
private static LiveRoomCurrentRecordingState GetCurrentRecordingState(LiveRoom room, bool hasActiveSession)
|
||||
{
|
||||
if (room.AvailabilityStatus != LiveRoomAvailabilityStatus.Live)
|
||||
{
|
||||
return LiveRoomCurrentRecordingState.Offline;
|
||||
}
|
||||
|
||||
return hasActiveSession
|
||||
? LiveRoomCurrentRecordingState.Recording
|
||||
: LiveRoomCurrentRecordingState.Live;
|
||||
}
|
||||
|
||||
private static int? ClampNullable(int? value, int min, int max) =>
|
||||
value.HasValue ? Math.Clamp(value.Value, min, max) : null;
|
||||
|
||||
|
||||
@@ -42,6 +42,13 @@ internal static class RecordModelMapper
|
||||
DanmakuMessageCount = recordResult.DanmakuMessageCount,
|
||||
FinalStatus = recordResult.FinalStatus,
|
||||
ErrorMessage = recordResult.ErrorMessage,
|
||||
UploadStatus = recordResult.UploadStatus,
|
||||
LastUploadProvider = recordResult.LastUploadProvider,
|
||||
RemoteVideoPath = recordResult.RemoteVideoPath,
|
||||
RemoteDanmakuPath = recordResult.RemoteDanmakuPath,
|
||||
LastUploadedAt = recordResult.LastUploadedAt,
|
||||
UploadErrorMessage = recordResult.UploadErrorMessage,
|
||||
DeletedLocalFilesAfterUpload = recordResult.DeletedLocalFilesAfterUpload,
|
||||
CreatedAt = recordResult.CreatedAt
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ namespace LiveRecorder.Application.Services;
|
||||
|
||||
public sealed class RecordService
|
||||
{
|
||||
private static readonly TimeSpan StartRecordingDebounceWindow = TimeSpan.FromSeconds(10);
|
||||
|
||||
private readonly ILiveRoomRepository _liveRoomRepository;
|
||||
private readonly IRecordSessionRepository _recordSessionRepository;
|
||||
private readonly IRecordTaskRepository _recordTaskRepository;
|
||||
@@ -146,6 +148,34 @@ public sealed class RecordService
|
||||
throw new InvalidOperationException("The live room is disabled. Enable it before starting a recording.");
|
||||
}
|
||||
|
||||
var debounceTriggeredAt = DateTimeOffset.UtcNow;
|
||||
if (liveRoom.LastStartRecordingTriggeredAt.HasValue &&
|
||||
debounceTriggeredAt - liveRoom.LastStartRecordingTriggeredAt.Value < StartRecordingDebounceWindow)
|
||||
{
|
||||
if (trackAutoStartDecision)
|
||||
{
|
||||
await UpdateAutoStartDecisionAsync(
|
||||
liveRoom,
|
||||
AutoStartDecisionCodes.SkippedDebounce,
|
||||
"Auto-start skipped because start recording debounce is active.",
|
||||
$"lastTriggeredAt={liveRoom.LastStartRecordingTriggeredAt:O}",
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
await _systemLogService.WriteAsync(
|
||||
SystemLogLevel.Info,
|
||||
"RecordSession",
|
||||
"Recording start skipped because the debounce window is still active.",
|
||||
$"windowSeconds={(int)StartRecordingDebounceWindow.TotalSeconds}",
|
||||
liveRoomId: liveRoom.Id,
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
throw new InvalidOperationException("Recording start was triggered too recently. Please wait a few seconds and try again.");
|
||||
}
|
||||
|
||||
liveRoom.MarkStartRecordingTriggered(debounceTriggeredAt);
|
||||
await _unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
await ReconcileActiveSessionsAsync(liveRoom.Id, cancellationToken);
|
||||
var activeSession = await _recordSessionRepository.GetActiveByLiveRoomIdAsync(liveRoom.Id, cancellationToken);
|
||||
if (activeSession is not null)
|
||||
@@ -204,6 +234,7 @@ public sealed class RecordService
|
||||
var outputFormat = request.OutputFormat ?? effectiveSettings.OutputFormat;
|
||||
var saveMode = effectiveSettings.SaveMode;
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var storageAnchorName = GetStorageAnchorName(liveRoom, settings);
|
||||
|
||||
var recordSession = new RecordSession(liveRoom.Id, preferredQuality, outputFormat, saveMode, now);
|
||||
await _recordSessionRepository.AddAsync(recordSession, cancellationToken);
|
||||
@@ -251,7 +282,7 @@ public sealed class RecordService
|
||||
settings.OutputFileNameTemplate,
|
||||
liveRoom.Platform,
|
||||
liveRoom.RoomId,
|
||||
liveRoom.AnchorName,
|
||||
storageAnchorName,
|
||||
liveRoom.Title,
|
||||
outputFormat,
|
||||
saveMode,
|
||||
@@ -774,6 +805,18 @@ public sealed class RecordService
|
||||
return Path.Combine(folder, $"{fileNameStem}.{extension}");
|
||||
}
|
||||
|
||||
private static string? GetStorageAnchorName(LiveRoom liveRoom, Application.Models.Settings.SystemSettingsDto settings)
|
||||
{
|
||||
if (!settings.UseAliasForStorage)
|
||||
{
|
||||
return liveRoom.AnchorName;
|
||||
}
|
||||
|
||||
return string.IsNullOrWhiteSpace(liveRoom.Alias)
|
||||
? liveRoom.AnchorName
|
||||
: liveRoom.Alias;
|
||||
}
|
||||
|
||||
internal static string ResolveSegmentOutputPath(
|
||||
string outputPathPattern,
|
||||
RecordOutputFormat outputFormat,
|
||||
|
||||
@@ -32,6 +32,28 @@ public sealed class SystemSettingsService : ISystemSettingsService
|
||||
private const string EnableBackgroundPollingKey = "scheduler.enable_background_polling";
|
||||
private const string AutoStartRecordingOnLiveKey = "scheduler.auto_start_recording_on_live";
|
||||
private const string PollingIntervalSecondsKey = "scheduler.polling_interval_seconds";
|
||||
private const string UseAliasForStorageKey = "recording.use_alias_for_storage";
|
||||
private const string EnableFileUploadKey = "upload.enabled";
|
||||
private const string EnableAutoUploadKey = "upload.auto_upload";
|
||||
private const string DeleteLocalFilesAfterUploadKey = "upload.delete_local_files_after_upload";
|
||||
private const string UploadTargetKey = "upload.target";
|
||||
private const string WebDavEndpointKey = "upload.webdav.endpoint";
|
||||
private const string WebDavBasePathKey = "upload.webdav.base_path";
|
||||
private const string WebDavUsernameKey = "upload.webdav.username";
|
||||
private const string WebDavPasswordKey = "upload.webdav.password";
|
||||
private const string S3EndpointKey = "upload.s3.endpoint";
|
||||
private const string S3BucketKey = "upload.s3.bucket";
|
||||
private const string S3RegionKey = "upload.s3.region";
|
||||
private const string S3AccessKeyKey = "upload.s3.access_key";
|
||||
private const string S3SecretKeyKey = "upload.s3.secret_key";
|
||||
private const string S3PrefixKey = "upload.s3.prefix";
|
||||
private const string S3ForcePathStyleKey = "upload.s3.force_path_style";
|
||||
private const string DouyinProxyEnabledKey = "platform_proxy.douyin.enabled";
|
||||
private const string DouyinProxyUrlKey = "platform_proxy.douyin.url";
|
||||
private const string BilibiliProxyEnabledKey = "platform_proxy.bilibili.enabled";
|
||||
private const string BilibiliProxyUrlKey = "platform_proxy.bilibili.url";
|
||||
private const string HuyaProxyEnabledKey = "platform_proxy.huya.enabled";
|
||||
private const string HuyaProxyUrlKey = "platform_proxy.huya.url";
|
||||
private const string EnableEventScriptsKey = "event_scripts.enabled";
|
||||
private const string LiveStartedScriptModeKey = "event_scripts.live_started.mode";
|
||||
private const string LiveStartedScriptPathKey = "event_scripts.live_started.path";
|
||||
@@ -117,6 +139,45 @@ public sealed class SystemSettingsService : ISystemSettingsService
|
||||
EnableBackgroundPolling = bool.TryParse(GetValue(lookup, EnableBackgroundPollingKey, "true"), out var enableBackgroundPolling) && enableBackgroundPolling,
|
||||
AutoStartRecordingOnLive = bool.TryParse(GetValue(lookup, AutoStartRecordingOnLiveKey, "true"), out var autoStartRecordingOnLive) && autoStartRecordingOnLive,
|
||||
PollingIntervalSeconds = GetIntValue(lookup, PollingIntervalSecondsKey, 60, 10, 3600),
|
||||
UseAliasForStorage = bool.TryParse(GetValue(lookup, UseAliasForStorageKey, "false"), out var useAliasForStorage) && useAliasForStorage,
|
||||
EnableFileUpload = bool.TryParse(GetValue(lookup, EnableFileUploadKey, "false"), out var enableFileUpload) && enableFileUpload,
|
||||
EnableAutoUpload = bool.TryParse(GetValue(lookup, EnableAutoUploadKey, "false"), out var enableAutoUpload) && enableAutoUpload,
|
||||
DeleteLocalFilesAfterUpload = bool.TryParse(GetValue(lookup, DeleteLocalFilesAfterUploadKey, "false"), out var deleteLocalFilesAfterUpload) && deleteLocalFilesAfterUpload,
|
||||
UploadTarget = Enum.TryParse(GetValue(lookup, UploadTargetKey, "None"), true, out UploadTargetType uploadTarget)
|
||||
? uploadTarget
|
||||
: UploadTargetType.None,
|
||||
DouyinProxy = new PlatformProxySettingsDto
|
||||
{
|
||||
Enabled = bool.TryParse(GetValue(lookup, DouyinProxyEnabledKey, "false"), out var douyinProxyEnabled) && douyinProxyEnabled,
|
||||
ProxyUrl = GetValue(lookup, DouyinProxyUrlKey, string.Empty)
|
||||
},
|
||||
BilibiliProxy = new PlatformProxySettingsDto
|
||||
{
|
||||
Enabled = bool.TryParse(GetValue(lookup, BilibiliProxyEnabledKey, "false"), out var bilibiliProxyEnabled) && bilibiliProxyEnabled,
|
||||
ProxyUrl = GetValue(lookup, BilibiliProxyUrlKey, string.Empty)
|
||||
},
|
||||
HuyaProxy = new PlatformProxySettingsDto
|
||||
{
|
||||
Enabled = bool.TryParse(GetValue(lookup, HuyaProxyEnabledKey, "false"), out var huyaProxyEnabled) && huyaProxyEnabled,
|
||||
ProxyUrl = GetValue(lookup, HuyaProxyUrlKey, string.Empty)
|
||||
},
|
||||
WebDavUpload = new WebDavUploadSettingsDto
|
||||
{
|
||||
Endpoint = GetValue(lookup, WebDavEndpointKey, string.Empty),
|
||||
BasePath = GetValue(lookup, WebDavBasePathKey, string.Empty),
|
||||
Username = GetValue(lookup, WebDavUsernameKey, string.Empty),
|
||||
Password = GetValue(lookup, WebDavPasswordKey, string.Empty)
|
||||
},
|
||||
S3Upload = new S3UploadSettingsDto
|
||||
{
|
||||
Endpoint = GetValue(lookup, S3EndpointKey, string.Empty),
|
||||
Bucket = GetValue(lookup, S3BucketKey, string.Empty),
|
||||
Region = GetValue(lookup, S3RegionKey, string.Empty),
|
||||
AccessKey = GetValue(lookup, S3AccessKeyKey, string.Empty),
|
||||
SecretKey = GetValue(lookup, S3SecretKeyKey, string.Empty),
|
||||
Prefix = GetValue(lookup, S3PrefixKey, string.Empty),
|
||||
ForcePathStyle = bool.TryParse(GetValue(lookup, S3ForcePathStyleKey, "false"), out var s3ForcePathStyle) && s3ForcePathStyle
|
||||
},
|
||||
EnableEventScripts = bool.TryParse(GetValue(lookup, EnableEventScriptsKey, "false"), out var enableEventScripts) && enableEventScripts,
|
||||
LiveStartedScriptMode = GetEventScriptMode(lookup, LiveStartedScriptModeKey, LiveStartedScriptPathKey, LiveStartedScriptContentKey),
|
||||
LiveStartedScriptPath = GetValue(lookup, LiveStartedScriptPathKey, string.Empty),
|
||||
@@ -199,6 +260,11 @@ public sealed class SystemSettingsService : ISystemSettingsService
|
||||
ArgumentNullException.ThrowIfNull(request);
|
||||
|
||||
var now = DateTimeOffset.UtcNow;
|
||||
var douyinProxy = request.DouyinProxy ?? new PlatformProxySettingsDto();
|
||||
var bilibiliProxy = request.BilibiliProxy ?? new PlatformProxySettingsDto();
|
||||
var huyaProxy = request.HuyaProxy ?? new PlatformProxySettingsDto();
|
||||
var webDavUpload = request.WebDavUpload ?? new WebDavUploadSettingsDto();
|
||||
var s3Upload = request.S3Upload ?? new S3UploadSettingsDto();
|
||||
|
||||
await UpsertAsync(FfmpegPathKey, request.FfmpegPath.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(OutputRootKey, request.OutputRoot.Trim(), now, cancellationToken);
|
||||
@@ -240,6 +306,28 @@ public sealed class SystemSettingsService : ISystemSettingsService
|
||||
await UpsertAsync(EnableBackgroundPollingKey, request.EnableBackgroundPolling.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(AutoStartRecordingOnLiveKey, request.AutoStartRecordingOnLive.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(PollingIntervalSecondsKey, request.PollingIntervalSeconds.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(UseAliasForStorageKey, request.UseAliasForStorage.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(EnableFileUploadKey, request.EnableFileUpload.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(EnableAutoUploadKey, request.EnableAutoUpload.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(DeleteLocalFilesAfterUploadKey, request.DeleteLocalFilesAfterUpload.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(UploadTargetKey, request.UploadTarget.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(WebDavEndpointKey, webDavUpload.Endpoint.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(WebDavBasePathKey, webDavUpload.BasePath.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(WebDavUsernameKey, webDavUpload.Username.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(WebDavPasswordKey, webDavUpload.Password, now, cancellationToken);
|
||||
await UpsertAsync(S3EndpointKey, s3Upload.Endpoint.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(S3BucketKey, s3Upload.Bucket.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(S3RegionKey, s3Upload.Region.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(S3AccessKeyKey, s3Upload.AccessKey.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(S3SecretKeyKey, s3Upload.SecretKey, now, cancellationToken);
|
||||
await UpsertAsync(S3PrefixKey, s3Upload.Prefix.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(S3ForcePathStyleKey, s3Upload.ForcePathStyle.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(DouyinProxyEnabledKey, douyinProxy.Enabled.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(DouyinProxyUrlKey, douyinProxy.ProxyUrl.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(BilibiliProxyEnabledKey, bilibiliProxy.Enabled.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(BilibiliProxyUrlKey, bilibiliProxy.ProxyUrl.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(HuyaProxyEnabledKey, huyaProxy.Enabled.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(HuyaProxyUrlKey, huyaProxy.ProxyUrl.Trim(), now, cancellationToken);
|
||||
await UpsertAsync(EnableEventScriptsKey, request.EnableEventScripts.ToString(), now, cancellationToken);
|
||||
await UpsertAsync(LiveStartedScriptModeKey, NormalizeEventScriptMode(request.LiveStartedScriptMode), now, cancellationToken);
|
||||
await UpsertAsync(LiveStartedScriptPathKey, request.LiveStartedScriptPath.Trim(), now, cancellationToken);
|
||||
|
||||
Reference in New Issue
Block a user