125 lines
6.3 KiB
C#
125 lines
6.3 KiB
C#
using dy.net.model.dto;
|
|
using dy.net.model.entity;
|
|
using Newtonsoft.Json;
|
|
using SqlSugar;
|
|
using MediaStorageType = dy.net.model.dto.StorageType;
|
|
|
|
namespace dy.net.service
|
|
{
|
|
public class VideoExclusionService
|
|
{
|
|
private readonly ISqlSugarClient _db;
|
|
private readonly VideoTaskService _tasks;
|
|
|
|
public VideoExclusionService(ISqlSugarClient db, VideoTaskService tasks)
|
|
{
|
|
_db = db;
|
|
_tasks = tasks;
|
|
}
|
|
|
|
public async Task<VideoExclusionPage> GetPageAsync(VideoExclusionPageRequest request)
|
|
{
|
|
request ??= new VideoExclusionPageRequest();
|
|
var page = Math.Max(1, request.PageIndex);
|
|
var size = Math.Clamp(request.PageSize, 1, 100);
|
|
var query = _db.Queryable<DouyinVideoDelete>()
|
|
.WhereIF(!string.IsNullOrWhiteSpace(request.Keyword), x => x.VideoTitle.Contains(request.Keyword)
|
|
|| x.ViedoId.Contains(request.Keyword) || x.Author.Contains(request.Keyword));
|
|
return new VideoExclusionPage
|
|
{
|
|
TotalCount = await query.CountAsync(),
|
|
Items = await query.OrderByDescending(x => x.DeleteTime).Skip((page - 1) * size).Take(size).ToListAsync()
|
|
};
|
|
}
|
|
|
|
public async Task<UnexcludeVideosResult> UnexcludeAsync(UnexcludeVideosRequest request)
|
|
{
|
|
if (request?.Ids == null || request.Ids.Count == 0) throw new InvalidOperationException("请选择要取消排除的视频。");
|
|
var exclusions = await _db.Queryable<DouyinVideoDelete>().Where(x => request.Ids.Contains(x.Id)).ToListAsync();
|
|
if (exclusions.Count == 0) throw new KeyNotFoundException("未找到永久排除记录。");
|
|
var awemeIds = exclusions.Select(x => x.ViedoId).Where(x => !string.IsNullOrWhiteSpace(x)).Distinct().ToList();
|
|
var allDuplicates = awemeIds.Count == 0
|
|
? exclusions
|
|
: await _db.Queryable<DouyinVideoDelete>().Where(x => awemeIds.Contains(x.ViedoId)).ToListAsync();
|
|
var snapshots = request.CreateDownloadTask
|
|
? allDuplicates.Select(TryGetSnapshot).Where(x => x != null).GroupBy(x => x.AwemeId).Select(x => x.First()).ToList()
|
|
: new List<DouyinVideo>();
|
|
VideoDownloadTask task = null;
|
|
var result = new UnexcludeVideosResult();
|
|
var transaction = await _db.Ado.UseTranAsync(async () =>
|
|
{
|
|
if (request.CreateDownloadTask && snapshots.Count > 0)
|
|
{
|
|
task = await _tasks.CreateTaskAsync(VideoTaskType.ExclusionRestore, VideoTaskTrigger.UserAction,
|
|
$"取消排除恢复({snapshots.Count} 条)", storageType: snapshots[0].StorageType);
|
|
foreach (var video in snapshots)
|
|
{
|
|
var exclusion = allDuplicates.First(x => x.ViedoId == video.AwemeId);
|
|
await _tasks.AddItemAsync(task.Id, video.AwemeId, video.CookieId, null, video.ViedoType,
|
|
video.VideoTitle, video.Author, video.VideoSavePath,
|
|
new[] { video.VideoUrl }, video, video.FileSize, workerManaged: true);
|
|
}
|
|
}
|
|
await _db.Deleteable<DouyinVideoDelete>()
|
|
.Where(x => request.Ids.Contains(x.Id) || awemeIds.Contains(x.ViedoId)).ExecuteCommandAsync();
|
|
var now = DateTime.Now;
|
|
if (awemeIds.Count > 0)
|
|
{
|
|
var relatedTaskId = task?.Id;
|
|
await _db.Updateable<VideoDownloadTaskItem>()
|
|
.SetColumns(x => new VideoDownloadTaskItem
|
|
{
|
|
ExclusionReleasedAt = now,
|
|
RelatedTaskId = relatedTaskId,
|
|
UpdatedAt = now
|
|
}).Where(x => awemeIds.Contains(x.AwemeId) && x.SkipReason == VideoTaskSkipReason.PermanentlyExcluded)
|
|
.ExecuteCommandAsync();
|
|
}
|
|
});
|
|
if (!transaction.IsSuccess) throw new InvalidOperationException("取消排除失败:" + transaction.ErrorMessage);
|
|
|
|
result.ReleasedCount = awemeIds.Count;
|
|
result.QueuedCount = snapshots.Count;
|
|
result.TaskId = task?.Id;
|
|
result.CannotQueueIds = request.CreateDownloadTask
|
|
? awemeIds.Where(id => snapshots.All(x => x.AwemeId != id)).ToList()
|
|
: new List<string>();
|
|
result.Message = result.CannotQueueIds.Count > 0
|
|
? $"已取消排除 {result.ReleasedCount} 条,其中 {result.CannotQueueIds.Count} 条旧记录资料不足,将在下次正常同步时重新发现。"
|
|
: task == null
|
|
? $"已取消排除 {result.ReleasedCount} 条,将在下次正常同步时重新发现。"
|
|
: $"已取消排除并创建 {result.QueuedCount} 条恢复下载任务。";
|
|
return result;
|
|
}
|
|
|
|
private static DouyinVideo TryGetSnapshot(DouyinVideoDelete exclusion)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(exclusion.RestoreSnapshotJson))
|
|
{
|
|
try
|
|
{
|
|
var snapshot = JsonConvert.DeserializeObject<DouyinVideo>(exclusion.RestoreSnapshotJson);
|
|
if (snapshot != null && !string.IsNullOrWhiteSpace(snapshot.AwemeId) && !string.IsNullOrWhiteSpace(snapshot.CookieId)) return snapshot;
|
|
}
|
|
catch { }
|
|
}
|
|
if (string.IsNullOrWhiteSpace(exclusion.ViedoId) || string.IsNullOrWhiteSpace(exclusion.CookieId)
|
|
|| !exclusion.VideoType.HasValue || string.IsNullOrWhiteSpace(exclusion.VideoUrl)) return null;
|
|
return new DouyinVideo
|
|
{
|
|
Id = Guid.NewGuid().ToString("N"),
|
|
AwemeId = exclusion.ViedoId,
|
|
CookieId = exclusion.CookieId,
|
|
ViedoType = exclusion.VideoType.Value,
|
|
VideoTitle = exclusion.VideoTitle,
|
|
VideoSavePath = exclusion.VideoSavePath,
|
|
VideoUrl = exclusion.VideoUrl,
|
|
AuthorId = exclusion.AuthorId,
|
|
Author = exclusion.Author,
|
|
StorageType = MediaStorageType.Local,
|
|
SyncTime = DateTime.Now
|
|
};
|
|
}
|
|
}
|
|
}
|