feat: add fnOS packaging, storage workflows and release pipeline
This commit is contained in:
@@ -24,6 +24,11 @@ namespace dy.net.model.entity
|
||||
/// </summary>
|
||||
public int BatchCount { get; set; } = 18;
|
||||
|
||||
/// <summary>
|
||||
/// 新同步任务使用的全局存储。历史记录始终使用自身保存的存储类型。
|
||||
/// </summary>
|
||||
public dy.net.model.dto.StorageType StorageType { get; set; } = dy.net.model.dto.StorageType.Local;
|
||||
|
||||
/// <summary>
|
||||
/// 博主视频是否 直接用标题做文件名
|
||||
/// </summary>
|
||||
|
||||
@@ -145,5 +145,51 @@ namespace dy.net.model.entity
|
||||
/// </summary>
|
||||
[SugarColumn(Length = 500, IsNullable = true)]
|
||||
public string SeriesPath { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string WebDavCollectPath { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string WebDavFavoritePath { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string WebDavFollowPath { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string WebDavMixPath { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string WebDavSeriesPath { get; set; }
|
||||
|
||||
public int ConsecutiveSourceForbidden { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? SourceCooldownUntil { get; set; }
|
||||
|
||||
public bool SourceRequiresAuthorization { get; set; }
|
||||
|
||||
public bool SourceProbePending { get; set; }
|
||||
|
||||
public bool SourceProbeInProgress { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public int? LastSourceStatusCode { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string LastSourceError { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? SourceHealthUpdatedAt { get; set; }
|
||||
|
||||
public int ConsecutiveLiveCheckFailures { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LiveCheckCooldownUntil { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string LastLiveCheckError { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LiveCheckHealthUpdatedAt { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SqlSugar;
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
@@ -72,5 +73,57 @@ namespace dy.net.model.entity
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 100)]
|
||||
public string DouyinNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 直播状态监测独立开关,不影响作品同步开关。
|
||||
/// </summary>
|
||||
public bool LiveMonitorEnabled { get; set; }
|
||||
|
||||
public DouyinLiveStatusState LiveStatus { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 100)]
|
||||
public string LiveRoomId { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 100)]
|
||||
public string LiveWebRid { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 500)]
|
||||
public string LiveTitle { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LiveCheckedAt { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LiveStatusUpdatedAt { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LiveStartedAt { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 1000)]
|
||||
public string LiveCheckError { get; set; }
|
||||
|
||||
public bool LiveEmailNotificationEnabled { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 200)]
|
||||
public string LastLiveNotificationKey { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LastLiveNotificationAttemptAt { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LastLiveNotifiedAt { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 1000)]
|
||||
public string LastLiveNotificationError { get; set; }
|
||||
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public bool LiveStatusStale => LiveMonitorEnabled &&
|
||||
(!LiveStatusUpdatedAt.HasValue || DateTime.Now - LiveStatusUpdatedAt.Value > TimeSpan.FromMinutes(10) ||
|
||||
!string.IsNullOrWhiteSpace(LiveCheckError));
|
||||
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public string LiveRoomUrl => LiveStatus == DouyinLiveStatusState.Live && !string.IsNullOrWhiteSpace(LiveWebRid)
|
||||
? "https://live.douyin.com/" + Uri.EscapeDataString(LiveWebRid)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ namespace dy.net.model.entity
|
||||
public string SavePath { get; set; }
|
||||
|
||||
public string CookieId { get; set; }
|
||||
[SugarColumn(IsNullable = true, Length = 100)]
|
||||
public string VideoRecordId { get; set; }
|
||||
/// <summary>
|
||||
/// 0-未下载 1-下载成功 2-下载失败
|
||||
/// </summary>
|
||||
@@ -33,5 +35,12 @@ namespace dy.net.model.entity
|
||||
public DateTime CreateTime { get; set; }
|
||||
public DateTime DownTime { get; set; }
|
||||
public DateTime UpdateTime { get; set; }
|
||||
public int Attempts { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string ErrorMessage { get; set; }
|
||||
[SugarColumn(Length = 50, IsNullable = true)]
|
||||
public string TaskId { get; set; }
|
||||
[SugarColumn(Length = 50, IsNullable = true)]
|
||||
public string TaskItemId { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using dy.net.model.dto;
|
||||
using MediaStorageType = dy.net.model.dto.StorageType;
|
||||
using dy.net.utils;
|
||||
using SqlSugar;
|
||||
|
||||
@@ -77,6 +78,11 @@ namespace dy.net.model.entity
|
||||
/// </summary>
|
||||
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||
public string VideoSavePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该记录实际所在存储。旧数据默认值 0 表示本地文件。
|
||||
/// </summary>
|
||||
public MediaStorageType StorageType { get; set; } = MediaStorageType.Local;
|
||||
/// <summary>
|
||||
/// 视频封面地址
|
||||
/// </summary>
|
||||
@@ -171,5 +177,23 @@ namespace dy.net.model.entity
|
||||
/// </summary>
|
||||
[SugarColumn(Length = 200, IsNullable = true)]
|
||||
public string CateXId { get; set; }
|
||||
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public string PendingStoragePath { get; set; }
|
||||
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public string TemporaryDirectory { get; set; }
|
||||
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public string TaskItemId { get; set; }
|
||||
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public string TaskWarning { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 普通同步将旧存储记录安全替换到当前存储时使用的旧记录快照,不写入数据库。
|
||||
/// </summary>
|
||||
[SugarColumn(IsIgnore = true)]
|
||||
public DouyinVideo SupersededStorageSnapshot { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using SqlSugar;
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
@@ -25,5 +26,23 @@ namespace dy.net.model.entity
|
||||
public string VideoTitle { get; set; }
|
||||
[SugarColumn(IsNullable = true, Length = 1000)]
|
||||
public string VideoSavePath { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 200)]
|
||||
public string CookieId { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public VideoTypeEnum? VideoType { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 200)]
|
||||
public string AuthorId { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 500)]
|
||||
public string Author { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true, Length = 2000)]
|
||||
public string VideoUrl { get; set; }
|
||||
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string RestoreSnapshotJson { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "dy_email_notification_settings")]
|
||||
public sealed class EmailNotificationSettings
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; } = "default";
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
[SugarColumn(Length = 500, IsNullable = true)]
|
||||
public string Host { get; set; }
|
||||
|
||||
public int Port { get; set; } = 465;
|
||||
|
||||
public EmailSecurityMode SecurityMode { get; set; } = EmailSecurityMode.SslOnConnect;
|
||||
|
||||
[SugarColumn(Length = 500, IsNullable = true)]
|
||||
public string UserName { get; set; }
|
||||
|
||||
[SugarColumn(Length = -1, IsNullable = true)]
|
||||
public string ProtectedPassword { get; set; }
|
||||
|
||||
[SugarColumn(Length = 500, IsNullable = true)]
|
||||
public string FromAddress { get; set; }
|
||||
|
||||
[SugarColumn(Length = 200, IsNullable = true)]
|
||||
public string FromName { get; set; }
|
||||
|
||||
[SugarColumn(Length = 4000, IsNullable = true)]
|
||||
public string Recipients { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LastTestedAt { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string LastTestMessage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
using MediaStorageType = dy.net.model.dto.StorageType;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "media_storage_health")]
|
||||
public class MediaStorageHealth
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; } = "default";
|
||||
public MediaStorageHealthStatus Status { get; set; }
|
||||
public MediaStorageType StorageType { get; set; }
|
||||
[SugarColumn(Length = 128, IsNullable = true)]
|
||||
public string ConfigurationFingerprint { get; set; }
|
||||
public int ConsecutiveFailures { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string LastError { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LastFailedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LastProbedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "openlist_directory_repair_item")]
|
||||
[SugarIndex("idx_openlist_repair_item_task_status", nameof(TaskId), OrderByType.Asc,
|
||||
nameof(Status), OrderByType.Asc)]
|
||||
public sealed class OpenListDirectoryRepairItem
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; }
|
||||
[SugarColumn(Length = 50)]
|
||||
public string TaskId { get; set; }
|
||||
[SugarColumn(Length = 500)]
|
||||
public string DirectoryName { get; set; }
|
||||
[SugarColumn(Length = 2000)]
|
||||
public string ActualPath { get; set; }
|
||||
public OpenListDirectoryRepairItemStatus Status { get; set; }
|
||||
public int Attempts { get; set; }
|
||||
public int EntryCount { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string ErrorMessage { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)] public DateTime? CompletedAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "openlist_directory_repair_task")]
|
||||
[SugarIndex("idx_openlist_repair_created", nameof(CreatedAt), OrderByType.Desc)]
|
||||
public sealed class OpenListDirectoryRepairTask
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; }
|
||||
public OpenListDirectoryRepairStatus Status { get; set; }
|
||||
[SugarColumn(Length = 128)]
|
||||
public string ConfigurationFingerprint { get; set; }
|
||||
[SugarColumn(Length = 2000)]
|
||||
public string RequestedPath { get; set; }
|
||||
[SugarColumn(Length = 2000)]
|
||||
public string CanonicalPath { get; set; }
|
||||
[SugarColumn(Length = 2000)]
|
||||
public string ActualParentPath { get; set; }
|
||||
[SugarColumn(Length = 500)]
|
||||
public string RequestedName { get; set; }
|
||||
[SugarColumn(Length = 1000)]
|
||||
public string CandidatePattern { get; set; }
|
||||
public int TotalCount { get; set; }
|
||||
public int PendingCount { get; set; }
|
||||
public int EmptyCount { get; set; }
|
||||
public int DeletedCount { get; set; }
|
||||
public int SkippedCount { get; set; }
|
||||
public int FailedCount { get; set; }
|
||||
public int MissingCount { get; set; }
|
||||
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||
public string CurrentDirectory { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string ErrorMessage { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)] public DateTime? StartedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)] public DateTime? ScanCompletedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)] public DateTime? CompletedAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using SqlSugar;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "dy_openlist_settings")]
|
||||
public class OpenListSettings
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; } = "default";
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string Endpoint { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string BasePath { get; set; } = "/dysync";
|
||||
|
||||
/// <summary>本应用写入中转文件的本地绝对路径。</summary>
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string LocalStagingPath { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>OpenList 中映射到 LocalStagingPath 的源挂载根目录。</summary>
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string SourcePath { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>旧草稿字段,仅用于平滑升级;新版本统一使用 BasePath 作为目标目录。</summary>
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string DestinationPath { get; set; } = string.Empty;
|
||||
|
||||
[SugarColumn(Length = 500, IsNullable = true)]
|
||||
public string UserName { get; set; }
|
||||
|
||||
[SugarColumn(Length = -1, IsNullable = true)]
|
||||
public string ProtectedPassword { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LastTestedAt { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string LastTestMessage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "openlist_transfer_job")]
|
||||
[SugarIndex("idx_openlist_transfer_target", nameof(ConfigurationFingerprint), OrderByType.Asc,
|
||||
nameof(LogicalTargetPath), OrderByType.Asc, nameof(Status), OrderByType.Asc)]
|
||||
public sealed class OpenListTransferJob
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; }
|
||||
public OpenListTransferStatus Status { get; set; }
|
||||
[SugarColumn(Length = 128)]
|
||||
public string ConfigurationFingerprint { get; set; }
|
||||
[SugarColumn(Length = 2000)]
|
||||
public string LogicalTargetPath { get; set; }
|
||||
[SugarColumn(Length = 2000)]
|
||||
public string ActualTargetPath { get; set; }
|
||||
[SugarColumn(Length = 2000)]
|
||||
public string LocalSourcePath { get; set; }
|
||||
[SugarColumn(Length = 2000)]
|
||||
public string OpenListSourcePath { get; set; }
|
||||
[SugarColumn(Length = 2000)]
|
||||
public string StagedTargetPath { get; set; }
|
||||
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||
public string BackupTargetPath { get; set; }
|
||||
public long ExpectedLength { get; set; }
|
||||
[SugarColumn(Length = 200, IsNullable = true)]
|
||||
public string ExternalTaskId { get; set; }
|
||||
public double ExternalProgress { get; set; }
|
||||
public int Attempts { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? ExternalTaskStartedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LastProgressAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? NextAttemptAt { get; set; }
|
||||
[SugarColumn(Length = 50, IsNullable = true)]
|
||||
public string LeaseOwner { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LeaseUntil { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string ErrorMessage { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? CompletedAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
using AppStorageType = dy.net.model.dto.StorageType;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "storage_migration_item")]
|
||||
[SugarIndex("idx_migration_item_task_stage", nameof(TaskId), OrderByType.Asc, nameof(Stage), OrderByType.Asc)]
|
||||
public class StorageMigrationItem
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; }
|
||||
[SugarColumn(Length = 50)]
|
||||
public string TaskId { get; set; }
|
||||
[SugarColumn(Length = 200)]
|
||||
public string VideoId { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public AppStorageType? SourceStorageType { get; set; }
|
||||
public bool AdoptExistingTarget { get; set; }
|
||||
public StorageMigrationItemStage Stage { get; set; }
|
||||
public int Attempts { get; set; }
|
||||
public long ExpectedLength { get; set; }
|
||||
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||
public string OldVideoPath { get; set; }
|
||||
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||
public string TargetVideoPath { get; set; }
|
||||
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||
public string TargetCoverPath { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1)]
|
||||
public string OldSnapshotJson { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string AttachmentPlanJson { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string UploadedPathsJson { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string OwnedRemotePathsJson { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string ErrorMessage { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string WarningMessage { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? CompletedAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
using AppStorageType = dy.net.model.dto.StorageType;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "storage_migration_task")]
|
||||
public class StorageMigrationTask
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; }
|
||||
public StorageMigrationTaskStatus Status { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public AppStorageType? TargetStorageType { get; set; }
|
||||
public int Concurrency { get; set; } = 1;
|
||||
public int TotalCount { get; set; }
|
||||
public int PendingCount { get; set; }
|
||||
public int SuccessCount { get; set; }
|
||||
public int WarningCount { get; set; }
|
||||
public int FailedCount { get; set; }
|
||||
public int RemovedCount { get; set; }
|
||||
public long TotalBytes { get; set; }
|
||||
[SugarColumn(Length = 128)]
|
||||
public string ConfigurationFingerprint { get; set; }
|
||||
[SugarColumn(Length = 200, IsNullable = true)]
|
||||
public string CurrentVideoId { get; set; }
|
||||
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||
public string CurrentFile { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string ErrorMessage { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? StartedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? CompletedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? CleanedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? RolledBackAt { get; set; }
|
||||
/// <summary>
|
||||
/// 已归档的终态任务不再出现在系统配置和任务中心,但保留条目用于审计及失败记录处理。
|
||||
/// </summary>
|
||||
public bool IsArchived { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
using MediaStorageType = dy.net.model.dto.StorageType;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "video_download_task")]
|
||||
[SugarIndex("idx_video_task_created", nameof(CreatedAt), OrderByType.Desc)]
|
||||
public class VideoDownloadTask
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; }
|
||||
public VideoTaskType Type { get; set; }
|
||||
public VideoTaskTrigger Trigger { get; set; }
|
||||
public VideoTaskStatus Status { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public VideoTypeEnum? VideoType { get; set; }
|
||||
public MediaStorageType StorageType { get; set; }
|
||||
[SugarColumn(Length = 500)]
|
||||
public string Title { get; set; }
|
||||
[SugarColumn(Length = 128, IsNullable = true)]
|
||||
public string StorageFingerprint { get; set; }
|
||||
public int TotalCount { get; set; }
|
||||
public int PendingCount { get; set; }
|
||||
public int RunningCount { get; set; }
|
||||
public int SuccessCount { get; set; }
|
||||
public int WarningCount { get; set; }
|
||||
public int FailedCount { get; set; }
|
||||
public int SkippedCount { get; set; }
|
||||
public bool IsArchived { get; set; }
|
||||
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||
public string CurrentFile { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string ErrorMessage { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? StartedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? CompletedAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using dy.net.model.dto;
|
||||
using SqlSugar;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "video_download_task_item")]
|
||||
[SugarIndex("idx_video_task_item_task_stage", nameof(TaskId), OrderByType.Asc, nameof(Stage), OrderByType.Asc)]
|
||||
public class VideoDownloadTaskItem
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; }
|
||||
[SugarColumn(Length = 50)]
|
||||
public string TaskId { get; set; }
|
||||
[SugarColumn(Length = 200, IsNullable = true)]
|
||||
public string VideoId { get; set; }
|
||||
[SugarColumn(Length = 200, IsNullable = true)]
|
||||
public string AwemeId { get; set; }
|
||||
[SugarColumn(Length = 200, IsNullable = true)]
|
||||
public string CookieId { get; set; }
|
||||
[SugarColumn(Length = 500, IsNullable = true)]
|
||||
public string CookieName { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public VideoTypeEnum? VideoType { get; set; }
|
||||
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||
public string VideoTitle { get; set; }
|
||||
[SugarColumn(Length = 500, IsNullable = true)]
|
||||
public string Author { get; set; }
|
||||
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||
public string TargetPath { get; set; }
|
||||
public VideoTaskItemStage Stage { get; set; }
|
||||
public VideoTaskErrorType ErrorType { get; set; }
|
||||
public VideoTaskSkipReason SkipReason { get; set; }
|
||||
public int Attempts { get; set; }
|
||||
public bool WorkerManaged { get; set; }
|
||||
public long ExpectedLength { get; set; }
|
||||
public long ActualLength { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string SourceUrlsJson { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string RetrySnapshotJson { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string ErrorMessage { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string WarningMessage { get; set; }
|
||||
public bool CleanupPending { get; set; }
|
||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||
public string CleanupError { get; set; }
|
||||
[SugarColumn(Length = 255, IsNullable = true)]
|
||||
public string SourceHost { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public int? HttpStatusCode { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? RetryAfter { get; set; }
|
||||
[SugarColumn(Length = 50, IsNullable = true)]
|
||||
public string ExclusionId { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? ExclusionReleasedAt { get; set; }
|
||||
[SugarColumn(Length = 50, IsNullable = true)]
|
||||
public string RelatedTaskId { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? CompletedAt { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using SqlSugar;
|
||||
|
||||
namespace dy.net.model.entity
|
||||
{
|
||||
[SugarTable(TableName = "dy_webdav_settings")]
|
||||
public class WebDavSettings
|
||||
{
|
||||
[SugarColumn(IsPrimaryKey = true, Length = 50)]
|
||||
public string Id { get; set; } = "default";
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string Endpoint { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string BasePath { get; set; } = "/dysync";
|
||||
|
||||
[SugarColumn(Length = 500, IsNullable = true)]
|
||||
public string UserName { get; set; }
|
||||
|
||||
[SugarColumn(Length = -1, IsNullable = true)]
|
||||
public string ProtectedPassword { get; set; }
|
||||
|
||||
public bool AllowInvalidCertificate { get; set; }
|
||||
|
||||
[SugarColumn(IsNullable = true)]
|
||||
public DateTime? LastTestedAt { get; set; }
|
||||
|
||||
[SugarColumn(Length = 1000, IsNullable = true)]
|
||||
public string LastTestMessage { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user