Files
douyin/service/VideoExclusionService.cs

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
};
}
}
}