代码整理
This commit is contained in:
+1
-5
@@ -1,8 +1,4 @@
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration.Json;
|
||||||
using Microsoft.Extensions.Configuration.Json;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace dy.net
|
namespace dy.net
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
using ClockSnowFlake;
|
using ClockSnowFlake;
|
||||||
|
using dy.net.model.dto;
|
||||||
|
using dy.net.service;
|
||||||
|
using dy.net.utils;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using dy.net.service;
|
|
||||||
using dy.net.utils;
|
|
||||||
using dy.net.model.dto;
|
|
||||||
|
|
||||||
namespace dy.net.Controllers
|
namespace dy.net.Controllers
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
using dy.net.model.dto;
|
using dy.net.model.dto;
|
||||||
using dy.net.model.entity;
|
|
||||||
using dy.net.service;
|
using dy.net.service;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace dy.net.Controllers
|
namespace dy.net.Controllers
|
||||||
@@ -56,12 +54,12 @@ namespace dy.net.Controllers
|
|||||||
public async Task<IActionResult> BatchSave(List<DouyinCollectCateSwitchDto> dto)
|
public async Task<IActionResult> BatchSave(List<DouyinCollectCateSwitchDto> dto)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(dto.Any(x=> !DouyinFileNameHelper.IsValidWithoutSpecialChars(x.SaveFolder)))
|
if (dto.Any(x => !DouyinFileNameHelper.IsValidWithoutSpecialChars(x.SaveFolder)))
|
||||||
{
|
{
|
||||||
return ApiResult.Fail("有部分文件名不符合要求,请检查");
|
return ApiResult.Fail("有部分文件名不符合要求,请检查");
|
||||||
}
|
}
|
||||||
|
|
||||||
var result= await _douyinCollectCateService.BatchSwitchSync(dto);
|
var result = await _douyinCollectCateService.BatchSwitchSync(dto);
|
||||||
return ApiResult.SuccOrFail(result, result);
|
return ApiResult.SuccOrFail(result, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,8 @@ using dy.net.service;
|
|||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using dy.sync.lib;
|
using dy.sync.lib;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Quartz.Util;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using static Dm.net.buffer.ByteArrayBuffer;
|
|
||||||
|
|
||||||
namespace dy.net.Controllers
|
namespace dy.net.Controllers
|
||||||
{
|
{
|
||||||
@@ -64,50 +58,53 @@ namespace dy.net.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 导入配置
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dto"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[HttpPost("importConf")]
|
[HttpPost("importConf")]
|
||||||
public async Task<IActionResult> ImportConf(AppConfigImportDto dto)
|
public async Task<IActionResult> ImportConf(AppConfigImportDto dto)
|
||||||
{
|
{
|
||||||
if (dto == null)
|
if (dto == null)
|
||||||
return ApiResult.Fail("json数据为空");
|
return ApiResult.Fail("json数据为空");
|
||||||
|
|
||||||
var follows = dto.follows;
|
await HandleFollowsImport(dto.follows);
|
||||||
if (follows != null && follows.Count > 0)
|
await HandleConfigImport(dto.conf);
|
||||||
{
|
await HandleCookiesImport(dto.cookies);
|
||||||
var add = await douyinFollowService.AddHandFollows(follows);
|
|
||||||
if (add)
|
|
||||||
Serilog.Log.Debug("关注列表导入成功");
|
|
||||||
}
|
|
||||||
|
|
||||||
var conf = dto.conf;
|
|
||||||
if (conf != null)
|
|
||||||
{
|
|
||||||
if (conf.BatchCount > 30)
|
|
||||||
{
|
|
||||||
Serilog.Log.Debug("$对不起,为了项目能长久稳定运行,还是最大不要超过30吧。。。");
|
|
||||||
conf.BatchCount = 30;
|
|
||||||
}
|
|
||||||
var update = await commonService.UpdateConfig(conf);
|
|
||||||
if (update)
|
|
||||||
Serilog.Log.Debug("系统配置导入成功");
|
|
||||||
}
|
|
||||||
var cookies = dto.cookies;
|
|
||||||
|
|
||||||
if (cookies != null && cookies.Count > 0)
|
|
||||||
{
|
|
||||||
var importCookies = await douyinCookieService.ImportCookies(cookies);
|
|
||||||
if (importCookies)
|
|
||||||
{
|
|
||||||
Serilog.Log.Debug("抖音Cookie配置导入成功");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ApiResult.Success();
|
return ApiResult.Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task HandleFollowsImport(List<DouyinFollowed> follows)
|
||||||
|
{
|
||||||
|
if (follows?.Count > 0)
|
||||||
|
{
|
||||||
|
var added = await douyinFollowService.AddHandFollows(follows);
|
||||||
|
if (added)
|
||||||
|
Serilog.Log.Debug("关注列表导入成功");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleConfigImport(AppConfig conf)
|
||||||
|
{
|
||||||
|
if (conf == null) return;
|
||||||
|
|
||||||
|
if (conf.BatchCount > 30)
|
||||||
|
{
|
||||||
|
Serilog.Log.Debug("对不起,为了项目能长久稳定运行,还是最大不要超过30吧。。。");
|
||||||
|
conf.BatchCount = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
var updated = await commonService.UpdateConfig(conf);
|
||||||
|
if (updated)
|
||||||
|
Serilog.Log.Debug("系统配置导入成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task HandleCookiesImport(List<DouyinCookie> cookies)
|
||||||
|
{
|
||||||
|
if (cookies?.Count > 0)
|
||||||
|
{
|
||||||
|
var imported = await douyinCookieService.ImportCookies(cookies);
|
||||||
|
if (imported)
|
||||||
|
Serilog.Log.Debug("抖音Cookie配置导入成功");
|
||||||
|
}
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 分页查询
|
/// 分页查询
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -181,45 +178,51 @@ namespace dy.net.Controllers
|
|||||||
[AllowAnonymous]
|
[AllowAnonymous]
|
||||||
public async Task<IActionResult> DeskInitAsync([FromBody] DouyinCookie dyUserCookies)
|
public async Task<IActionResult> DeskInitAsync([FromBody] DouyinCookie dyUserCookies)
|
||||||
{
|
{
|
||||||
|
// 1. 基础赋值
|
||||||
dyUserCookies.Id = IdGener.GetLong().ToString();
|
dyUserCookies.Id = IdGener.GetLong().ToString();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(dyUserCookies.SavePath))
|
// 2. 路径权限校验
|
||||||
{
|
var pathValidationResult = ValidatePaths(dyUserCookies);
|
||||||
return ApiResult.Fail("收藏存储路径不能为空");
|
if (!pathValidationResult.Success)
|
||||||
}
|
return ApiResult.Fail(pathValidationResult.Message);
|
||||||
if (!DouyinFileUtils.HasDirectoryReadWritePermission(dyUserCookies.SavePath))
|
|
||||||
{
|
|
||||||
return ApiResult.Fail($"请在飞牛应用设置里面将{dyUserCookies.SavePath}添加读写权限");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(dyUserCookies.FavSavePath) && !DouyinFileUtils.HasDirectoryReadWritePermission(dyUserCookies.FavSavePath))
|
// 3. Cookie 有效性校验
|
||||||
{
|
var cookieValid = await httpClientService.CheckCookie(dyUserCookies);
|
||||||
return ApiResult.Fail($"请在飞牛应用设置里面将{dyUserCookies.FavSavePath}添加读写权限");
|
if (!cookieValid)
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(dyUserCookies.UpSavePath) && !DouyinFileUtils.HasDirectoryReadWritePermission(dyUserCookies.UpSavePath))
|
|
||||||
{
|
|
||||||
return ApiResult.Fail($"请在飞牛应用设置里面将{dyUserCookies.UpSavePath}添加读写权限");
|
|
||||||
}
|
|
||||||
|
|
||||||
//if (!string.IsNullOrWhiteSpace(dyUserCookies.ImgSavePath) && !DouyinFileUtils.HasDirectoryReadWritePermission(dyUserCookies.ImgSavePath))
|
|
||||||
//{
|
|
||||||
// return ApiResult.Fail($"请在飞牛应用设置里面将{dyUserCookies.ImgSavePath}添加读写权限");
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
var checkCk = await httpClientService.CheckCookie(dyUserCookies);
|
|
||||||
if (!checkCk)
|
|
||||||
{
|
|
||||||
return ApiResult.Fail("Cookie无效,请按照文档提示重新获取有效Cookie,不要使用插件获取cookie");
|
return ApiResult.Fail("Cookie无效,请按照文档提示重新获取有效Cookie,不要使用插件获取cookie");
|
||||||
|
|
||||||
|
// 4. 保存到数据库
|
||||||
|
var saved = await dyCookieService.Add(dyUserCookies);
|
||||||
|
return saved ? ApiResult.Success() : ApiResult.Fail("添加失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
private (bool Success, string Message) ValidatePaths(DouyinCookie cookie)
|
||||||
|
{
|
||||||
|
var pathsToCheck = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "收藏存储路径", cookie.SavePath },
|
||||||
|
{ "喜欢视频存储路径", cookie.FavSavePath },
|
||||||
|
{ "上传视频存储路径", cookie.UpSavePath },
|
||||||
|
// { "图片存储路径", cookie.ImgSavePath } // 可随时启用
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var (label, path) in pathsToCheck)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(path))
|
||||||
|
{
|
||||||
|
if (!DouyinFileUtils.HasDirectoryReadWritePermission(path))
|
||||||
|
{
|
||||||
|
return (false, $"请在飞牛应用设置里面将 {path} 添加读写权限({label})");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await dyCookieService.Add(dyUserCookies);
|
if (string.IsNullOrWhiteSpace(cookie.SavePath))
|
||||||
if (result)
|
|
||||||
{
|
{
|
||||||
return ApiResult.Success();
|
return (false, "收藏存储路径不能为空");
|
||||||
}
|
}
|
||||||
return ApiResult.Fail("添加失败");
|
|
||||||
|
return (true, string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -414,7 +417,7 @@ namespace dy.net.Controllers
|
|||||||
Path.GetFileNameWithoutExtension(filePath) != "silent_10")
|
Path.GetFileNameWithoutExtension(filePath) != "silent_10")
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var fileNames = customMusics.Select(f => new {filename= Path.GetFileName(f) }).Where(x=>x.filename!= "silent_10.mp3").ToList();
|
var fileNames = customMusics.Select(f => new { filename = Path.GetFileName(f) }).Where(x => x.filename != "silent_10.mp3").ToList();
|
||||||
return ApiResult.Success(fileNames);
|
return ApiResult.Success(fileNames);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using dy.net.model.entity;
|
|||||||
using dy.net.service;
|
using dy.net.service;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace dy.net.Controllers
|
namespace dy.net.Controllers
|
||||||
@@ -62,7 +61,7 @@ namespace dy.net.Controllers
|
|||||||
public async Task<IActionResult> AddFollow(DouyinFollowed followed)
|
public async Task<IActionResult> AddFollow(DouyinFollowed followed)
|
||||||
{
|
{
|
||||||
var res = await _douyinFollowService.AddAsync(followed);
|
var res = await _douyinFollowService.AddAsync(followed);
|
||||||
return ApiResult.SuccOrFail(res,"", res ? "" : "添加失败,或者已存在相同secuid和uid");
|
return ApiResult.SuccOrFail(res, "", res ? "" : "添加失败,或者已存在相同secuid和uid");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -89,7 +88,7 @@ namespace dy.net.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var result= await _douyinFollowService.OpenOrCloseSync(dto);
|
var result = await _douyinFollowService.OpenOrCloseSync(dto);
|
||||||
return ApiResult.SuccOrFail(result, result);
|
return ApiResult.SuccOrFail(result, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +107,7 @@ namespace dy.net.Controllers
|
|||||||
[HttpPost("delete")]
|
[HttpPost("delete")]
|
||||||
public async Task<IActionResult> DeleteFollow(FollowUpdateDto dto)
|
public async Task<IActionResult> DeleteFollow(FollowUpdateDto dto)
|
||||||
{
|
{
|
||||||
var result= await _douyinFollowService.DeleteFollow(dto);
|
var result = await _douyinFollowService.DeleteFollow(dto);
|
||||||
return ApiResult.SuccOrFail(result, result);
|
return ApiResult.SuccOrFail(result, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
using dy.net.model.dto;
|
using dy.net.model.dto;
|
||||||
using dy.net.service;
|
using dy.net.service;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace dy.net.Controllers
|
namespace dy.net.Controllers
|
||||||
{
|
{
|
||||||
@@ -14,14 +11,14 @@ namespace dy.net.Controllers
|
|||||||
private readonly IWebHostEnvironment webHostEnvironment;
|
private readonly IWebHostEnvironment webHostEnvironment;
|
||||||
private readonly LogInfoService logInfoService;
|
private readonly LogInfoService logInfoService;
|
||||||
|
|
||||||
public LogsController(IWebHostEnvironment webHostEnvironment,LogInfoService logInfoService)
|
public LogsController(IWebHostEnvironment webHostEnvironment, LogInfoService logInfoService)
|
||||||
{
|
{
|
||||||
this.webHostEnvironment = webHostEnvironment;
|
this.webHostEnvironment = webHostEnvironment;
|
||||||
this.logInfoService = logInfoService;
|
this.logInfoService = logInfoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("/api/logs/GetLog/{type}/{date}")]
|
[HttpGet("/api/logs/GetLog/{type}/{date}")]
|
||||||
public async Task<IActionResult> GetLog([FromRoute]string type, [FromRoute] string date)
|
public async Task<IActionResult> GetLog([FromRoute] string type, [FromRoute] string date)
|
||||||
{
|
{
|
||||||
var filePath = Path.Combine(webHostEnvironment.IsDevelopment() ? Directory.GetCurrentDirectory() : AppDomain.CurrentDomain.BaseDirectory, "logs", $"log-{type}-{date}.txt");
|
var filePath = Path.Combine(webHostEnvironment.IsDevelopment() ? Directory.GetCurrentDirectory() : AppDomain.CurrentDomain.BaseDirectory, "logs", $"log-{type}-{date}.txt");
|
||||||
if (!System.IO.File.Exists(filePath))
|
if (!System.IO.File.Exists(filePath))
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ using dy.net.service;
|
|||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
|
|
||||||
namespace dy.net.Controllers
|
namespace dy.net.Controllers
|
||||||
{
|
{
|
||||||
@@ -500,7 +498,7 @@ namespace dy.net.Controllers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>7天图表数据列表</returns>
|
/// <returns>7天图表数据列表</returns>
|
||||||
[HttpGet("chart/{day}")]
|
[HttpGet("chart/{day}")]
|
||||||
public async Task<IActionResult> Chart([FromRoute]int day=7)
|
public async Task<IActionResult> Chart([FromRoute] int day = 7)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -514,7 +512,7 @@ namespace dy.net.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("/Move")]
|
[HttpGet("/Move")]
|
||||||
public async Task <IActionResult> Move()
|
public async Task<IActionResult> Move()
|
||||||
{
|
{
|
||||||
await douyinVideoService.HandOldFolderVideos();
|
await douyinVideoService.HandOldFolderVideos();
|
||||||
|
|
||||||
|
|||||||
+5
-70
@@ -1,7 +1,6 @@
|
|||||||
using dy.net.extension;
|
using dy.net.extension;
|
||||||
using dy.net.service;
|
using dy.net.service;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using dy.sync.lib;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -117,13 +116,13 @@ namespace dy.net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 配置依赖注入服务
|
/// 配置依赖注入服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void ConfigureServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment environment,string dbPath)
|
private static void ConfigureServices(IServiceCollection services, IConfiguration config, IWebHostEnvironment environment, string dbPath)
|
||||||
{
|
{
|
||||||
|
|
||||||
//打印logo
|
//打印logo
|
||||||
//PrintApp();
|
//PrintApp();
|
||||||
|
|
||||||
services.AddSingleton(new Appsettings (config));
|
services.AddSingleton(new Appsettings(config));
|
||||||
// 雪花ID生成器
|
// 雪花ID生成器
|
||||||
services.AddSnowFlakeId(options => options.WorkId = new Random().Next(1, 100));
|
services.AddSnowFlakeId(options => options.WorkId = new Random().Next(1, 100));
|
||||||
|
|
||||||
@@ -202,7 +201,7 @@ namespace dy.net
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化应用服务数据
|
/// 初始化应用服务数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void InitApplicationServices(WebApplication app,bool isDevelopment)
|
private static void InitApplicationServices(WebApplication app, bool isDevelopment)
|
||||||
{
|
{
|
||||||
using var scope = app.Services.CreateScope();
|
using var scope = app.Services.CreateScope();
|
||||||
var services = scope.ServiceProvider;
|
var services = scope.ServiceProvider;
|
||||||
@@ -211,7 +210,7 @@ namespace dy.net
|
|||||||
{
|
{
|
||||||
// 初始化用户
|
// 初始化用户
|
||||||
var userService = services.GetRequiredService<AdminUserService>();
|
var userService = services.GetRequiredService<AdminUserService>();
|
||||||
userService.InitUser("douyin","douyin2026");
|
userService.InitUser("douyin", "douyin2026");
|
||||||
var commonService = services.GetRequiredService<DouyinCommonService>();
|
var commonService = services.GetRequiredService<DouyinCommonService>();
|
||||||
|
|
||||||
// 更新视频类型--兼容老版本--不再需要
|
// 更新视频类型--兼容老版本--不再需要
|
||||||
@@ -227,7 +226,7 @@ namespace dy.net
|
|||||||
quartzJobService.InitOrReStartAllJobs(config?.Cron <= 0 ? "30" : config.Cron.ToString());
|
quartzJobService.InitOrReStartAllJobs(config?.Cron <= 0 ? "30" : config.Cron.ToString());
|
||||||
}
|
}
|
||||||
// 初始化Cookie
|
// 初始化Cookie
|
||||||
var deploy= Appsettings.Get("deploy");
|
var deploy = Appsettings.Get("deploy");
|
||||||
if (deploy != null && deploy == "docker")//docker环境直接初始化一个默认的配置
|
if (deploy != null && deploy == "docker")//docker环境直接初始化一个默认的配置
|
||||||
{
|
{
|
||||||
var cookieService = services.GetRequiredService<DouyinCookieService>();
|
var cookieService = services.GetRequiredService<DouyinCookieService>();
|
||||||
@@ -240,69 +239,5 @@ namespace dy.net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void PrintApp()
|
|
||||||
{
|
|
||||||
Console.ForegroundColor = ConsoleColor.DarkCyan;
|
|
||||||
|
|
||||||
// 步骤1:定义原始ASCII艺术字行(无缩进)
|
|
||||||
List<string> originalArtLines = new List<string>
|
|
||||||
{
|
|
||||||
" __ __ ",
|
|
||||||
" ___/ /_ __ ___ __ _____ ____ ___ ___ / /_",
|
|
||||||
"/ _ / // / (_-</ // / _ \\__/ / _ \\/ -_) __/",
|
|
||||||
"\\_,_/\\_, (_)___/\\_, /_//_/\\__(_)_//_/\\__/\\__/ ",
|
|
||||||
" /___/ /___/ "
|
|
||||||
};
|
|
||||||
|
|
||||||
// 步骤2:设置缩进字符数(可自由修改:4、8、10 等)
|
|
||||||
int indentCount = 4;
|
|
||||||
string indent = new string(' ', indentCount); // 生成对应数量的空格
|
|
||||||
|
|
||||||
// 步骤3:给每行添加缩进
|
|
||||||
List<string> indentedArtLines = new List<string>();
|
|
||||||
foreach (var line in originalArtLines)
|
|
||||||
{
|
|
||||||
indentedArtLines.Add(indent + line); // 每行开头拼接缩进空格
|
|
||||||
}
|
|
||||||
|
|
||||||
// 步骤4:找到缩进后最长行的长度(避免越界)
|
|
||||||
int maxLength = 0;
|
|
||||||
foreach (var line in indentedArtLines)
|
|
||||||
{
|
|
||||||
if (line.Length > maxLength) maxLength = line.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 步骤5:按列推进打印(从左到右,包含缩进)
|
|
||||||
for (int col = 0; col < maxLength; col++)
|
|
||||||
{
|
|
||||||
Console.SetCursorPosition(0, 0); // 重置光标到第一行开头
|
|
||||||
|
|
||||||
for (int row = 0; row < indentedArtLines.Count; row++)
|
|
||||||
{
|
|
||||||
// 定位到「当前列、当前行」(已包含缩进偏移)
|
|
||||||
Console.SetCursorPosition(col, row);
|
|
||||||
|
|
||||||
// 打印字符(无字符则补空格)
|
|
||||||
if (col < indentedArtLines[row].Length)
|
|
||||||
{
|
|
||||||
Console.Write(indentedArtLines[row][col]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.Write(' ');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.Sleep(20); // 列推进速度(可调整:10=快,50=慢)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打印完成后,光标移到艺术字下方
|
|
||||||
Console.SetCursorPosition(0, indentedArtLines.Count);
|
|
||||||
Console.WriteLine();
|
|
||||||
Console.ResetColor();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<_PublishTargetUrl>E:\code\dysync\bin\Release\net6.0\publish\</_PublishTargetUrl>
|
<_PublishTargetUrl>E:\code\dysync\bin\Release\net6.0\publish\</_PublishTargetUrl>
|
||||||
<History>True|2026-01-23T05:36:48.4086406Z||;True|2026-01-23T13:30:27.2924204+08:00||;True|2026-01-23T13:02:53.3219368+08:00||;True|2026-01-23T13:01:54.3466638+08:00||;True|2026-01-23T13:01:28.8560809+08:00||;True|2026-01-22T23:18:32.0400436+08:00||;True|2026-01-22T22:29:29.5746209+08:00||;True|2026-01-22T21:32:21.7284081+08:00||;True|2026-01-22T21:20:26.5985955+08:00||;False|2026-01-22T21:20:21.1372539+08:00||;True|2026-01-22T21:11:18.3771739+08:00||;True|2026-01-22T20:58:55.9862778+08:00||;True|2026-01-22T20:51:48.6699461+08:00||;False|2026-01-22T20:51:42.2079210+08:00||;True|2026-01-22T20:50:34.7280114+08:00||;True|2026-01-22T20:50:11.1588492+08:00||;True|2026-01-22T16:11:14.0626037+08:00||;True|2026-01-22T15:53:16.6377347+08:00||;True|2026-01-22T15:45:34.0935091+08:00||;True|2026-01-22T12:44:28.1577014+08:00||;True|2026-01-22T12:40:45.7449335+08:00||;True|2026-01-22T12:39:07.0683214+08:00||;True|2026-01-22T09:55:49.7086190+08:00||;True|2026-01-22T01:37:53.6972395+08:00||;True|2026-01-22T01:34:14.2142463+08:00||;True|2026-01-22T01:32:50.9228911+08:00||;True|2026-01-22T01:29:43.8871986+08:00||;True|2026-01-22T01:29:40.7838709+08:00||;True|2026-01-22T01:27:34.4763970+08:00||;True|2026-01-22T01:26:55.0117367+08:00||;True|2026-01-22T01:23:19.4789587+08:00||;True|2026-01-19T10:19:44.8997385+08:00||;True|2026-01-19T10:11:10.2305307+08:00||;True|2026-01-17T00:52:08.8180346+08:00||;False|2026-01-17T00:52:03.1829000+08:00||;True|2026-01-17T00:45:04.0498090+08:00||;True|2026-01-16T21:00:57.7239379+08:00||;True|2026-01-16T21:00:03.3912989+08:00||;True|2026-01-16T20:56:08.5505592+08:00||;True|2026-01-16T20:46:32.3067302+08:00||;True|2026-01-15T22:18:57.9835738+08:00||;True|2026-01-15T22:07:25.4753938+08:00||;True|2026-01-15T22:07:14.8243754+08:00||;True|2026-01-15T21:40:13.2613927+08:00||;True|2026-01-15T20:57:56.6291682+08:00||;True|2026-01-15T20:57:47.1363536+08:00||;True|2026-01-15T20:08:44.4710883+08:00||;True|2026-01-15T20:04:51.8284314+08:00||;False|2026-01-15T20:04:45.3258155+08:00||;True|2026-01-15T19:59:11.7907672+08:00||;True|2026-01-15T01:10:48.9066941+08:00||;True|2026-01-15T01:03:23.6216975+08:00||;True|2026-01-15T01:03:16.3364591+08:00||;False|2026-01-15T01:03:10.5654436+08:00||;True|2026-01-15T00:49:21.6559622+08:00||;True|2026-01-15T00:10:42.7288439+08:00||;True|2026-01-15T00:06:28.4241682+08:00||;True|2026-01-13T22:34:15.2372411+08:00||;True|2026-01-13T22:26:46.4522947+08:00||;True|2026-01-13T22:15:56.9735179+08:00||;True|2026-01-13T22:15:51.8250677+08:00||;False|2026-01-13T22:15:46.6608690+08:00||;True|2026-01-13T22:03:06.4683237+08:00||;False|2026-01-13T22:03:01.2036027+08:00||;True|2026-01-13T21:36:05.8776209+08:00||;True|2026-01-13T21:33:02.0766289+08:00||;False|2026-01-13T21:32:57.1976141+08:00||;True|2026-01-13T19:14:35.2519439+08:00||;True|2026-01-13T15:07:50.0836745+08:00||;False|2026-01-13T15:06:35.5929685+08:00||;True|2026-01-13T10:21:41.6012776+08:00||;True|2026-01-13T09:57:25.4788847+08:00||;True|2026-01-13T09:53:14.4900360+08:00||;True|2026-01-13T09:23:53.6465295+08:00||;True|2026-01-12T22:04:14.5886955+08:00||;False|2026-01-12T22:04:08.2008101+08:00||;True|2026-01-12T21:53:46.9947176+08:00||;True|2026-01-12T21:11:15.8358024+08:00||;True|2026-01-12T21:09:51.8663228+08:00||;True|2026-01-11T21:25:07.5052845+08:00||;False|2026-01-11T21:24:27.5744557+08:00||;True|2026-01-11T19:59:15.4734611+08:00||;False|2026-01-11T19:59:04.9543339+08:00||;True|2026-01-11T18:51:30.6649269+08:00||;True|2026-01-08T21:07:57.5094466+08:00||;True|2026-01-08T14:51:18.2266231+08:00||;True|2026-01-08T14:31:55.1137120+08:00||;True|2026-01-08T00:16:24.4451490+08:00||;True|2026-01-08T00:14:20.7430793+08:00||;True|2026-01-08T00:07:46.7228194+08:00||;True|2026-01-07T23:52:13.3290082+08:00||;True|2026-01-07T23:49:28.4838650+08:00||;True|2026-01-07T23:47:45.1936189+08:00||;True|2026-01-07T23:35:09.7818611+08:00||;True|2026-01-07T23:20:43.7462863+08:00||;True|2026-01-07T23:04:39.5140429+08:00||;False|2026-01-07T23:04:36.5367611+08:00||;True|2026-01-07T22:53:14.6013449+08:00||;True|2026-01-07T22:49:59.9549006+08:00||;True|2026-01-07T22:36:40.0254856+08:00||;</History>
|
<History>True|2026-01-23T14:14:26.8066324Z||;True|2026-01-23T13:36:48.4086406+08:00||;True|2026-01-23T13:30:27.2924204+08:00||;True|2026-01-23T13:02:53.3219368+08:00||;True|2026-01-23T13:01:54.3466638+08:00||;True|2026-01-23T13:01:28.8560809+08:00||;True|2026-01-22T23:18:32.0400436+08:00||;True|2026-01-22T22:29:29.5746209+08:00||;True|2026-01-22T21:32:21.7284081+08:00||;True|2026-01-22T21:20:26.5985955+08:00||;False|2026-01-22T21:20:21.1372539+08:00||;True|2026-01-22T21:11:18.3771739+08:00||;True|2026-01-22T20:58:55.9862778+08:00||;True|2026-01-22T20:51:48.6699461+08:00||;False|2026-01-22T20:51:42.2079210+08:00||;True|2026-01-22T20:50:34.7280114+08:00||;True|2026-01-22T20:50:11.1588492+08:00||;True|2026-01-22T16:11:14.0626037+08:00||;True|2026-01-22T15:53:16.6377347+08:00||;True|2026-01-22T15:45:34.0935091+08:00||;True|2026-01-22T12:44:28.1577014+08:00||;True|2026-01-22T12:40:45.7449335+08:00||;True|2026-01-22T12:39:07.0683214+08:00||;True|2026-01-22T09:55:49.7086190+08:00||;True|2026-01-22T01:37:53.6972395+08:00||;True|2026-01-22T01:34:14.2142463+08:00||;True|2026-01-22T01:32:50.9228911+08:00||;True|2026-01-22T01:29:43.8871986+08:00||;True|2026-01-22T01:29:40.7838709+08:00||;True|2026-01-22T01:27:34.4763970+08:00||;True|2026-01-22T01:26:55.0117367+08:00||;True|2026-01-22T01:23:19.4789587+08:00||;True|2026-01-19T10:19:44.8997385+08:00||;True|2026-01-19T10:11:10.2305307+08:00||;True|2026-01-17T00:52:08.8180346+08:00||;False|2026-01-17T00:52:03.1829000+08:00||;True|2026-01-17T00:45:04.0498090+08:00||;True|2026-01-16T21:00:57.7239379+08:00||;True|2026-01-16T21:00:03.3912989+08:00||;True|2026-01-16T20:56:08.5505592+08:00||;True|2026-01-16T20:46:32.3067302+08:00||;True|2026-01-15T22:18:57.9835738+08:00||;True|2026-01-15T22:07:25.4753938+08:00||;True|2026-01-15T22:07:14.8243754+08:00||;True|2026-01-15T21:40:13.2613927+08:00||;True|2026-01-15T20:57:56.6291682+08:00||;True|2026-01-15T20:57:47.1363536+08:00||;True|2026-01-15T20:08:44.4710883+08:00||;True|2026-01-15T20:04:51.8284314+08:00||;False|2026-01-15T20:04:45.3258155+08:00||;True|2026-01-15T19:59:11.7907672+08:00||;True|2026-01-15T01:10:48.9066941+08:00||;True|2026-01-15T01:03:23.6216975+08:00||;True|2026-01-15T01:03:16.3364591+08:00||;False|2026-01-15T01:03:10.5654436+08:00||;True|2026-01-15T00:49:21.6559622+08:00||;True|2026-01-15T00:10:42.7288439+08:00||;True|2026-01-15T00:06:28.4241682+08:00||;True|2026-01-13T22:34:15.2372411+08:00||;True|2026-01-13T22:26:46.4522947+08:00||;True|2026-01-13T22:15:56.9735179+08:00||;True|2026-01-13T22:15:51.8250677+08:00||;False|2026-01-13T22:15:46.6608690+08:00||;True|2026-01-13T22:03:06.4683237+08:00||;False|2026-01-13T22:03:01.2036027+08:00||;True|2026-01-13T21:36:05.8776209+08:00||;True|2026-01-13T21:33:02.0766289+08:00||;False|2026-01-13T21:32:57.1976141+08:00||;True|2026-01-13T19:14:35.2519439+08:00||;True|2026-01-13T15:07:50.0836745+08:00||;False|2026-01-13T15:06:35.5929685+08:00||;True|2026-01-13T10:21:41.6012776+08:00||;True|2026-01-13T09:57:25.4788847+08:00||;True|2026-01-13T09:53:14.4900360+08:00||;True|2026-01-13T09:23:53.6465295+08:00||;True|2026-01-12T22:04:14.5886955+08:00||;False|2026-01-12T22:04:08.2008101+08:00||;True|2026-01-12T21:53:46.9947176+08:00||;True|2026-01-12T21:11:15.8358024+08:00||;True|2026-01-12T21:09:51.8663228+08:00||;True|2026-01-11T21:25:07.5052845+08:00||;False|2026-01-11T21:24:27.5744557+08:00||;True|2026-01-11T19:59:15.4734611+08:00||;False|2026-01-11T19:59:04.9543339+08:00||;True|2026-01-11T18:51:30.6649269+08:00||;True|2026-01-08T21:07:57.5094466+08:00||;True|2026-01-08T14:51:18.2266231+08:00||;True|2026-01-08T14:31:55.1137120+08:00||;True|2026-01-08T00:16:24.4451490+08:00||;True|2026-01-08T00:14:20.7430793+08:00||;True|2026-01-08T00:07:46.7228194+08:00||;True|2026-01-07T23:52:13.3290082+08:00||;True|2026-01-07T23:49:28.4838650+08:00||;True|2026-01-07T23:47:45.1936189+08:00||;True|2026-01-07T23:35:09.7818611+08:00||;True|2026-01-07T23:20:43.7462863+08:00||;True|2026-01-07T23:04:39.5140429+08:00||;False|2026-01-07T23:04:36.5367611+08:00||;True|2026-01-07T22:53:14.6013449+08:00||;True|2026-01-07T22:49:59.9549006+08:00||;</History>
|
||||||
<LastFailureDetails />
|
<LastFailureDetails />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -73,6 +73,7 @@
|
|||||||
<PackageReference Include="Serilog.Sinks.Async" Version="1.4.0" />
|
<PackageReference Include="Serilog.Sinks.Async" Version="1.4.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
|
||||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
<PackageReference Include="Serilog" Version="3.1.1" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Seq" Version="4.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
|
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ActiveDebugProfile>dy.net</ActiveDebugProfile>
|
<ActiveDebugProfile>dy.net</ActiveDebugProfile>
|
||||||
<NameOfLastUsedPublishProfile>E:\code\dysync\Properties\PublishProfiles\fn.pubxml</NameOfLastUsedPublishProfile>
|
<NameOfLastUsedPublishProfile>E:\code\dysync\Properties\PublishProfiles\docker.pubxml</NameOfLastUsedPublishProfile>
|
||||||
<Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
|
<Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
|
||||||
<Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath>
|
<Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
using dy.net.model.dto;
|
using dy.net.model.dto;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace dy.net.extension
|
namespace dy.net.extension
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace dy.net.extension
|
|||||||
|
|
||||||
public static VideoTypeEnum? ToVideoTypeEnum(this string value)
|
public static VideoTypeEnum? ToVideoTypeEnum(this string value)
|
||||||
{
|
{
|
||||||
if(int.TryParse(value, out int intValue))
|
if (int.TryParse(value, out int intValue))
|
||||||
{
|
{
|
||||||
return ToVideoTypeEnum(intValue);
|
return ToVideoTypeEnum(intValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
using dy.net.job;
|
using dy.net.service;
|
||||||
using dy.net.service;
|
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
|
||||||
using Microsoft.AspNetCore.ResponseCompression;
|
using Microsoft.AspNetCore.ResponseCompression;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
//using Microsoft.OpenApi.Models;
|
//using Microsoft.OpenApi.Models;
|
||||||
@@ -19,7 +15,6 @@ using SqlSugar;
|
|||||||
//using Swashbuckle.AspNetCore.SwaggerGen;
|
//using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
//using Swashbuckle.AspNetCore.SwaggerUI;
|
//using Swashbuckle.AspNetCore.SwaggerUI;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Security;
|
using System.Net.Security;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -62,12 +57,12 @@ namespace dy.net.extension
|
|||||||
// return connectionString;
|
// return connectionString;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
private static string CreateSqliteDBConn(string dbPath="")
|
private static string CreateSqliteDBConn(string dbPath = "")
|
||||||
{
|
{
|
||||||
string fileFloder= Path.Combine(Environment.CurrentDirectory, "db");
|
string fileFloder = Path.Combine(Environment.CurrentDirectory, "db");
|
||||||
if (!string.IsNullOrEmpty(dbPath))
|
if (!string.IsNullOrEmpty(dbPath))
|
||||||
{
|
{
|
||||||
fileFloder= Path.Combine(dbPath, "db");
|
fileFloder = Path.Combine(dbPath, "db");
|
||||||
FnDataFolder = Path.Combine(dbPath, "mp3");
|
FnDataFolder = Path.Combine(dbPath, "mp3");
|
||||||
if ((!Directory.Exists(FnDataFolder)))
|
if ((!Directory.Exists(FnDataFolder)))
|
||||||
{
|
{
|
||||||
@@ -78,8 +73,8 @@ namespace dy.net.extension
|
|||||||
{
|
{
|
||||||
if (Appsettings.Get("deploy") == "fn")
|
if (Appsettings.Get("deploy") == "fn")
|
||||||
{
|
{
|
||||||
Log.Error($"fn--dbpath,未正常获取到,请进Q群联系作者 759876963");
|
Log.Error($"fn--dbpath,未正常获取到,请进Q群联系作者 759876963");
|
||||||
throw new Exception("fn--dbpath,未正常获取到,请进Q群联系作者 759876963");
|
throw new Exception("fn--dbpath,未正常获取到,请进Q群联系作者 759876963");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,14 +131,14 @@ namespace dy.net.extension
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddSqlsugar(this IServiceCollection services,string dbpath)
|
public static void AddSqlsugar(this IServiceCollection services, string dbpath)
|
||||||
{
|
{
|
||||||
//DbType dbtype = GetDBType(configuration);
|
//DbType dbtype = GetDBType(configuration);
|
||||||
services.AddScoped<ISqlSugarClient>(db =>
|
services.AddScoped<ISqlSugarClient>(db =>
|
||||||
{
|
{
|
||||||
var sqlSugar = new SqlSugarClient(new ConnectionConfig
|
var sqlSugar = new SqlSugarClient(new ConnectionConfig
|
||||||
{
|
{
|
||||||
ConnectionString = CreateSqliteDBConn( dbpath),
|
ConnectionString = CreateSqliteDBConn(dbpath),
|
||||||
InitKeyType = InitKeyType.Attribute,
|
InitKeyType = InitKeyType.Attribute,
|
||||||
DbType = DbType.Sqlite,
|
DbType = DbType.Sqlite,
|
||||||
IsAutoCloseConnection = true // close connection after each operation (recommended)
|
IsAutoCloseConnection = true // close connection after each operation (recommended)
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
using dy.net.model.dto;
|
|
||||||
using dy.net.service;
|
|
||||||
using Quartz;
|
|
||||||
using Serilog;
|
|
||||||
using static Quartz.Logging.OperationName;
|
|
||||||
|
|
||||||
namespace dy.net.job
|
|
||||||
{
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
///// 抖音任务依赖监听器(独立公共类)
|
|
||||||
///// 作用:监听任务执行完成事件,触发下一个依赖任务,实现顺序执行
|
|
||||||
///// </summary>
|
|
||||||
// public class DouyinJobDependencyListener : IJobListener
|
|
||||||
// {
|
|
||||||
// // 监听器名称(唯一标识,不可重复)
|
|
||||||
// public string Name => "DouyinJobDependencyListener";
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 任务配置字典(从外部注入)
|
|
||||||
// /// </summary>
|
|
||||||
// private readonly Dictionary<string, JobConfig> _jobConfigs;
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 任务依赖关系(从外部注入,定义执行顺序)
|
|
||||||
// /// </summary>
|
|
||||||
// private readonly Dictionary<string, string> _jobDependency;
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 任务服务(用于触发下一个任务,从外部注入)
|
|
||||||
// /// </summary>
|
|
||||||
// private readonly DouyinQuartzJobService _jobService;
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 构造函数(依赖注入)
|
|
||||||
// /// </summary>
|
|
||||||
// /// <param name="jobConfigs">任务配置</param>
|
|
||||||
// /// <param name="jobDependency">任务依赖关系</param>
|
|
||||||
// /// <param name="jobService">任务服务</param>
|
|
||||||
// public DouyinJobDependencyListener(
|
|
||||||
// Dictionary<string, JobConfig> jobConfigs,
|
|
||||||
// Dictionary<string, string> jobDependency,
|
|
||||||
// DouyinQuartzJobService jobService)
|
|
||||||
// {
|
|
||||||
// _jobConfigs = jobConfigs ?? throw new ArgumentNullException(nameof(jobConfigs), "任务配置不能为空");
|
|
||||||
// _jobDependency = jobDependency ?? throw new ArgumentNullException(nameof(jobDependency), "任务依赖关系不能为空");
|
|
||||||
// _jobService = jobService ?? throw new ArgumentNullException(nameof(jobService), "任务服务不能为空");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 任务执行前触发(无需处理)
|
|
||||||
// /// </summary>
|
|
||||||
// public Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken = default)
|
|
||||||
// {
|
|
||||||
// return Task.CompletedTask;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 任务被否决执行时触发(无需处理)
|
|
||||||
// /// </summary>
|
|
||||||
// public Task JobExecutionVetoed(IJobExecutionContext context, CancellationToken cancellationToken = default)
|
|
||||||
// {
|
|
||||||
// return Task.CompletedTask;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 任务执行完成后触发(核心逻辑:触发下一个依赖任务)
|
|
||||||
// /// </summary>
|
|
||||||
// public async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException? jobException, CancellationToken cancellationToken = default)
|
|
||||||
// {
|
|
||||||
// var currentJobKey = context.JobDetail.Key;
|
|
||||||
// Log.Information("【任务监听】任务执行完成 - 任务名称: {JobName}, 执行状态: {Status}",
|
|
||||||
// currentJobKey.Name, jobException == null ? "成功" : "失败");
|
|
||||||
|
|
||||||
// // 1. 若当前任务执行失败,终止后续依赖任务(避免无效执行)
|
|
||||||
// if (jobException != null)
|
|
||||||
// {
|
|
||||||
// Log.Error(jobException, "【任务监听】任务 {JobName} 执行失败,终止后续任务链条", currentJobKey.Name);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 2. 根据当前任务的 JobKey,找到对应的配置 Key(如:dy.job.key.collect → collect)
|
|
||||||
// var currentConfigKey = _jobConfigs.FirstOrDefault(kv => kv.Value.JobKey == currentJobKey.Name).Key;
|
|
||||||
// if (string.IsNullOrEmpty(currentConfigKey))
|
|
||||||
// {
|
|
||||||
// Log.Warning("【任务监听】未找到任务 {JobName} 的配置信息,任务链条终止", currentJobKey.Name);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 3. 查找下一个依赖任务的配置 Key
|
|
||||||
// if (!_jobDependency.TryGetValue(currentConfigKey, out var nextConfigKey) || string.IsNullOrEmpty(nextConfigKey))
|
|
||||||
// {
|
|
||||||
// Log.Information("【任务监听】任务 {JobName} 是最后一个任务,本次任务链条执行完毕", currentJobKey.Name);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 4. 触发下一个任务(标记为「依赖触发」,立即执行)
|
|
||||||
// Log.Information("【任务监听】准备触发下一个任务: {NextJobName}(依赖触发)", nextConfigKey);
|
|
||||||
// var triggerSuccess = await _jobService.StartJobAsync(nextConfigKey, "", isDependencyTrigger: true);
|
|
||||||
|
|
||||||
// if (triggerSuccess)
|
|
||||||
// {
|
|
||||||
// Log.Information("【任务监听】下一个任务 {NextJobName} 触发成功", nextConfigKey);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// Log.Error("【任务监听】下一个任务 {NextJobName} 触发失败,任务链条中断", nextConfigKey);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,6 @@ using dy.net.model.entity;
|
|||||||
using dy.net.model.response;
|
using dy.net.model.response;
|
||||||
using dy.net.service;
|
using dy.net.service;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using Serilog;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace dy.net.job
|
namespace dy.net.job
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ namespace dy.net.job
|
|||||||
|
|
||||||
protected override async Task<List<DouyinCookie>> GetSyncCookies()
|
protected override async Task<List<DouyinCookie>> GetSyncCookies()
|
||||||
{
|
{
|
||||||
return await douyinCookieService.GetOpendCookiesAsync(x=> !string.IsNullOrWhiteSpace(x.FavSavePath)&&!string.IsNullOrWhiteSpace(x.SecUserId));
|
return await douyinCookieService.GetOpendCookiesAsync(x => !string.IsNullOrWhiteSpace(x.FavSavePath) && !string.IsNullOrWhiteSpace(x.SecUserId));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<DouyinVideoInfoResponse> FetchVideoData(DouyinCookie cookie, string cursor,DouyinFollowed followed, DouyinCollectCate cate)
|
protected override async Task<DouyinVideoInfoResponse> FetchVideoData(DouyinCookie cookie, string cursor, DouyinFollowed followed, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
return await douyinHttpClientService.SyncFavoriteVideos(count, cursor, cookie.SecUserId, cookie.Cookies);
|
return await douyinHttpClientService.SyncFavoriteVideos(count, cursor, cookie.SecUserId, cookie.Cookies);
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ namespace dy.net.job
|
|||||||
// await base.HandleSyncCompletion(cookie, syncCount, followed, cate);
|
// await base.HandleSyncCompletion(cookie, syncCount, followed, cate);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
protected override string CreateSaveFolder(DouyinCookie cookie, Aweme item, AppConfig config, DouyinFollowed followed,DouyinCollectCate cate)
|
protected override string CreateSaveFolder(DouyinCookie cookie, Aweme item, AppConfig config, DouyinFollowed followed, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
string authorFolder;
|
string authorFolder;
|
||||||
if (string.IsNullOrWhiteSpace(item.Author?.Nickname) && string.IsNullOrWhiteSpace(item.Author?.Uid))
|
if (string.IsNullOrWhiteSpace(item.Author?.Nickname) && string.IsNullOrWhiteSpace(item.Author?.Uid))
|
||||||
|
|||||||
+35
-47
@@ -211,7 +211,7 @@ namespace dy.net.job
|
|||||||
/// <param name="cate"></param>
|
/// <param name="cate"></param>
|
||||||
/// <param name="config">应用配置</param>
|
/// <param name="config">应用配置</param>
|
||||||
/// <returns>创建的视频保存文件夹路径</returns>
|
/// <returns>创建的视频保存文件夹路径</returns>
|
||||||
protected virtual string CreateSaveFolder(DouyinCookie cookie, Aweme item, AppConfig config, DouyinFollowed followed,DouyinCollectCate cate)
|
protected virtual string CreateSaveFolder(DouyinCookie cookie, Aweme item, AppConfig config, DouyinFollowed followed, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
var folder = Path.Combine(cookie.SavePath, DouyinFileNameHelper.SanitizeLinuxFileName(item.Desc, item.AwemeId, true));
|
var folder = Path.Combine(cookie.SavePath, DouyinFileNameHelper.SanitizeLinuxFileName(item.Desc, item.AwemeId, true));
|
||||||
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
|
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
|
||||||
@@ -260,7 +260,7 @@ namespace dy.net.job
|
|||||||
/// <param name="followed"></param>
|
/// <param name="followed"></param>
|
||||||
/// <param name="cate"></param>
|
/// <param name="cate"></param>
|
||||||
/// <returns>一个表示异步操作的任务</returns>
|
/// <returns>一个表示异步操作的任务</returns>
|
||||||
protected async Task HandleSyncCompletion(DouyinCookie cookie, int syncCount, DouyinFollowed followed = null,DouyinCollectCate cate=null)
|
protected async Task HandleSyncCompletion(DouyinCookie cookie, int syncCount, DouyinFollowed followed = null, DouyinCollectCate cate = null)
|
||||||
{
|
{
|
||||||
var tag = cate?.Name ?? followed?.UperName ?? string.Empty;
|
var tag = cate?.Name ?? followed?.UperName ?? string.Empty;
|
||||||
tag = !string.IsNullOrWhiteSpace(tag) ? $"-[{tag}]" : tag;
|
tag = !string.IsNullOrWhiteSpace(tag) ? $"-[{tag}]" : tag;
|
||||||
@@ -388,7 +388,7 @@ namespace dy.net.job
|
|||||||
{
|
{
|
||||||
// 获取视频数据
|
// 获取视频数据
|
||||||
var data = await FetchVideoData(cookie, cursor, followed, cate);
|
var data = await FetchVideoData(cookie, cursor, followed, cate);
|
||||||
if (data == null|| data.AwemeList == null || !data.AwemeList.Any())
|
if (data == null || data.AwemeList == null || !data.AwemeList.Any())
|
||||||
{
|
{
|
||||||
Serilog.Log.Debug($"[{VideoType.GetDesc()}][{cookie.UserName}] 没有新的视频");
|
Serilog.Log.Debug($"[{VideoType.GetDesc()}][{cookie.UserName}] 没有新的视频");
|
||||||
break;
|
break;
|
||||||
@@ -402,8 +402,8 @@ namespace dy.net.job
|
|||||||
hasMore = data.HasMore == 1;
|
hasMore = data.HasMore == 1;
|
||||||
|
|
||||||
// 处理视频列表
|
// 处理视频列表
|
||||||
(List<DouyinVideo> videos,int syncCountx) = await ProcessVideoList(syncCount,cookie, data, config, followed, cate);
|
(List<DouyinVideo> videos, int syncCountx) = await ProcessVideoList(syncCount, cookie, data, config, followed, cate);
|
||||||
if(videos != null && videos.Any())
|
if (videos != null && videos.Any())
|
||||||
{
|
{
|
||||||
// 保存视频信息到数据库
|
// 保存视频信息到数据库
|
||||||
await SaveVideos(videos);
|
await SaveVideos(videos);
|
||||||
@@ -411,7 +411,7 @@ namespace dy.net.job
|
|||||||
|
|
||||||
syncCount += syncCountx;
|
syncCount += syncCountx;
|
||||||
|
|
||||||
if (IsSyncLimitReached(cookie, config, syncCount,cate,followed))
|
if (IsSyncLimitReached(cookie, config, syncCount, cate, followed))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -432,9 +432,9 @@ namespace dy.net.job
|
|||||||
/// <param name="cate"></param>
|
/// <param name="cate"></param>
|
||||||
/// <param name="followed"></param>
|
/// <param name="followed"></param>
|
||||||
/// <returns>是否需要终止循环</returns>
|
/// <returns>是否需要终止循环</returns>
|
||||||
private bool IsSyncLimitReached(DouyinCookie cookie, AppConfig config, int syncCount,DouyinCollectCate cate,DouyinFollowed followed)
|
private bool IsSyncLimitReached(DouyinCookie cookie, AppConfig config, int syncCount, DouyinCollectCate cate, DouyinFollowed followed)
|
||||||
{
|
{
|
||||||
if(cate!=null && cate.CateType != VideoTypeEnum.dy_custom_collect)
|
if (cate != null && cate.CateType != VideoTypeEnum.dy_custom_collect)
|
||||||
{
|
{
|
||||||
if (syncCount >= 15)
|
if (syncCount >= 15)
|
||||||
{
|
{
|
||||||
@@ -481,7 +481,7 @@ namespace dy.net.job
|
|||||||
/// <param name="followed">关注的</param>
|
/// <param name="followed">关注的</param>
|
||||||
/// <param name="cate">收藏夹、合集、短剧</param>
|
/// <param name="cate">收藏夹、合集、短剧</param>
|
||||||
/// <returns>处理后的视频实体列表</returns>
|
/// <returns>处理后的视频实体列表</returns>
|
||||||
protected async Task<(List<DouyinVideo> videos,int currentCount)> ProcessVideoList(int syncCount1,DouyinCookie cookie, DouyinVideoInfoResponse data, AppConfig config, DouyinFollowed followed = null, DouyinCollectCate cate = null)
|
protected async Task<(List<DouyinVideo> videos, int currentCount)> ProcessVideoList(int syncCount1, DouyinCookie cookie, DouyinVideoInfoResponse data, AppConfig config, DouyinFollowed followed = null, DouyinCollectCate cate = null)
|
||||||
{
|
{
|
||||||
int syncCount = 0;
|
int syncCount = 0;
|
||||||
var videos = new List<DouyinVideo>();
|
var videos = new List<DouyinVideo>();
|
||||||
@@ -533,15 +533,15 @@ namespace dy.net.job
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 处理单个视频
|
// 处理单个视频
|
||||||
var video = await ProcessSingleVideo(cookie, item, data, config, followed,cate);
|
var video = await ProcessSingleVideo(cookie, item, data, config, followed, cate);
|
||||||
if (video != null)
|
if (video != null)
|
||||||
{
|
{
|
||||||
videos.Add(video);
|
videos.Add(video);
|
||||||
syncCount++;
|
syncCount++;
|
||||||
|
|
||||||
if (syncCount+ syncCount1 >= config.BatchCount)
|
if (syncCount + syncCount1 >= config.BatchCount)
|
||||||
{
|
{
|
||||||
return (videos,syncCount);
|
return (videos, syncCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -579,7 +579,7 @@ namespace dy.net.job
|
|||||||
if (dynamicVideoUrls.Count > 0)
|
if (dynamicVideoUrls.Count > 0)
|
||||||
{
|
{
|
||||||
// 处理动态视频
|
// 处理动态视频
|
||||||
var dynamicVideo = await ProcessDynamicVideo(dynamicVideoUrls, cookie, item, config,followed,cate);
|
var dynamicVideo = await ProcessDynamicVideo(dynamicVideoUrls, cookie, item, config, followed, cate);
|
||||||
if (dynamicVideo != null)
|
if (dynamicVideo != null)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(dynamicVideo.DynamicVideos))
|
if (!string.IsNullOrEmpty(dynamicVideo.DynamicVideos))
|
||||||
@@ -620,7 +620,7 @@ namespace dy.net.job
|
|||||||
}
|
}
|
||||||
videos.Add(dynamicVideo);
|
videos.Add(dynamicVideo);
|
||||||
syncCount++;
|
syncCount++;
|
||||||
if (syncCount+ syncCount1 >= config.BatchCount)
|
if (syncCount + syncCount1 >= config.BatchCount)
|
||||||
{
|
{
|
||||||
return (videos, syncCount);
|
return (videos, syncCount);
|
||||||
}
|
}
|
||||||
@@ -640,7 +640,7 @@ namespace dy.net.job
|
|||||||
{
|
{
|
||||||
videos.Add(mergevideo);
|
videos.Add(mergevideo);
|
||||||
syncCount++;
|
syncCount++;
|
||||||
if (syncCount+ syncCount1 >= config.BatchCount)
|
if (syncCount + syncCount1 >= config.BatchCount)
|
||||||
{
|
{
|
||||||
return (videos, syncCount);
|
return (videos, syncCount);
|
||||||
}
|
}
|
||||||
@@ -814,8 +814,6 @@ namespace dy.net.job
|
|||||||
var videoUrl = v.PlayAddr.UrlList.Where(x => !string.IsNullOrEmpty(x))?.FirstOrDefault();
|
var videoUrl = v.PlayAddr.UrlList.Where(x => !string.IsNullOrEmpty(x))?.FirstOrDefault();
|
||||||
if (string.IsNullOrWhiteSpace(videoUrl)) return null;
|
if (string.IsNullOrWhiteSpace(videoUrl)) return null;
|
||||||
|
|
||||||
// 获取视频标签
|
|
||||||
var (tag1, tag2, tag3) = GetVideoTags(item);
|
|
||||||
// 创建保存文件夹
|
// 创建保存文件夹
|
||||||
var saveFolder = CreateSaveFolder(cookie, item, config, followed, cate);
|
var saveFolder = CreateSaveFolder(cookie, item, config, followed, cate);
|
||||||
// 获取视频文件名
|
// 获取视频文件名
|
||||||
@@ -851,12 +849,12 @@ namespace dy.net.job
|
|||||||
Log.Debug($"[{VideoType.GetDesc()}][{item?.Author?.Nickname ?? ""}]-视频[{DouyinFileNameHelper.SanitizeLinuxFileName(item.Desc, item.AwemeId)}]下载完成.");
|
Log.Debug($"[{VideoType.GetDesc()}][{item?.Author?.Nickname ?? ""}]-视频[{DouyinFileNameHelper.SanitizeLinuxFileName(item.Desc, item.AwemeId)}]下载完成.");
|
||||||
}
|
}
|
||||||
// 下载视频封面
|
// 下载视频封面
|
||||||
await GetDownVideoCover(item, saveFolder, cookie, config,cate);
|
await GetDownVideoCover(item, saveFolder, cookie, config, cate);
|
||||||
// 下载作者头像
|
// 下载作者头像
|
||||||
var (avatarSavePath, avatarUrl) = await DownAuthorAvatar(cookie, item);
|
var (avatarSavePath, avatarUrl) = await DownAuthorAvatar(cookie, item);
|
||||||
|
|
||||||
// 创建视频实体
|
// 创建视频实体
|
||||||
return await CreateVideoEntity(config, cookie, item, v, savePath, saveFolder, tag1, tag2, tag3, avatarUrl, avatarSavePath, null, cate);
|
return await CreateVideoEntity(config, cookie, item, v, savePath, saveFolder, avatarSavePath, null, cate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -869,12 +867,8 @@ namespace dy.net.job
|
|||||||
/// <param name="followed"></param>
|
/// <param name="followed"></param>
|
||||||
/// <param name="cate"></param>
|
/// <param name="cate"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected async Task<DouyinVideo> ProcessDynamicVideo(List<DouyinDynamicVideoDto> dynamicUrls, DouyinCookie cookie, Aweme item, AppConfig config, DouyinFollowed followed = null,DouyinCollectCate cate=null)
|
protected async Task<DouyinVideo> ProcessDynamicVideo(List<DouyinDynamicVideoDto> dynamicUrls, DouyinCookie cookie, Aweme item, AppConfig config, DouyinFollowed followed = null, DouyinCollectCate cate = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
// 获取视频标签
|
|
||||||
var (tag1, tag2, tag3) = GetVideoTags(item);
|
|
||||||
// 创建保存文件夹
|
// 创建保存文件夹
|
||||||
var saveFolder = CreateSaveFolder(cookie, item, config, followed, cate);
|
var saveFolder = CreateSaveFolder(cookie, item, config, followed, cate);
|
||||||
// 获取视频文件名
|
// 获取视频文件名
|
||||||
@@ -932,7 +926,7 @@ namespace dy.net.job
|
|||||||
DataSize = DouyinFileUtils.GetTotalFileSize(dynamicSavePaths.Select(x => x.Path).ToList()) // 合成视频的文件大小
|
DataSize = DouyinFileUtils.GetTotalFileSize(dynamicSavePaths.Select(x => x.Path).ToList()) // 合成视频的文件大小
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return await CreateVideoEntity(config, cookie, item, virtualBitRate, dynamicSavePaths.FirstOrDefault()?.Path, saveFolder, tag1, tag2, tag3, avatarUrl, avatarSavePath, dynamicSavePaths,cate);
|
return await CreateVideoEntity(config, cookie, item, virtualBitRate, dynamicSavePaths.FirstOrDefault()?.Path, saveFolder, avatarSavePath, dynamicSavePaths, cate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1003,7 +997,7 @@ namespace dy.net.job
|
|||||||
/// <param name="followed">应用配置</param>
|
/// <param name="followed">应用配置</param>
|
||||||
/// <param name="cate"></param>
|
/// <param name="cate"></param>
|
||||||
/// <returns>合成后的视频实体,如果处理失败则为null</returns>
|
/// <returns>合成后的视频实体,如果处理失败则为null</returns>
|
||||||
protected async Task<DouyinVideo> ProcessImageSetAndMergeToVideo(DouyinCookie cookie, Aweme item, AppConfig config, DouyinFollowed followed,DouyinCollectCate cate)
|
protected async Task<DouyinVideo> ProcessImageSetAndMergeToVideo(DouyinCookie cookie, Aweme item, AppConfig config, DouyinFollowed followed, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1027,7 +1021,7 @@ namespace dy.net.job
|
|||||||
|
|
||||||
if (!Directory.Exists(fileNamefolder)) Directory.CreateDirectory(fileNamefolder);
|
if (!Directory.Exists(fileNamefolder)) Directory.CreateDirectory(fileNamefolder);
|
||||||
|
|
||||||
var fileName = GetVideoFileName(cookie, item, config,cate);
|
var fileName = GetVideoFileName(cookie, item, config, cate);
|
||||||
// 合成视频的保存路径
|
// 合成视频的保存路径
|
||||||
var savePath = Path.Combine(fileNamefolder, fileName);
|
var savePath = Path.Combine(fileNamefolder, fileName);
|
||||||
|
|
||||||
@@ -1090,16 +1084,14 @@ namespace dy.net.job
|
|||||||
}
|
}
|
||||||
|
|
||||||
var coverUrl = cate is not null && cate.CateType != VideoTypeEnum.dy_custom_collect
|
var coverUrl = cate is not null && cate.CateType != VideoTypeEnum.dy_custom_collect
|
||||||
? item.Music?.CoverHd?.UrlList?.FirstOrDefault() ?? imageUrls.FirstOrDefault()
|
? (item.MixInfo?.CoverUrl?.UrlList?.FirstOrDefault() ?? imageUrls.FirstOrDefault() ?? item.Music?.CoverHd?.UrlList?.FirstOrDefault())
|
||||||
: imageUrls.FirstOrDefault();
|
: imageUrls.FirstOrDefault();
|
||||||
// 下载视频封面(使用第一张图片作为封面)
|
// 下载视频封面(使用第一张图片作为封面)
|
||||||
if(!string.IsNullOrWhiteSpace(coverUrl))
|
if (!string.IsNullOrWhiteSpace(coverUrl))
|
||||||
await DownVideoCover(coverUrl, fileNamefolder, cookie, item, config,cate);
|
await DownVideoCover(coverUrl, fileNamefolder, cookie, item, config, cate);
|
||||||
// 下载作者头像
|
// 下载作者头像
|
||||||
var (avatarSavePath, avatarUrl) = await DownAuthorAvatar(cookie, item);
|
var (avatarSavePath, avatarUrl) = await DownAuthorAvatar(cookie, item);
|
||||||
|
|
||||||
// 获取视频标签
|
|
||||||
var (tag1, tag2, tag3) = GetVideoTags(item);
|
|
||||||
// 为合成的视频创建一个“虚拟”的BitRate对象,以便复用CreateVideoEntity方法
|
// 为合成的视频创建一个“虚拟”的BitRate对象,以便复用CreateVideoEntity方法
|
||||||
var virtualBitRate = new VideoBitRate
|
var virtualBitRate = new VideoBitRate
|
||||||
{
|
{
|
||||||
@@ -1113,8 +1105,7 @@ namespace dy.net.job
|
|||||||
|
|
||||||
// 创建视频实体
|
// 创建视频实体
|
||||||
var videoEntity = await CreateVideoEntity(config,
|
var videoEntity = await CreateVideoEntity(config,
|
||||||
cookie, item, virtualBitRate, savePath, fileNamefolder,
|
cookie, item, virtualBitRate, savePath, fileNamefolder, avatarSavePath, null, cate);
|
||||||
tag1, tag2, tag3, avatarUrl,avatarSavePath, null,cate);
|
|
||||||
|
|
||||||
// 特殊处理合成视频的字段
|
// 特殊处理合成视频的字段
|
||||||
videoEntity.FileHash = string.Empty; // 合成视频没有原始文件哈希
|
videoEntity.FileHash = string.Empty; // 合成视频没有原始文件哈希
|
||||||
@@ -1164,7 +1155,7 @@ namespace dy.net.job
|
|||||||
/// <param name="config">应用配置</param>
|
/// <param name="config">应用配置</param>
|
||||||
/// <param name="cate"></param>
|
/// <param name="cate"></param>
|
||||||
/// <returns>一个表示异步操作的任务</returns>
|
/// <returns>一个表示异步操作的任务</returns>
|
||||||
protected async Task GetDownVideoCover(Aweme item, string saveFolder, DouyinCookie cookie, AppConfig config,DouyinCollectCate cate)
|
protected async Task GetDownVideoCover(Aweme item, string saveFolder, DouyinCookie cookie, AppConfig config, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
// 定义封面URL变量
|
// 定义封面URL变量
|
||||||
string coverUrl;
|
string coverUrl;
|
||||||
@@ -1174,8 +1165,8 @@ namespace dy.net.job
|
|||||||
{
|
{
|
||||||
// cate不为空时:优先MixInfo封面 → 其次Music高清封面 → 最后Video封面
|
// cate不为空时:优先MixInfo封面 → 其次Music高清封面 → 最后Video封面
|
||||||
coverUrl = item.MixInfo?.CoverUrl?.UrlList?.FirstOrDefault()
|
coverUrl = item.MixInfo?.CoverUrl?.UrlList?.FirstOrDefault()
|
||||||
?? item.Music?.CoverHd?.UrlList?.FirstOrDefault()
|
?? item.Video.Cover.UrlList?.LastOrDefault()
|
||||||
?? item.Video.Cover.UrlList?.FirstOrDefault();
|
?? item.Music?.CoverHd?.UrlList?.FirstOrDefault();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1294,7 +1285,7 @@ namespace dy.net.job
|
|||||||
/// <param name="config">应用配置</param>
|
/// <param name="config">应用配置</param>
|
||||||
/// <param name="cate"></param>
|
/// <param name="cate"></param>
|
||||||
/// <returns>一个表示异步操作的任务</returns>
|
/// <returns>一个表示异步操作的任务</returns>
|
||||||
private async Task DownVideoCover(string coverUrl, string saveFolder, DouyinCookie cookie, Aweme item, AppConfig config,DouyinCollectCate cate)
|
private async Task DownVideoCover(string coverUrl, string saveFolder, DouyinCookie cookie, Aweme item, AppConfig config, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(coverUrl)) return;
|
if (string.IsNullOrWhiteSpace(coverUrl)) return;
|
||||||
// 获取封面图片文件名
|
// 获取封面图片文件名
|
||||||
@@ -1318,18 +1309,15 @@ namespace dy.net.job
|
|||||||
/// <param name="bitRate">视频码率信息</param>
|
/// <param name="bitRate">视频码率信息</param>
|
||||||
/// <param name="savePath">视频保存路径</param>
|
/// <param name="savePath">视频保存路径</param>
|
||||||
/// <param name="saveFolder">视频保存文件夹</param>
|
/// <param name="saveFolder">视频保存文件夹</param>
|
||||||
/// <param name="tag1">视频标签1</param>
|
|
||||||
/// <param name="tag2">视频标签2</param>
|
|
||||||
/// <param name="tag3">视频标签3</param>
|
|
||||||
/// <param name="avatorUrl"></param>
|
|
||||||
/// <param name="avatorPath"></param>
|
/// <param name="avatorPath"></param>
|
||||||
/// <param name="dynamicVideos">动态视频</param>
|
/// <param name="dynamicVideos">动态视频</param>
|
||||||
/// <param name="cate">短剧、合集、自定义收藏夹</param>
|
/// <param name="cate">短剧、合集、自定义收藏夹</param>
|
||||||
/// <returns>创建的视频实体对象</returns>
|
/// <returns>创建的视频实体对象</returns>
|
||||||
private async Task<DouyinVideo> CreateVideoEntity(AppConfig config,
|
private async Task<DouyinVideo> CreateVideoEntity(AppConfig config,
|
||||||
DouyinCookie cookie, Aweme item, VideoBitRate bitRate, string savePath, string saveFolder,
|
DouyinCookie cookie, Aweme item, VideoBitRate bitRate, string savePath, string saveFolder, string avatorPath, List<DouyinDynamicVideoDto> dynamicVideos = null, DouyinCollectCate cate = null)
|
||||||
string tag1, string tag2, string tag3,string avatorUrl,string avatorPath, List<DouyinDynamicVideoDto> dynamicVideos = null,DouyinCollectCate cate=null)
|
|
||||||
{
|
{
|
||||||
|
// 获取视频标签
|
||||||
|
var (tag1, tag2, tag3) = GetVideoTags(item);
|
||||||
var video = new DouyinVideo
|
var video = new DouyinVideo
|
||||||
{
|
{
|
||||||
ViedoType = VideoType,
|
ViedoType = VideoType,
|
||||||
@@ -1356,12 +1344,12 @@ namespace dy.net.job
|
|||||||
DyUserId = item.AuthorUserId == 0 ? item.Author?.Uid : item.AuthorUserId.ToString(),
|
DyUserId = item.AuthorUserId == 0 ? item.Author?.Uid : item.AuthorUserId.ToString(),
|
||||||
CookieId = cookie.Id,
|
CookieId = cookie.Id,
|
||||||
OnlyImgOrOnlyMp3 = string.IsNullOrWhiteSpace(savePath) && !config.DownImageVideo && (config.DownImage || config.DownMp3),
|
OnlyImgOrOnlyMp3 = string.IsNullOrWhiteSpace(savePath) && !config.DownImageVideo && (config.DownImage || config.DownMp3),
|
||||||
CateId= cate?.Id,
|
CateId = cate?.Id,
|
||||||
CateXId= cate?.XId,
|
CateXId = cate?.XId,
|
||||||
};
|
};
|
||||||
if (cate != null && cate.CateType != VideoTypeEnum.dy_custom_collect)
|
if (cate != null && cate.CateType != VideoTypeEnum.dy_custom_collect)
|
||||||
{
|
{
|
||||||
video.VideoTitle = (string.IsNullOrWhiteSpace(item.Desc) ? cate.Name : $"[{cate.Name}]"+"_"+item.Desc) + "_" + item.MixInfo.Statis.CurrentEpisode;
|
video.VideoTitle = (string.IsNullOrWhiteSpace(item.Desc) ? cate.Name : $"[{cate.Name}]" + "_" + item.Desc) + "_" + item.MixInfo.Statis.CurrentEpisode;
|
||||||
}
|
}
|
||||||
if (dynamicVideos != null && dynamicVideos.Count > 0)
|
if (dynamicVideos != null && dynamicVideos.Count > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using dy.net.model.entity;
|
|||||||
using dy.net.model.response;
|
using dy.net.model.response;
|
||||||
using dy.net.service;
|
using dy.net.service;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace dy.net.job
|
namespace dy.net.job
|
||||||
{
|
{
|
||||||
@@ -25,7 +24,7 @@ namespace dy.net.job
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return base.CreateSaveFolder(cookie, item, config,followed,cate);
|
return base.CreateSaveFolder(cookie, item, config, followed, cate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
protected override string GetAuthorAvatarBasePath(DouyinCookie cookie)
|
protected override string GetAuthorAvatarBasePath(DouyinCookie cookie)
|
||||||
@@ -35,7 +34,7 @@ namespace dy.net.job
|
|||||||
|
|
||||||
protected override async Task<DouyinVideoInfoResponse> FetchVideoData(DouyinCookie cookie, string cursor, DouyinFollowed followed, DouyinCollectCate cate)
|
protected override async Task<DouyinVideoInfoResponse> FetchVideoData(DouyinCookie cookie, string cursor, DouyinFollowed followed, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
return await douyinHttpClientService.SyncCollectVideosByCollectId(cursor,count,cookie.Cookies,cate.XId);
|
return await douyinHttpClientService.SyncCollectVideosByCollectId(cursor, count, cookie.Cookies, cate.XId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//protected override bool ShouldContinueSync(DouyinCookie cookie, DouyinVideoInfoResponse data, DouyinFollowed followed = null)
|
//protected override bool ShouldContinueSync(DouyinCookie cookie, DouyinVideoInfoResponse data, DouyinFollowed followed = null)
|
||||||
|
|||||||
@@ -4,10 +4,6 @@ using dy.net.model.entity;
|
|||||||
using dy.net.model.response;
|
using dy.net.model.response;
|
||||||
using dy.net.service;
|
using dy.net.service;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace dy.net.job
|
namespace dy.net.job
|
||||||
{
|
{
|
||||||
@@ -21,10 +17,10 @@ namespace dy.net.job
|
|||||||
|
|
||||||
protected override async Task<List<DouyinCookie>> GetSyncCookies()
|
protected override async Task<List<DouyinCookie>> GetSyncCookies()
|
||||||
{
|
{
|
||||||
return await douyinCookieService.GetOpendCookiesAsync(x => !string.IsNullOrWhiteSpace(x.UpSavePath));
|
return await douyinCookieService.GetOpendCookiesAsync(x => !string.IsNullOrWhiteSpace(x.UpSavePath));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<DouyinVideoInfoResponse> FetchVideoData(DouyinCookie cookie, string cursor, DouyinFollowed followed,DouyinCollectCate cate)
|
protected override async Task<DouyinVideoInfoResponse> FetchVideoData(DouyinCookie cookie, string cursor, DouyinFollowed followed, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
return await douyinHttpClientService.SyncUpderPostVideos(count, cursor, followed.SecUid, cookie.Cookies);
|
return await douyinHttpClientService.SyncUpderPostVideos(count, cursor, followed.SecUid, cookie.Cookies);
|
||||||
}
|
}
|
||||||
@@ -47,7 +43,7 @@ namespace dy.net.job
|
|||||||
/// <param name="cate"></param>
|
/// <param name="cate"></param>
|
||||||
/// <param name="config"></param>
|
/// <param name="config"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected override string CreateSaveFolder(DouyinCookie cookie, Aweme item, AppConfig config, DouyinFollowed followed,DouyinCollectCate cate)
|
protected override string CreateSaveFolder(DouyinCookie cookie, Aweme item, AppConfig config, DouyinFollowed followed, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
#region 默认使用UP主名称作为文件夹名称,若关注列表中有自定义保存路径则使用自定义路径
|
#region 默认使用UP主名称作为文件夹名称,若关注列表中有自定义保存路径则使用自定义路径
|
||||||
// 1. 优先获取有效的作者名称(遵循原有优先级:followed.UperName > item.Author.Nickname > 默认值)
|
// 1. 优先获取有效的作者名称(遵循原有优先级:followed.UperName > item.Author.Nickname > 默认值)
|
||||||
@@ -75,7 +71,7 @@ namespace dy.net.job
|
|||||||
/// <param name="config"></param>
|
/// <param name="config"></param>
|
||||||
/// <param name="cate"></param>
|
/// <param name="cate"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected override string GetVideoFileName(DouyinCookie cookie, Aweme item,AppConfig config,DouyinCollectCate cate)
|
protected override string GetVideoFileName(DouyinCookie cookie, Aweme item, AppConfig config, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
|
|
||||||
string Format = "mp4";
|
string Format = "mp4";
|
||||||
@@ -95,8 +91,9 @@ namespace dy.net.job
|
|||||||
{
|
{
|
||||||
//图片合成视频,参数要自己写。
|
//图片合成视频,参数要自己写。
|
||||||
var image = item.Images?.FirstOrDefault();
|
var image = item.Images?.FirstOrDefault();
|
||||||
if(image != null){
|
if (image != null)
|
||||||
FileHash = IdGener.GetGuid().ToLower().Replace("-","");//使用随机值,避免重复
|
{
|
||||||
|
FileHash = IdGener.GetGuid().ToLower().Replace("-", "");//使用随机值,避免重复
|
||||||
Height = image.Height.ToString();
|
Height = image.Height.ToString();
|
||||||
Width = image.Width.ToString();
|
Width = image.Width.ToString();
|
||||||
}
|
}
|
||||||
@@ -113,24 +110,24 @@ namespace dy.net.job
|
|||||||
//else
|
//else
|
||||||
//{
|
//{
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(config.FullFollowedTitleTemplate))
|
if (!string.IsNullOrWhiteSpace(config.FullFollowedTitleTemplate))
|
||||||
|
{
|
||||||
|
var fullName = VideoTitleGenerator.Generate(config.FullFollowedTitleTemplate, new VideoTitleDataTemplate
|
||||||
{
|
{
|
||||||
var fullName = VideoTitleGenerator.Generate(config.FullFollowedTitleTemplate, new VideoTitleDataTemplate
|
FileHash = FileHash,
|
||||||
{
|
Id = item.AwemeId,
|
||||||
FileHash = FileHash,
|
ReleaseTime = DateTimeUtil.Convert10BitTimestamp(item.CreateTime),
|
||||||
Id = item.AwemeId,
|
Resolution = $"{Width}×{Height}",
|
||||||
ReleaseTime = DateTimeUtil.Convert10BitTimestamp(item.CreateTime),
|
VideoTitle = DouyinFileNameHelper.SanitizeLinuxFileName(item.Desc, item.AwemeId),
|
||||||
Resolution = $"{Width}×{Height}",
|
Author = item.Author.Nickname
|
||||||
VideoTitle = DouyinFileNameHelper.SanitizeLinuxFileName(item.Desc, item.AwemeId),
|
});
|
||||||
Author = item.Author.Nickname
|
|
||||||
});
|
|
||||||
|
|
||||||
fileName= $"{fullName}.{Format}";
|
fileName = $"{fullName}.{Format}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fileName = $"{item.AwemeId}.{Format}";
|
fileName = $"{item.AwemeId}.{Format}";
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
return fileName;
|
return fileName;
|
||||||
|
|
||||||
@@ -146,7 +143,7 @@ namespace dy.net.job
|
|||||||
/// <param name="imageType"></param>
|
/// <param name="imageType"></param>
|
||||||
/// <param name="cate"></param>
|
/// <param name="cate"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected override string GetNfoFileName(DouyinCookie cookie, Aweme item, AppConfig config, string imageType,DouyinCollectCate cate)
|
protected override string GetNfoFileName(DouyinCookie cookie, Aweme item, AppConfig config, string imageType, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
return base.GetNfoFileName(cookie, item, config, imageType, cate);
|
return base.GetNfoFileName(cookie, item, config, imageType, cate);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,6 @@ using dy.net.model.response;
|
|||||||
using dy.net.service;
|
using dy.net.service;
|
||||||
using Quartz;
|
using Quartz;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace dy.net.job
|
namespace dy.net.job
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ namespace dy.net.job
|
|||||||
protected override VideoTypeEnum VideoType => VideoTypeEnum.dy_mix;
|
protected override VideoTypeEnum VideoType => VideoTypeEnum.dy_mix;
|
||||||
|
|
||||||
|
|
||||||
protected override async Task<DouyinVideoInfoResponse> FetchVideoData(DouyinCookie cookie, string cursor,DouyinFollowed followed,DouyinCollectCate cate)
|
protected override async Task<DouyinVideoInfoResponse> FetchVideoData(DouyinCookie cookie, string cursor, DouyinFollowed followed, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
return await douyinHttpClientService.SyncMixViedosByMixId(cursor,count,cookie.Cookies,cate.XId);
|
return await douyinHttpClientService.SyncMixViedosByMixId(cursor, count, cookie.Cookies, cate.XId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//protected override bool ShouldContinueSync(DouyinCookie cookie, DouyinVideoInfoResponse data, DouyinFollowed followed=null)
|
//protected override bool ShouldContinueSync(DouyinCookie cookie, DouyinVideoInfoResponse data, DouyinFollowed followed=null)
|
||||||
@@ -29,7 +29,7 @@ namespace dy.net.job
|
|||||||
{
|
{
|
||||||
if (cate != null)
|
if (cate != null)
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(cookie.MixPath))
|
if (string.IsNullOrWhiteSpace(cookie.MixPath))
|
||||||
{
|
{
|
||||||
var folder = Path.Combine(cookie.SavePath, VideoType.GetDesc(), DouyinFileNameHelper.SanitizeLinuxFileName(cate.SaveFolder, cate.Name, true));
|
var folder = Path.Combine(cookie.SavePath, VideoType.GetDesc(), DouyinFileNameHelper.SanitizeLinuxFileName(cate.SaveFolder, cate.Name, true));
|
||||||
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
|
if (!Directory.Exists(folder)) Directory.CreateDirectory(folder);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using dy.net.model.entity;
|
|||||||
using dy.net.model.response;
|
using dy.net.model.response;
|
||||||
using dy.net.service;
|
using dy.net.service;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace dy.net.job
|
namespace dy.net.job
|
||||||
{
|
{
|
||||||
@@ -16,9 +15,9 @@ namespace dy.net.job
|
|||||||
|
|
||||||
protected override VideoTypeEnum VideoType => VideoTypeEnum.dy_series;
|
protected override VideoTypeEnum VideoType => VideoTypeEnum.dy_series;
|
||||||
|
|
||||||
protected override async Task<DouyinVideoInfoResponse> FetchVideoData(DouyinCookie cookie, string cursor,DouyinFollowed followed, DouyinCollectCate cate)
|
protected override async Task<DouyinVideoInfoResponse> FetchVideoData(DouyinCookie cookie, string cursor, DouyinFollowed followed, DouyinCollectCate cate)
|
||||||
{
|
{
|
||||||
return await douyinHttpClientService.SyncSeriesViedosByMSeriesId(cursor, count, cookie.Cookies,cate.XId);
|
return await douyinHttpClientService.SyncSeriesViedosByMSeriesId(cursor, count, cookie.Cookies, cate.XId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//protected override bool ShouldContinueSync(DouyinCookie cookie, DouyinVideoInfoResponse data, DouyinFollowed followed=null)
|
//protected override bool ShouldContinueSync(DouyinCookie cookie, DouyinVideoInfoResponse data, DouyinFollowed followed=null)
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace dy.net.model.dto
|
|||||||
/// <param name="t"></param>
|
/// <param name="t"></param>
|
||||||
/// <param name="message"></param>
|
/// <param name="message"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IActionResult SuccOrFail<T>(int code,T t,string message = "")
|
public static IActionResult SuccOrFail<T>(int code, T t, string message = "")
|
||||||
{
|
{
|
||||||
if (code == ResponseCode.Success)
|
if (code == ResponseCode.Success)
|
||||||
{
|
{
|
||||||
@@ -130,7 +130,7 @@ namespace dy.net.model.dto
|
|||||||
/// <param name="message">错误消息</param>
|
/// <param name="message">错误消息</param>
|
||||||
/// <param name="data">附加数据</param>
|
/// <param name="data">附加数据</param>
|
||||||
/// <returns>IActionResult</returns>
|
/// <returns>IActionResult</returns>
|
||||||
public static IActionResult Fail<T>(string message="请求失败", int businessCode = ResponseCode.ServerError, T data = default)
|
public static IActionResult Fail<T>(string message = "请求失败", int businessCode = ResponseCode.ServerError, T data = default)
|
||||||
{
|
{
|
||||||
var response = new DouyinApiResponse<T>
|
var response = new DouyinApiResponse<T>
|
||||||
{
|
{
|
||||||
@@ -158,7 +158,7 @@ namespace dy.net.model.dto
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">错误消息</param>
|
/// <param name="message">错误消息</param>
|
||||||
/// <returns>IActionResult</returns>
|
/// <returns>IActionResult</returns>
|
||||||
public static IActionResult Fail(string message="请求失败")
|
public static IActionResult Fail(string message = "请求失败")
|
||||||
{
|
{
|
||||||
return Fail<object>(message, ResponseCode.ServerError);
|
return Fail<object>(message, ResponseCode.ServerError);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Newtonsoft.Json;
|
namespace dy.net.model.dto
|
||||||
|
|
||||||
namespace dy.net.model.dto
|
|
||||||
{
|
{
|
||||||
public class DouyinUpSecUserIdDto
|
public class DouyinUpSecUserIdDto
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
namespace dy.net.model.dto
|
||||||
|
|
||||||
namespace dy.net.model.dto
|
|
||||||
{
|
{
|
||||||
public class DouyinVideoPageRequestDto : PageRequestDto
|
public class DouyinVideoPageRequestDto : PageRequestDto
|
||||||
{
|
{
|
||||||
@@ -35,7 +33,7 @@ namespace dy.net.model.dto
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public class FollowRequestDto: PageRequestDto
|
public class FollowRequestDto : PageRequestDto
|
||||||
{
|
{
|
||||||
public string FollowUserName { get; set; }
|
public string FollowUserName { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
using System;
|
namespace dy.net.model.dto
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace dy.net.model.dto
|
|
||||||
{
|
{
|
||||||
public class MediaMergeRequest
|
public class MediaMergeRequest
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.ComponentModel;
|
namespace dy.net.model.dto
|
||||||
|
|
||||||
namespace dy.net.model.dto
|
|
||||||
{
|
{
|
||||||
public enum VideoTypeEnum
|
public enum VideoTypeEnum
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
namespace dy.net.model.entity
|
||||||
|
|
||||||
namespace dy.net.model.entity
|
|
||||||
{
|
{
|
||||||
[SqlSugar.SugarTable(TableName = "login_user_info")]
|
[SqlSugar.SugarTable(TableName = "login_user_info")]
|
||||||
public class AdminUserInfo
|
public class AdminUserInfo
|
||||||
{
|
{
|
||||||
public string UserName { get; set;}
|
public string UserName { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
|
||||||
[SqlSugar.SugarColumn(IsPrimaryKey = true)]
|
[SqlSugar.SugarColumn(IsPrimaryKey = true)]
|
||||||
@@ -23,7 +21,7 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 原密码,不存在数据库
|
/// 原密码,不存在数据库
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SqlSugar.SugarColumn(IsIgnore =true)]
|
[SqlSugar.SugarColumn(IsIgnore = true)]
|
||||||
public string? OldPwd { get; set; }
|
public string? OldPwd { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Newtonsoft.Json;
|
using SqlSugar;
|
||||||
using SqlSugar;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace dy.net.model.entity
|
namespace dy.net.model.entity
|
||||||
{
|
{
|
||||||
@@ -15,10 +13,10 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsPrimaryKey = true,Length =100)]
|
[SugarColumn(IsPrimaryKey = true, Length = 100)]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public int Cron { get; set; }
|
public int Cron { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -29,18 +29,18 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 收藏夹Id、合集Id、短剧Id
|
/// 收藏夹Id、合集Id、短剧Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =60,IsNullable =false)]
|
[SugarColumn(Length = 60, IsNullable = false)]
|
||||||
public string XId { get; set; }
|
public string XId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 封面
|
/// 封面
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =500,IsNullable =true)]
|
[SugarColumn(Length = 500, IsNullable = true)]
|
||||||
public string CoverUrl { get; set; }
|
public string CoverUrl { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保存文件夹
|
/// 保存文件夹
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =500,IsNullable =true)]
|
[SugarColumn(Length = 500, IsNullable = true)]
|
||||||
public string SaveFolder { get; set; }
|
public string SaveFolder { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否开启同步
|
/// 是否开启同步
|
||||||
@@ -52,9 +52,9 @@ namespace dy.net.model.entity
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public VideoTypeEnum CateType { get; set; }
|
public VideoTypeEnum CateType { get; set; }
|
||||||
|
|
||||||
public DateTime CreateTime { get; set; }
|
public DateTime CreateTime { get; set; }
|
||||||
|
|
||||||
[SugarColumn(IsNullable =true)]
|
[SugarColumn(IsNullable = true)]
|
||||||
public DateTime? UpdateTime { get; set; }
|
public DateTime? UpdateTime { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否已完结
|
/// 是否已完结
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Newtonsoft.Json;
|
using SqlSugar;
|
||||||
using SqlSugar;
|
|
||||||
|
|
||||||
namespace dy.net.model.entity
|
namespace dy.net.model.entity
|
||||||
{
|
{
|
||||||
@@ -18,18 +17,18 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 博主sec_uid
|
/// 博主sec_uid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = false,Length =500)]
|
[SugarColumn(IsNullable = false, Length = 500)]
|
||||||
public string SecUid { get; set; }
|
public string SecUid { get; set; }
|
||||||
|
|
||||||
[SugarColumn(IsNullable = false, Length =200)]
|
[SugarColumn(IsNullable = false, Length = 200)]
|
||||||
public string UperName { get; set; }
|
public string UperName { get; set; }
|
||||||
|
|
||||||
[SugarColumn(IsNullable = true, Length =1000)]
|
[SugarColumn(IsNullable = true, Length = 1000)]
|
||||||
public string UperAvatar { get; set; }
|
public string UperAvatar { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 官方账号(企业认证)
|
/// 官方账号(企业认证)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = true, Length =200)]
|
[SugarColumn(IsNullable = true, Length = 200)]
|
||||||
public string Enterprise { get; set; }
|
public string Enterprise { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否开启同步
|
/// 是否开启同步
|
||||||
@@ -47,25 +46,25 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 我的userId,关注者的抖音userid
|
/// 我的userId,关注者的抖音userid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = false,Length =200)]
|
[SugarColumn(IsNullable = false, Length = 200)]
|
||||||
public string mySelfId { get; set; }
|
public string mySelfId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 签名
|
/// 签名
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = true,Length =500)]
|
[SugarColumn(IsNullable = true, Length = 500)]
|
||||||
public string Signature { get; set; }
|
public string Signature { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 同步文件保存路径
|
/// 同步文件保存路径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = true,Length =500)]
|
[SugarColumn(IsNullable = true, Length = 500)]
|
||||||
public string SavePath { get; set; }
|
public string SavePath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 博主Id
|
/// 博主Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable = true,Length =100)]
|
[SugarColumn(IsNullable = true, Length = 100)]
|
||||||
public string UperId { get; set; }
|
public string UperId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 原视频Id
|
/// 原视频Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable =true,Length =50)]
|
[SugarColumn(IsNullable = true, Length = 50)]
|
||||||
public string ViedoId { get; set; }
|
public string ViedoId { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 原保存目录
|
/// 原保存目录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable =true,Length =1000)]
|
[SugarColumn(IsNullable = true, Length = 1000)]
|
||||||
public string SavePath { get; set; }
|
public string SavePath { get; set; }
|
||||||
|
|
||||||
public string CookieId { get; set; }
|
public string CookieId { get; set; }
|
||||||
|
|||||||
+27
-28
@@ -1,5 +1,4 @@
|
|||||||
using dy.net.extension;
|
using dy.net.model.dto;
|
||||||
using dy.net.model.dto;
|
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
@@ -15,17 +14,17 @@ namespace dy.net.model.entity
|
|||||||
[SugarColumn(IsPrimaryKey = true)]
|
[SugarColumn(IsPrimaryKey = true)]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string DyUserId { get; set; }
|
public string DyUserId { get; set; }
|
||||||
[SugarColumn(IsIgnore =true)]
|
[SugarColumn(IsIgnore = true)]
|
||||||
public string DyUser { get; set; }
|
public string DyUser { get; set; }
|
||||||
|
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string CookieId { get; set; }
|
public string CookieId { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// aweme_id
|
/// aweme_id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string AwemeId { get; set; }
|
public string AwemeId { get; set; }
|
||||||
|
|
||||||
public DateTime SyncTime { get; set; }
|
public DateTime SyncTime { get; set; }
|
||||||
@@ -34,34 +33,34 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 视频标题
|
/// 视频标题
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =2000,IsNullable =true)]
|
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||||
public string VideoTitle { get; set; }
|
public string VideoTitle { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 如果配置文件 UperFileNameUseViedoTitle=true
|
/// 如果配置文件 UperFileNameUseViedoTitle=true
|
||||||
/// 简化后的标题 默认空 只有关注的博主的 视频会存储该字段,实际UP主的视频文件名是 VideoTitleSimplify + VideoTitleSimplifyPrefix
|
/// 简化后的标题 默认空 只有关注的博主的 视频会存储该字段,实际UP主的视频文件名是 VideoTitleSimplify + VideoTitleSimplifyPrefix
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =500,IsNullable =true)]
|
[SugarColumn(Length = 500, IsNullable = true)]
|
||||||
public string VideoTitleSimplify { get; set; }
|
public string VideoTitleSimplify { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 精简标题的前缀 默认空,其实就是序号,类似 001-,002-
|
/// 精简标题的前缀 默认空,其实就是序号,类似 001-,002-
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =50,IsNullable =true)]
|
[SugarColumn(Length = 50, IsNullable = true)]
|
||||||
public string VideoTitleSimplifyPrefix { get; set; }
|
public string VideoTitleSimplifyPrefix { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 标签(分类)
|
/// 标签(分类)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string Tag1 { get; set; }
|
public string Tag1 { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 标签(分类)
|
/// 标签(分类)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string Tag2 { get; set; }
|
public string Tag2 { get; set; }
|
||||||
|
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string Tag3 { get; set; }
|
public string Tag3 { get; set; }
|
||||||
|
|
||||||
///// <summary>
|
///// <summary>
|
||||||
@@ -71,59 +70,59 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 视频地址(解析会有多个取第一个)
|
/// 视频地址(解析会有多个取第一个)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =2000,IsNullable =true)]
|
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||||
public string VideoUrl { get; set; }
|
public string VideoUrl { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 视频下载后保存路径
|
/// 视频下载后保存路径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =2000,IsNullable =true)]
|
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||||
public string VideoSavePath { get; set; }
|
public string VideoSavePath { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 视频封面地址
|
/// 视频封面地址
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
[SugarColumn(Length =2000,IsNullable =true)]
|
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||||
public string VideoCoverUrl { get; set; }
|
public string VideoCoverUrl { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 视频封面保存路径
|
/// 视频封面保存路径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =2000,IsNullable =true)]
|
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||||
public string VideoCoverSavePath { get; set; }
|
public string VideoCoverSavePath { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 作者
|
/// 作者
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string Author { get; set; }
|
public string Author { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 作者ID
|
/// 作者ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string AuthorId { get; set; }
|
public string AuthorId { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 作者头像
|
/// 作者头像
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =2000,IsNullable =true)]
|
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||||
public string AuthorAvatar { get; set; }
|
public string AuthorAvatar { get; set; }
|
||||||
|
|
||||||
[SugarColumn(Length =2000,IsNullable =true)]
|
[SugarColumn(Length = 2000, IsNullable = true)]
|
||||||
public string AuthorAvatarUrl { get; set; }
|
public string AuthorAvatarUrl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件hash值唯一值
|
/// 文件hash值唯一值
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string FileHash { get; set; }
|
public string FileHash { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 文件大小(字节)
|
/// 文件大小(字节)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public long FileSize { get; set; }
|
public long FileSize { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 分辨率(如1920x1080, 3840x2160等)
|
/// 分辨率(如1920x1080, 3840x2160等)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string Resolution { get; set; }
|
public string Resolution { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -137,7 +136,7 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 1喜欢的,2收藏的,3关注的 ,4 图片视频
|
/// 1喜欢的,2收藏的,3关注的 ,4 图片视频
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public VideoTypeEnum ViedoType { get; set; }
|
public VideoTypeEnum ViedoType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -146,14 +145,14 @@ namespace dy.net.model.entity
|
|||||||
public int IsMergeVideo { get; set; }
|
public int IsMergeVideo { get; set; }
|
||||||
|
|
||||||
[SugarColumn(IsIgnore = true)]
|
[SugarColumn(IsIgnore = true)]
|
||||||
public string ViedoTypeStr => ViedoType.GetDesc();
|
public string ViedoTypeStr => ViedoType.GetDesc();
|
||||||
|
|
||||||
[SugarColumn(IsIgnore = true)]
|
[SugarColumn(IsIgnore = true)]
|
||||||
public string ViedoCate =>(string.IsNullOrWhiteSpace(Tag1) ? "" : Tag1) + "/" + (string.IsNullOrWhiteSpace(Tag2) ? "" : Tag2);
|
public string ViedoCate => (string.IsNullOrWhiteSpace(Tag1) ? "" : Tag1) + "/" + (string.IsNullOrWhiteSpace(Tag2) ? "" : Tag2);
|
||||||
|
|
||||||
|
|
||||||
// 普通字符串字段,显式标记为 SQLite TEXT 类型
|
// 普通字符串字段,显式标记为 SQLite TEXT 类型
|
||||||
[SugarColumn(ColumnDataType = "TEXT", Length = -1,IsNullable =true)]
|
[SugarColumn(ColumnDataType = "TEXT", Length = -1, IsNullable = true)]
|
||||||
public string DynamicVideos { get; set; }
|
public string DynamicVideos { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -164,7 +163,7 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义收藏夹、合集、短剧 绑定的Id
|
/// 自定义收藏夹、合集、短剧 绑定的Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(Length =200,IsNullable =true)]
|
[SugarColumn(Length = 200, IsNullable = true)]
|
||||||
public string CateId { get; set; }
|
public string CateId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ namespace dy.net.model.entity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 原视频Id
|
/// 原视频Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsNullable =true,Length =50)]
|
[SugarColumn(IsNullable = true, Length = 50)]
|
||||||
public string ViedoId { get; set; }
|
public string ViedoId { get; set; }
|
||||||
|
|
||||||
public DateTime DeleteTime { get; set; }
|
public DateTime DeleteTime { get; set; }
|
||||||
|
|
||||||
[SugarColumn(IsNullable =true,Length =1000)]
|
[SugarColumn(IsNullable = true, Length = 1000)]
|
||||||
public string VideoTitle { get; set; }
|
public string VideoTitle { get; set; }
|
||||||
[SugarColumn(IsNullable = true, Length = 1000)]
|
[SugarColumn(IsNullable = true, Length = 1000)]
|
||||||
public string VideoSavePath { get; set; }
|
public string VideoSavePath { get; set; }
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
|
||||||
namespace dy.net.model.response
|
namespace dy.net.model.response
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace dy.net.repository
|
|||||||
user.Password = newpassword;
|
user.Password = newpassword;
|
||||||
user.UserName = loginUser.UserName;
|
user.UserName = loginUser.UserName;
|
||||||
var res = await this.UpdateAsync(user);
|
var res = await this.UpdateAsync(user);
|
||||||
return (res?0:-1,res ?"更新成功" : "更新失败");
|
return (res ? 0 : -1, res ? "更新成功" : "更新失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -50,11 +50,11 @@ namespace dy.net.repository
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<AdminUserInfo> GetUser(string userName=null)
|
public async Task<AdminUserInfo> GetUser(string userName = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(userName))
|
if (string.IsNullOrWhiteSpace(userName))
|
||||||
{
|
{
|
||||||
return await this.GetFirstAsync(x=>!string.IsNullOrWhiteSpace(x.Id));
|
return await this.GetFirstAsync(x => !string.IsNullOrWhiteSpace(x.Id));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -80,7 +80,7 @@ namespace dy.net.repository
|
|||||||
{
|
{
|
||||||
user.Avatar = avatar;
|
user.Avatar = avatar;
|
||||||
var update = await UpdateAsync(user);
|
var update = await UpdateAsync(user);
|
||||||
return update ;
|
return update;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +89,10 @@ namespace dy.net.repository
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userInfo"></param>
|
/// <param name="userInfo"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public (int code, string erro) InitUser(AdminUserInfo userInfo)
|
public (int code, string erro) InitUser(AdminUserInfo userInfo)
|
||||||
{
|
{
|
||||||
var isInit = this.GetFirst(x=>!string.IsNullOrWhiteSpace(x.Id));
|
var isInit = this.GetFirst(x => !string.IsNullOrWhiteSpace(x.Id));
|
||||||
if (isInit!=null)
|
if (isInit != null)
|
||||||
{
|
{
|
||||||
return (-1, "系统用户已存在");
|
return (-1, "系统用户已存在");
|
||||||
}
|
}
|
||||||
@@ -102,8 +102,8 @@ namespace dy.net.repository
|
|||||||
userInfo.CreateTime = DateTime.Now;
|
userInfo.CreateTime = DateTime.Now;
|
||||||
userInfo.Password = Md5Util.Md5(userInfo.Password);
|
userInfo.Password = Md5Util.Md5(userInfo.Password);
|
||||||
|
|
||||||
var res = this.Insert(userInfo);
|
var res = this.Insert(userInfo);
|
||||||
return (res ? 0 : -1, res ? "初始用户成功" : "初始化用户失败");
|
return (res ? 0 : -1, res ? "初始用户成功" : "初始化用户失败");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ using dy.net.model.dto;
|
|||||||
using dy.net.model.entity;
|
using dy.net.model.entity;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using System;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
|
|
||||||
namespace dy.net.repository
|
namespace dy.net.repository
|
||||||
{
|
{
|
||||||
@@ -24,7 +22,7 @@ namespace dy.net.repository
|
|||||||
public async Task<(List<DouyinCollectCate> list, int totalCount)> GetPagedAsync(DouyinCollectCateRequestDto dto)
|
public async Task<(List<DouyinCollectCate> list, int totalCount)> GetPagedAsync(DouyinCollectCateRequestDto dto)
|
||||||
{
|
{
|
||||||
var where = this.Db.Queryable<DouyinCollectCate>()
|
var where = this.Db.Queryable<DouyinCollectCate>()
|
||||||
.Where(x=>x.CateType==dto.cateType)
|
.Where(x => x.CateType == dto.cateType)
|
||||||
.WhereIF(!string.IsNullOrWhiteSpace(dto.cookieId), x => x.CookieId == dto.cookieId);
|
.WhereIF(!string.IsNullOrWhiteSpace(dto.cookieId), x => x.CookieId == dto.cookieId);
|
||||||
|
|
||||||
var totalCount = await where.CountAsync();
|
var totalCount = await where.CountAsync();
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace dy.net.repository
|
|||||||
// 1. 初始化查询:先加固定条件 Status == 1
|
// 1. 初始化查询:先加固定条件 Status == 1
|
||||||
var query = Db.Queryable<DouyinCookie>()
|
var query = Db.Queryable<DouyinCookie>()
|
||||||
.Where(x => x.Status == 1)
|
.Where(x => x.Status == 1)
|
||||||
.Where(x=>!string.IsNullOrWhiteSpace(x.Cookies)); // 固定条件(必选)
|
.Where(x => !string.IsNullOrWhiteSpace(x.Cookies)); // 固定条件(必选)
|
||||||
|
|
||||||
// 2. 若传入自定义条件,叠加 Where(自动 AND 组合)
|
// 2. 若传入自定义条件,叠加 Where(自动 AND 组合)
|
||||||
if (whereExpression != null)
|
if (whereExpression != null)
|
||||||
@@ -38,16 +38,16 @@ namespace dy.net.repository
|
|||||||
return (list, totalCount);
|
return (list, totalCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DouyinCookie GetDefault()
|
public DouyinCookie GetDefault()
|
||||||
{
|
{
|
||||||
return Db.Queryable<DouyinCookie>()
|
return Db.Queryable<DouyinCookie>()
|
||||||
.First();
|
.First();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public async Task<bool> SwitchAsync(DouyinCookieSwitchDto dto)
|
public async Task<bool> SwitchAsync(DouyinCookieSwitchDto dto)
|
||||||
{
|
{
|
||||||
var res =await Db.Updateable<DouyinCookie>().SetColumns(x => new DouyinCookie { Status = dto.Status }).Where(x => x.Id == dto.Id).ExecuteCommandAsync();
|
var res = await Db.Updateable<DouyinCookie>().SetColumns(x => new DouyinCookie { Status = dto.Status }).Where(x => x.Id == dto.Id).ExecuteCommandAsync();
|
||||||
|
|
||||||
return res > 0;
|
return res > 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using ClockSnowFlake;
|
using ClockSnowFlake;
|
||||||
using dy.net.extension;
|
|
||||||
using dy.net.model.dto;
|
using dy.net.model.dto;
|
||||||
using dy.net.model.entity;
|
using dy.net.model.entity;
|
||||||
using dy.net.model.response;
|
using dy.net.model.response;
|
||||||
@@ -84,7 +83,7 @@ namespace dy.net.repository
|
|||||||
public async Task<List<DouyinFollowed>> GetSyncFollows(string userId)
|
public async Task<List<DouyinFollowed>> GetSyncFollows(string userId)
|
||||||
{
|
{
|
||||||
return await this.Db.Queryable<DouyinFollowed>()
|
return await this.Db.Queryable<DouyinFollowed>()
|
||||||
.Where(x => x.OpenSync == true).Where(x => x.mySelfId == userId).Where(x=>!string.IsNullOrWhiteSpace(x.SecUid))
|
.Where(x => x.OpenSync == true).Where(x => x.mySelfId == userId).Where(x => !string.IsNullOrWhiteSpace(x.SecUid))
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
using dy.net.extension;
|
using dy.net.extension;
|
||||||
using dy.net.model.dto;
|
using dy.net.model.dto;
|
||||||
using dy.net.model.entity;
|
using dy.net.model.entity;
|
||||||
using Quartz.Util;
|
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace dy.net.repository
|
namespace dy.net.repository
|
||||||
{
|
{
|
||||||
@@ -19,7 +17,7 @@ namespace dy.net.repository
|
|||||||
|
|
||||||
public async Task<List<DouyinVideoTopDto>> GetTopsOrderBySyncTime(int top)
|
public async Task<List<DouyinVideoTopDto>> GetTopsOrderBySyncTime(int top)
|
||||||
{
|
{
|
||||||
return await Db.Queryable<DouyinVideo>().Select(x=>new DouyinVideoTopDto {Id=x.Id, Title=x.VideoTitle,Time=x.SyncTime.ToString("yyyy-MM-dd HH:mm:ss")}).Take(top).OrderByDescending(x=>x.Time).ToListAsync();
|
return await Db.Queryable<DouyinVideo>().Select(x => new DouyinVideoTopDto { Id = x.Id, Title = x.VideoTitle, Time = x.SyncTime.ToString("yyyy-MM-dd HH:mm:ss") }).Take(top).OrderByDescending(x => x.Time).ToListAsync();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
@@ -45,7 +43,7 @@ namespace dy.net.repository
|
|||||||
//.WhereIF(!string.IsNullOrWhiteSpace(title), x => x.VideoTitle.Contains(title))
|
//.WhereIF(!string.IsNullOrWhiteSpace(title), x => x.VideoTitle.Contains(title))
|
||||||
.WhereIF(!string.IsNullOrWhiteSpace(dto.Title), x => x.VideoTitle.Contains(dto.Title))
|
.WhereIF(!string.IsNullOrWhiteSpace(dto.Title), x => x.VideoTitle.Contains(dto.Title))
|
||||||
.WhereIF(!string.IsNullOrWhiteSpace(dto.Author), x => x.Author.Contains(dto.Author))
|
.WhereIF(!string.IsNullOrWhiteSpace(dto.Author), x => x.Author.Contains(dto.Author))
|
||||||
.WhereIF(!string.IsNullOrWhiteSpace(dto.Tag), x => x.Tag1==dto.Tag)
|
.WhereIF(!string.IsNullOrWhiteSpace(dto.Tag), x => x.Tag1 == dto.Tag)
|
||||||
.WhereIF(start.HasValue, x => x.SyncTime >= start.Value)
|
.WhereIF(start.HasValue, x => x.SyncTime >= start.Value)
|
||||||
.WhereIF(end.HasValue, x => x.SyncTime <= end.Value)
|
.WhereIF(end.HasValue, x => x.SyncTime <= end.Value)
|
||||||
.WhereIF(start2.HasValue, x => x.CreateTime >= start2.Value)
|
.WhereIF(start2.HasValue, x => x.CreateTime >= start2.Value)
|
||||||
@@ -56,8 +54,8 @@ namespace dy.net.repository
|
|||||||
|
|
||||||
var totalCount = await where.CountAsync();
|
var totalCount = await where.CountAsync();
|
||||||
List<DouyinVideo> list = new List<DouyinVideo>();
|
List<DouyinVideo> list = new List<DouyinVideo>();
|
||||||
if(string.IsNullOrWhiteSpace(dto.SortField))
|
if (string.IsNullOrWhiteSpace(dto.SortField))
|
||||||
list = await where.OrderByDescending(x => x.SyncTime).Skip((dto.PageIndex - 1) * dto.PageSize).Take(dto.PageSize).ToListAsync();
|
list = await where.OrderByDescending(x => x.SyncTime).Skip((dto.PageIndex - 1) * dto.PageSize).Take(dto.PageSize).ToListAsync();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -100,10 +98,10 @@ namespace dy.net.repository
|
|||||||
/// <param name="AuthorId"></param>
|
/// <param name="AuthorId"></param>
|
||||||
/// <param name="ViedoNameSimplify"></param>
|
/// <param name="ViedoNameSimplify"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public (string, string) GetUperLastViedoFileName(string AuthorId, string ViedoNameSimplify)
|
public (string, string) GetUperLastViedoFileName(string AuthorId, string ViedoNameSimplify)
|
||||||
{
|
{
|
||||||
|
|
||||||
var video = this.Db.Queryable<DouyinVideo>().Where(x => x.AuthorId == AuthorId && x.ViedoType == VideoTypeEnum.dy_follows)
|
var video = this.Db.Queryable<DouyinVideo>().Where(x => x.AuthorId == AuthorId && x.ViedoType == VideoTypeEnum.dy_follows)
|
||||||
.Where(x => x.VideoTitleSimplify == ViedoNameSimplify)
|
.Where(x => x.VideoTitleSimplify == ViedoNameSimplify)
|
||||||
.OrderByDescending(x => x.CreateTime).First();
|
.OrderByDescending(x => x.CreateTime).First();
|
||||||
|
|
||||||
@@ -157,7 +155,7 @@ namespace dy.net.repository
|
|||||||
{
|
{
|
||||||
if (downs != null)
|
if (downs != null)
|
||||||
{
|
{
|
||||||
return Db.Insertable(downs).ExecuteCommand() > 0;
|
return Db.Insertable(downs).ExecuteCommand() > 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace dy.net.service
|
|||||||
return await _userRepository.UpdatePwd(loginUser);
|
return await _userRepository.UpdatePwd(loginUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AdminUserInfo> GetUser(string userName=null)
|
public async Task<AdminUserInfo> GetUser(string userName = null)
|
||||||
{
|
{
|
||||||
return await _userRepository.GetUser(userName);
|
return await _userRepository.GetUser(userName);
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ namespace dy.net.service
|
|||||||
return await _userRepository.UpdateAvatar(avatar);
|
return await _userRepository.UpdateAvatar(avatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
public (int code, string erro) InitUser(string UserName,string Password)
|
public (int code, string erro) InitUser(string UserName, string Password)
|
||||||
{
|
{
|
||||||
AdminUserInfo userInfo = new AdminUserInfo
|
AdminUserInfo userInfo = new AdminUserInfo
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,7 @@ namespace dy.net.service
|
|||||||
Password = Password,
|
Password = Password,
|
||||||
CreateTime = DateTime.Now
|
CreateTime = DateTime.Now
|
||||||
};
|
};
|
||||||
return _userRepository.InitUser(userInfo);
|
return _userRepository.InitUser(userInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
using ClockSnowFlake;
|
using dy.net.model.dto;
|
||||||
using dy.net.model.dto;
|
|
||||||
using dy.net.model.entity;
|
using dy.net.model.entity;
|
||||||
using dy.net.model.response;
|
|
||||||
using dy.net.repository;
|
using dy.net.repository;
|
||||||
using SqlSugar;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
|
|
||||||
namespace dy.net.service
|
namespace dy.net.service
|
||||||
{
|
{
|
||||||
@@ -45,7 +41,7 @@ namespace dy.net.service
|
|||||||
/// <param name="ckId"></param>
|
/// <param name="ckId"></param>
|
||||||
/// <param name="cateType"></param>
|
/// <param name="cateType"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<(int add, int update,int delete, bool succ)> Sync(List<DouyinCollectCate> cates, string ckId,VideoTypeEnum cateType)
|
public async Task<(int add, int update, int delete, bool succ)> Sync(List<DouyinCollectCate> cates, string ckId, VideoTypeEnum cateType)
|
||||||
{
|
{
|
||||||
return await _douyinCollectCateRepository.Sync(cates, ckId, cateType);
|
return await _douyinCollectCateRepository.Sync(cates, ckId, cateType);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
using ClockSnowFlake;
|
using ClockSnowFlake;
|
||||||
using dy.net.model.dto;
|
|
||||||
using dy.net.model.entity;
|
using dy.net.model.entity;
|
||||||
using dy.net.utils;
|
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
//using static Org.BouncyCastle.Math.EC.ECCurve;
|
//using static Org.BouncyCastle.Math.EC.ECCurve;
|
||||||
|
|
||||||
namespace dy.net.service
|
namespace dy.net.service
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
using dy.net.model.dto;
|
using dy.net.model.dto;
|
||||||
using dy.net.model.entity;
|
using dy.net.model.entity;
|
||||||
using dy.net.repository;
|
using dy.net.repository;
|
||||||
using SqlSugar;
|
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace dy.net.service
|
namespace dy.net.service
|
||||||
{
|
{
|
||||||
@@ -33,7 +31,7 @@ namespace dy.net.service
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<bool> IsInit()
|
public async Task<bool> IsInit()
|
||||||
{
|
{
|
||||||
return await _cookieRepository.ExistsAsync(x => !string.IsNullOrEmpty(x.Id));
|
return await _cookieRepository.ExistsAsync(x => !string.IsNullOrEmpty(x.Id));
|
||||||
}
|
}
|
||||||
public async Task<bool> Add(DouyinCookie dyUserCookies)
|
public async Task<bool> Add(DouyinCookie dyUserCookies)
|
||||||
{
|
{
|
||||||
@@ -64,9 +62,9 @@ namespace dy.net.service
|
|||||||
//CollHasSyncd = 0,
|
//CollHasSyncd = 0,
|
||||||
//FavHasSyncd = 0,
|
//FavHasSyncd = 0,
|
||||||
//UperSyncd = 0,
|
//UperSyncd = 0,
|
||||||
MyUserId=""
|
MyUserId = ""
|
||||||
};
|
};
|
||||||
return _cookieRepository.Insert(cookie);
|
return _cookieRepository.Insert(cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询单个
|
// 查询单个
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using dy.net.model.entity;
|
|||||||
using dy.net.model.response;
|
using dy.net.model.response;
|
||||||
using dy.net.repository;
|
using dy.net.repository;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using System.Linq.Expressions;
|
|
||||||
|
|
||||||
namespace dy.net.service
|
namespace dy.net.service
|
||||||
{
|
{
|
||||||
@@ -32,8 +31,8 @@ namespace dy.net.service
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<bool> AddAsync(DouyinFollowed followed)
|
public async Task<bool> AddAsync(DouyinFollowed followed)
|
||||||
{
|
{
|
||||||
var foll= await _followRepository.GetFirstAsync(x=>x.SecUid==followed.SecUid && x.mySelfId== followed.mySelfId);
|
var foll = await _followRepository.GetFirstAsync(x => x.SecUid == followed.SecUid && x.mySelfId == followed.mySelfId);
|
||||||
if(foll!=null)
|
if (foll != null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -59,7 +58,7 @@ namespace dy.net.service
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<List<DouyinFollowed>> GetHandFollows()
|
public async Task<List<DouyinFollowed>> GetHandFollows()
|
||||||
{
|
{
|
||||||
return await _followRepository.GetListAsync(x=>x.IsNoFollowed);
|
return await _followRepository.GetListAsync(x => x.IsNoFollowed);
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 导入非关注
|
/// 导入非关注
|
||||||
@@ -114,7 +113,7 @@ namespace dy.net.service
|
|||||||
return await _followRepository.Sync(followInfos, ck);
|
return await _followRepository.Sync(followInfos, ck);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<DouyinFollowed> GetByUperId(string uperId,string myUid)
|
public async Task<DouyinFollowed> GetByUperId(string uperId, string myUid)
|
||||||
{
|
{
|
||||||
return await _followRepository.GetBySecUId(uperId, myUid);
|
return await _followRepository.GetBySecUId(uperId, myUid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
using Dm;
|
using dy.net.model.dto;
|
||||||
using dy.net.model.dto;
|
|
||||||
using dy.net.model.entity;
|
using dy.net.model.entity;
|
||||||
using dy.net.model.response;
|
using dy.net.model.response;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using Microsoft.AspNetCore.WebUtilities;
|
using Microsoft.AspNetCore.WebUtilities;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace dy.net.service
|
namespace dy.net.service
|
||||||
{
|
{
|
||||||
@@ -15,7 +12,7 @@ namespace dy.net.service
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
readonly IHttpClientFactory _clientFactory;
|
private readonly IHttpClientFactory _clientFactory;
|
||||||
public DouyinHttpClientService(IHttpClientFactory clientFactory)
|
public DouyinHttpClientService(IHttpClientFactory clientFactory)
|
||||||
{
|
{
|
||||||
_clientFactory = clientFactory;
|
_clientFactory = clientFactory;
|
||||||
@@ -110,7 +107,7 @@ namespace dy.net.service
|
|||||||
if (respose.IsSuccessStatusCode)
|
if (respose.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
var data = await respose.Content.ReadAsStringAsync();
|
var data = await respose.Content.ReadAsStringAsync();
|
||||||
var model= JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
var model = JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
||||||
if (model == null)
|
if (model == null)
|
||||||
Serilog.Log.Error($"SyncCollectVideos fail: {data}");
|
Serilog.Log.Error($"SyncCollectVideos fail: {data}");
|
||||||
return model;
|
return model;
|
||||||
@@ -169,7 +166,7 @@ namespace dy.net.service
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Serilog.Log.Error("SyncCollectFolderList ,{StatusCode}", respose.StatusCode);
|
Serilog.Log.Error("SyncCollectFolderList ,{StatusCode}", respose.StatusCode);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,7 +228,7 @@ namespace dy.net.service
|
|||||||
if (respose.IsSuccessStatusCode)
|
if (respose.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
var data = await respose.Content.ReadAsStringAsync();
|
var data = await respose.Content.ReadAsStringAsync();
|
||||||
var model= JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
var model = JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
||||||
if (model == null)
|
if (model == null)
|
||||||
Serilog.Log.Error($"SyncCollectVideosByCollectId fail: {data}");
|
Serilog.Log.Error($"SyncCollectVideosByCollectId fail: {data}");
|
||||||
return model;
|
return model;
|
||||||
@@ -352,7 +349,7 @@ namespace dy.net.service
|
|||||||
if (respose.IsSuccessStatusCode)
|
if (respose.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
var data = await respose.Content.ReadAsStringAsync();
|
var data = await respose.Content.ReadAsStringAsync();
|
||||||
var model = JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
var model = JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
||||||
if (model == null)
|
if (model == null)
|
||||||
Serilog.Log.Error($"SyncMixViedosByMixId fail: {data}");
|
Serilog.Log.Error($"SyncMixViedosByMixId fail: {data}");
|
||||||
return model;
|
return model;
|
||||||
@@ -472,7 +469,7 @@ namespace dy.net.service
|
|||||||
if (respose.IsSuccessStatusCode)
|
if (respose.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
var data = await respose.Content.ReadAsStringAsync();
|
var data = await respose.Content.ReadAsStringAsync();
|
||||||
var model= JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
var model = JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
||||||
if (model == null)
|
if (model == null)
|
||||||
Serilog.Log.Error($"SyncSeriesViedosByMSeriesId fail: {data}");
|
Serilog.Log.Error($"SyncSeriesViedosByMSeriesId fail: {data}");
|
||||||
return model;
|
return model;
|
||||||
@@ -544,7 +541,7 @@ namespace dy.net.service
|
|||||||
if (respose.IsSuccessStatusCode)
|
if (respose.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
var data = await respose.Content.ReadAsStringAsync();
|
var data = await respose.Content.ReadAsStringAsync();
|
||||||
var model= JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
var model = JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
||||||
if (model == null)
|
if (model == null)
|
||||||
Serilog.Log.Error($"SyncFavoriteVideos fail: {data}");
|
Serilog.Log.Error($"SyncFavoriteVideos fail: {data}");
|
||||||
return model;
|
return model;
|
||||||
@@ -616,7 +613,7 @@ namespace dy.net.service
|
|||||||
if (respose.IsSuccessStatusCode)
|
if (respose.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
var data = await respose.Content.ReadAsStringAsync();
|
var data = await respose.Content.ReadAsStringAsync();
|
||||||
var model= JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
var model = JsonConvert.DeserializeObject<DouyinVideoInfoResponse>(data);
|
||||||
if (model == null)
|
if (model == null)
|
||||||
Serilog.Log.Error($"SyncUpderPostVideos fail: {data}");
|
Serilog.Log.Error($"SyncUpderPostVideos fail: {data}");
|
||||||
return model;
|
return model;
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
using ClockSnowFlake;
|
using dy.net.extension;
|
||||||
using dy.net.extension;
|
|
||||||
using dy.net.model.dto;
|
using dy.net.model.dto;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace dy.net.service
|
namespace dy.net.service
|
||||||
@@ -37,7 +35,7 @@ namespace dy.net.service
|
|||||||
/// <param name="savePath"></param>
|
/// <param name="savePath"></param>
|
||||||
/// <param name="ck"></param>
|
/// <param name="ck"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<(string mp4Path,string mp3Path)> MergeMultipleVideosAsync(
|
public async Task<(string mp4Path, string mp3Path)> MergeMultipleVideosAsync(
|
||||||
List<DouyinDynamicVideoDto> videoFilePaths,
|
List<DouyinDynamicVideoDto> videoFilePaths,
|
||||||
string audioPath,
|
string audioPath,
|
||||||
string savePath,
|
string savePath,
|
||||||
@@ -51,11 +49,11 @@ namespace dy.net.service
|
|||||||
if (SuccessPaths != null && SuccessPaths.Length > 0)
|
if (SuccessPaths != null && SuccessPaths.Length > 0)
|
||||||
{
|
{
|
||||||
mergMusicPath = SuccessPaths[0];
|
mergMusicPath = SuccessPaths[0];
|
||||||
mp3Path= SuccessPaths[0];
|
mp3Path = SuccessPaths[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var ffmpeg = new FFmpegHelper();
|
var ffmpeg = new FFmpegHelper();
|
||||||
var mp4Path= await ffmpeg.MergeMultipleVideosAsync(videoFilePaths, mergMusicPath, savePath);
|
var mp4Path = await ffmpeg.MergeMultipleVideosAsync(videoFilePaths, mergMusicPath, savePath);
|
||||||
return (mp4Path, mp3Path);
|
return (mp4Path, mp3Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +134,7 @@ namespace dy.net.service
|
|||||||
// 保存下载的图片(如果需要)
|
// 保存下载的图片(如果需要)
|
||||||
if (downImage)
|
if (downImage)
|
||||||
{
|
{
|
||||||
await SaveDownloadedFilesAsync(rawImages, fileNamefolder, "jpg",Path.GetFileNameWithoutExtension(outputVideoPath));
|
await SaveDownloadedFilesAsync(rawImages, fileNamefolder, "jpg", Path.GetFileNameWithoutExtension(outputVideoPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 下载音频
|
// 2. 下载音频
|
||||||
@@ -154,7 +152,7 @@ namespace dy.net.service
|
|||||||
// 保存下载的音频(如果需要)
|
// 保存下载的音频(如果需要)
|
||||||
if (downMp3)
|
if (downMp3)
|
||||||
{
|
{
|
||||||
var ext= Path.GetExtension(rawAudios[0]);
|
var ext = Path.GetExtension(rawAudios[0]);
|
||||||
await SaveDownloadedFilesAsync(rawAudios, fileNamefolder, ext, Path.GetFileNameWithoutExtension(outputVideoPath));
|
await SaveDownloadedFilesAsync(rawAudios, fileNamefolder, ext, Path.GetFileNameWithoutExtension(outputVideoPath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,7 +160,7 @@ namespace dy.net.service
|
|||||||
// 不合成视频,直接返回成功
|
// 不合成视频,直接返回成功
|
||||||
if (!mergeImg2Viedo)
|
if (!mergeImg2Viedo)
|
||||||
{
|
{
|
||||||
Log.Debug($"根据系统配置设置不下载图文视频-[{outputVideoPath}],{(downImage?"下载图片":"不下载图片")},{(downMp3?"下载音频":"不下载音频")}");
|
Log.Debug($"根据系统配置设置不下载图文视频-[{outputVideoPath}],{(downImage ? "下载图片" : "不下载图片")},{(downMp3 ? "下载音频" : "不下载音频")}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,7 +235,7 @@ namespace dy.net.service
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保存下载的文件(图片/音频)到目标目录
|
/// 保存下载的文件(图片/音频)到目标目录
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static async Task SaveDownloadedFilesAsync(string[] sourcePaths, string targetFolder, string defaultExt,string videoFileName)
|
private static async Task SaveDownloadedFilesAsync(string[] sourcePaths, string targetFolder, string defaultExt, string videoFileName)
|
||||||
{
|
{
|
||||||
if (sourcePaths == null || sourcePaths.Length == 0) return;
|
if (sourcePaths == null || sourcePaths.Length == 0) return;
|
||||||
Directory.CreateDirectory(targetFolder); // 确保目标目录存在
|
Directory.CreateDirectory(targetFolder); // 确保目标目录存在
|
||||||
@@ -329,7 +327,7 @@ namespace dy.net.service
|
|||||||
|
|
||||||
/// <summary>通用媒体下载方法</summary>
|
/// <summary>通用媒体下载方法</summary>
|
||||||
private async Task<(string[] SuccessPaths, string ErrorMsg)> DownloadMediaAsync(
|
private async Task<(string[] SuccessPaths, string ErrorMsg)> DownloadMediaAsync(
|
||||||
List<string> urls, string saveDir, string prefix, string ext,string cookie)
|
List<string> urls, string saveDir, string prefix, string ext, string cookie)
|
||||||
{
|
{
|
||||||
var successPaths = new List<string>();
|
var successPaths = new List<string>();
|
||||||
for (var i = 0; i < urls.Count; i++)
|
for (var i = 0; i < urls.Count; i++)
|
||||||
@@ -341,8 +339,8 @@ namespace dy.net.service
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var (Success, ActualSavePath) = await douyinHttpClientService.DownloadAsync(url, savePath, cookie);
|
var (Success, ActualSavePath) = await douyinHttpClientService.DownloadAsync(url, savePath, cookie);
|
||||||
if(Success)
|
if (Success)
|
||||||
{
|
{
|
||||||
successPaths.Add(ActualSavePath);
|
successPaths.Add(ActualSavePath);
|
||||||
}
|
}
|
||||||
@@ -350,7 +348,7 @@ namespace dy.net.service
|
|||||||
{
|
{
|
||||||
Serilog.Log.Error($"下载失败:{url} → {savePath}");
|
Serilog.Log.Error($"下载失败:{url} → {savePath}");
|
||||||
}
|
}
|
||||||
//Console.WriteLine($"下载成功:{url} → {savePath}");
|
//Console.WriteLine($"下载成功:{url} → {savePath}");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,10 +3,6 @@ using dy.net.model.dto;
|
|||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using Quartz;
|
using Quartz;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace dy.net.service
|
namespace dy.net.service
|
||||||
{
|
{
|
||||||
@@ -99,7 +95,6 @@ namespace dy.net.service
|
|||||||
/// 启动所有抖音相关定时任务(所有任务独立执行)
|
/// 启动所有抖音相关定时任务(所有任务独立执行)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="expression">Cron表达式或间隔分钟数(所有任务使用相同的执行频率)</param>
|
/// <param name="expression">Cron表达式或间隔分钟数(所有任务使用相同的执行频率)</param>
|
||||||
/// <param name="isRestart"></param>
|
|
||||||
/// <returns>是否启动成功</returns>
|
/// <returns>是否启动成功</returns>
|
||||||
public async Task<bool> InitOrReStartAllJobs(string expression)
|
public async Task<bool> InitOrReStartAllJobs(string expression)
|
||||||
{
|
{
|
||||||
@@ -120,6 +115,8 @@ namespace dy.net.service
|
|||||||
// 执行任务启动逻辑
|
// 执行任务启动逻辑
|
||||||
foreach (var jobKey in JobConfigs.Keys)
|
foreach (var jobKey in JobConfigs.Keys)
|
||||||
{
|
{
|
||||||
|
if (jobKey == "follow_user_once")
|
||||||
|
continue;
|
||||||
if (jobKey == "follow_user") expression = "60";
|
if (jobKey == "follow_user") expression = "60";
|
||||||
var startSuccess = await StartJobAsync(jobKey, expression);
|
var startSuccess = await StartJobAsync(jobKey, expression);
|
||||||
if (startSuccess)
|
if (startSuccess)
|
||||||
@@ -131,7 +128,7 @@ namespace dy.net.service
|
|||||||
Log.Error($"启动任务失败:{jobKey}");
|
Log.Error($"启动任务失败:{jobKey}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log.Information($"共启动 {JobConfigs.Count} 个定时任务");
|
Log.Information($"共启动 {JobConfigs.Count - 1} 个定时任务");
|
||||||
|
|
||||||
|
|
||||||
//await StartJobAsync(VideoTypeEnum.dy_custom_collect.GetDesc(), expression);
|
//await StartJobAsync(VideoTypeEnum.dy_custom_collect.GetDesc(), expression);
|
||||||
|
|||||||
@@ -1,371 +0,0 @@
|
|||||||
//using dy.net.job;
|
|
||||||
//using dy.net.model.dto;
|
|
||||||
//using Quartz;
|
|
||||||
//using Quartz.Impl.Matchers;
|
|
||||||
//using Serilog;
|
|
||||||
//using System;
|
|
||||||
//using System.Threading.Tasks;
|
|
||||||
|
|
||||||
//namespace dy.net.service
|
|
||||||
//{
|
|
||||||
// /// <summary>
|
|
||||||
// /// 抖音相关定时任务服务
|
|
||||||
// /// </summary>
|
|
||||||
// public class DouyinQuartzJobService
|
|
||||||
// {
|
|
||||||
// private readonly ISchedulerFactory _schedulerFactory;
|
|
||||||
// private const string DefaultJobGroup = "dysync.net";
|
|
||||||
// private const int DefaultIntervalMinutes = 30;
|
|
||||||
// private const int DefaultCronStartDelaySeconds = 30;
|
|
||||||
// private const int DefaultSimpleStartDelaySeconds = 3;
|
|
||||||
|
|
||||||
// // 任务顺序依赖配置(核心:定义执行顺序,供 Listener 使用)
|
|
||||||
// public Dictionary<string, string> JobDependency { get; } = new()
|
|
||||||
// {
|
|
||||||
// {"collect", "favorite"}, // collect 执行完 → 触发 favorite
|
|
||||||
// {"favorite", "followed"}, // favorite 执行完 → 触发 followed
|
|
||||||
// {"followed", null}, // followed 执行完 → 一轮任务结束
|
|
||||||
// };
|
|
||||||
|
|
||||||
// // 任务配置信息(保持原有配置不变,改为 public 供 Listener 访问)
|
|
||||||
// public Dictionary<string, JobConfig> JobConfigs { get; } = new()
|
|
||||||
// {
|
|
||||||
// {
|
|
||||||
// "collect",
|
|
||||||
// new JobConfig(
|
|
||||||
// typeof(DouyinCollectSyncJob),
|
|
||||||
// "dy.job.key.collect",
|
|
||||||
// "dy.trigger.key.collect",
|
|
||||||
// "抖音收藏同步任务")
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "favorite",
|
|
||||||
// new JobConfig(
|
|
||||||
// typeof(DouyinFavoritSyncJob),
|
|
||||||
// "dy.job.key.favorite",
|
|
||||||
// "dy.trigger.key.favorite",
|
|
||||||
// "抖音点赞同步任务")
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "followed",
|
|
||||||
// new JobConfig(
|
|
||||||
// typeof(DouyinFollowedSyncJob),
|
|
||||||
// "dy.job.key.followed",
|
|
||||||
// "dy.trigger.key.followed",
|
|
||||||
// "抖音关注博主作品同步任务")
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "follow_user",
|
|
||||||
// new JobConfig(
|
|
||||||
// typeof(DouyinFollowsAndCollnectsSyncJob),
|
|
||||||
// "dy.job.key.follow_user",
|
|
||||||
// "dy.trigger.key.follow_user",
|
|
||||||
// "抖音关注列表同步任务")
|
|
||||||
// },
|
|
||||||
|
|
||||||
// {
|
|
||||||
// "custom_collect",
|
|
||||||
// new JobConfig(
|
|
||||||
// typeof(DouyinCollectCustomSyncJob),
|
|
||||||
// "dy.job.key.custom_collect",
|
|
||||||
// "dy.trigger.key.custom_collect",
|
|
||||||
// "抖音自定义收藏夹列表同步任务")
|
|
||||||
// },
|
|
||||||
|
|
||||||
// {
|
|
||||||
// "mix",
|
|
||||||
// new JobConfig(
|
|
||||||
// typeof(DouyinMixSyncJob),
|
|
||||||
// "dy.job.key.mix",
|
|
||||||
// "dy.trigger.key.mix",
|
|
||||||
// "抖音收藏夹合集同步任务")
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "series",
|
|
||||||
// new JobConfig(
|
|
||||||
// typeof(DouyinSeriesSyncJob),
|
|
||||||
// "dy.job.key.mix",
|
|
||||||
// "dy.trigger.key.mix",
|
|
||||||
// "抖音收藏夹短剧同步任务")
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// "follow_user_once",
|
|
||||||
// new JobConfig(
|
|
||||||
// typeof(DouyinFollowsAndCollnectsSyncJob),
|
|
||||||
// "dy.job.key.follow_user_once",
|
|
||||||
// "dy.trigger.key.follow_user_once",
|
|
||||||
// "抖音关注同步任务(单次执行)")
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// public DouyinQuartzJobService(ISchedulerFactory schedulerFactory)
|
|
||||||
// {
|
|
||||||
// _schedulerFactory = schedulerFactory ?? throw new ArgumentNullException(nameof(schedulerFactory));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 启动所有抖音相关定时任务(顺序执行模式)
|
|
||||||
// /// </summary>
|
|
||||||
// /// <param name="expression">Cron表达式或间隔分钟数(控制整个链条的执行频率)</param>
|
|
||||||
// /// <returns>是否启动成功</returns>
|
|
||||||
// public async Task<bool> InitOrReStartAllJobs(string expression)
|
|
||||||
// {
|
|
||||||
// if (string.IsNullOrWhiteSpace(expression))
|
|
||||||
// {
|
|
||||||
// Log.Debug("定时任务表达式为空,使用默认配置({DefaultMinutes}分钟)", DefaultIntervalMinutes);
|
|
||||||
// expression = DefaultIntervalMinutes.ToString();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var scheduler = await _schedulerFactory.GetScheduler();
|
|
||||||
|
|
||||||
// // 1. 注册独立的 JobListener(核心:注入配置和服务)
|
|
||||||
// await RegisterJobListener(scheduler);
|
|
||||||
|
|
||||||
// // 2. 移除所有已存在的任务(避免重复调度)
|
|
||||||
// await RemoveAllExistingJobs(scheduler);
|
|
||||||
|
|
||||||
// // 3. 只启动第一个任务(collect),后续任务由 Listener 自动触发
|
|
||||||
// var firstJobConfigKey = "collect";
|
|
||||||
// //var startSuccess = await StartJobAsync(firstJobConfigKey, expression);
|
|
||||||
|
|
||||||
// //if (startSuccess)
|
|
||||||
// //{
|
|
||||||
// // Log.Debug($"同步任务执行顺序:collect → favorite → followed-->默认每{expression}分钟执行一次...");
|
|
||||||
// //}
|
|
||||||
// //else
|
|
||||||
// //{
|
|
||||||
// // Log.Error($"任务执行失败(任务 {firstJobConfigKey} 启动失败)");
|
|
||||||
// //}
|
|
||||||
// //启动follow_user--这个与其他几个任务没有依赖关系,所以单独启动
|
|
||||||
// //await StartJobAsync("collect", expression);
|
|
||||||
// //await StartJobAsync("follow_user", expression);
|
|
||||||
// //await StartJobAsync("follow_user", expression);
|
|
||||||
// //await StartJobAsync("follow_user", expression);
|
|
||||||
// //await StartJobAsync("custom_collect", expression);
|
|
||||||
// //await StartJobAsync("mix", expression);
|
|
||||||
// //await StartJobAsync("series", expression);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// Log.Error(ex, "【任务服务】初始化任务链条异常");
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 启动关注同步任务(单次执行)
|
|
||||||
// /// </summary>
|
|
||||||
// public async Task<bool> StartFollowJobOnceAsync()
|
|
||||||
// {
|
|
||||||
// return await StartOneTimeJobAsync("follow_user_once");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 注册独立的 JobListener(核心步骤)
|
|
||||||
// /// </summary>
|
|
||||||
// private async Task RegisterJobListener(IScheduler scheduler)
|
|
||||||
// {
|
|
||||||
// // 创建独立的 Listener 实例,注入依赖(任务配置、依赖关系、当前服务)
|
|
||||||
// var dependencyListener = new DouyinJobDependencyListener(
|
|
||||||
// JobConfigs, // 任务配置
|
|
||||||
// JobDependency, // 依赖顺序
|
|
||||||
// this // 任务服务(用于触发下一个任务)
|
|
||||||
// );
|
|
||||||
|
|
||||||
// // 注册 Listener:仅监听 DefaultJobGroup 分组的任务(精准匹配,避免影响其他任务)
|
|
||||||
// scheduler.ListenerManager.AddJobListener(
|
|
||||||
// dependencyListener,
|
|
||||||
// GroupMatcher<JobKey>.GroupEquals(DefaultJobGroup)
|
|
||||||
// );
|
|
||||||
|
|
||||||
// Log.Information("【任务服务】JobListener 注册成功:{ListenerName}", dependencyListener.Name);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 移除所有已存在的任务(避免重复调度)
|
|
||||||
// /// </summary>
|
|
||||||
// private async Task RemoveAllExistingJobs(IScheduler scheduler)
|
|
||||||
// {
|
|
||||||
// var jobKeys = JobConfigs.Values.Select(config => new JobKey(config.JobKey, DefaultJobGroup)).ToList();
|
|
||||||
// foreach (var jobKey in jobKeys)
|
|
||||||
// {
|
|
||||||
// if (await scheduler.CheckExists(jobKey))
|
|
||||||
// {
|
|
||||||
// Log.Information("【任务服务】移除已存在的任务: {JobKey}", jobKey);
|
|
||||||
// await scheduler.DeleteJob(jobKey);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 启动指定定时任务(public 修饰,供 Listener 调用)
|
|
||||||
// /// </summary>
|
|
||||||
// /// <param name="configKey">任务配置Key(如:collect、favorite)</param>
|
|
||||||
// /// <param name="expression">定时表达式(依赖触发时传空)</param>
|
|
||||||
// /// <param name="isDependencyTrigger">是否为依赖触发(true=立即执行,false=定时执行)</param>
|
|
||||||
// /// <returns>是否启动成功</returns>
|
|
||||||
// public async Task<bool> StartJobAsync(string configKey, string expression, bool isDependencyTrigger = false)
|
|
||||||
// {
|
|
||||||
// if (!JobConfigs.TryGetValue(configKey, out var jobConfig))
|
|
||||||
// {
|
|
||||||
// Log.Error("【任务服务】找不到任务配置: {ConfigKey}", configKey);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var scheduler = await _schedulerFactory.GetScheduler();
|
|
||||||
// var jobKey = new JobKey(jobConfig.JobKey, DefaultJobGroup);
|
|
||||||
// // 触发器Key:区分「定时触发」和「依赖触发」,避免冲突
|
|
||||||
// var triggerKey = new TriggerKey(
|
|
||||||
// $"{jobConfig.TriggerKey}_{(isDependencyTrigger ? "dependency" : "main")}",
|
|
||||||
// DefaultJobGroup
|
|
||||||
// );
|
|
||||||
|
|
||||||
// // 移除已存在的任务(防止重复执行)
|
|
||||||
// await RemoveExistingJobAsync(scheduler, jobKey);
|
|
||||||
|
|
||||||
// // 创建任务详情(添加禁止并发执行特性,避免顺序混乱)
|
|
||||||
// var jobDetail = JobBuilder.Create(jobConfig.JobType)
|
|
||||||
// .WithIdentity(jobKey)
|
|
||||||
// .WithDescription(jobConfig.Description)
|
|
||||||
// .DisallowConcurrentExecution() // 关键:禁止同一任务并发执行
|
|
||||||
// .Build();
|
|
||||||
|
|
||||||
// // 创建立触发器
|
|
||||||
// ITrigger trigger = isDependencyTrigger
|
|
||||||
// ? CreateDependencyTrigger(triggerKey, jobConfig.Description) // 依赖触发:立即执行
|
|
||||||
// : CreateScheduledTrigger(triggerKey, expression, jobConfig.Description); // 定时触发:按表达式执行
|
|
||||||
|
|
||||||
// // 调度任务
|
|
||||||
// await scheduler.ScheduleJob(jobDetail, trigger);
|
|
||||||
// Log.Information("【任务服务】启动任务成功 - 任务描述: {JobDescription}, 触发类型: {TriggerType}, 表达式: {Expression}",
|
|
||||||
// jobConfig.Description,
|
|
||||||
// isDependencyTrigger ? "依赖触发(立即执行)" : "定时触发",
|
|
||||||
// isDependencyTrigger ? "无" : expression);
|
|
||||||
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// Log.Error(ex, "【任务服务】启动任务失败 - 任务描述: {JobDescription}", jobConfig.Description);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 启动单次执行任务(保持原有逻辑不变)
|
|
||||||
// /// </summary>
|
|
||||||
// private async Task<bool> StartOneTimeJobAsync(string configKey)
|
|
||||||
// {
|
|
||||||
// if (!JobConfigs.TryGetValue(configKey, out var jobConfig))
|
|
||||||
// {
|
|
||||||
// Log.Error("【任务服务】找不到任务配置: {ConfigKey}", configKey);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var scheduler = await _schedulerFactory.GetScheduler();
|
|
||||||
// var jobKey = new JobKey(jobConfig.JobKey, DefaultJobGroup);
|
|
||||||
// var triggerKey = new TriggerKey(jobConfig.TriggerKey, DefaultJobGroup);
|
|
||||||
|
|
||||||
// await RemoveExistingJobAsync(scheduler, jobKey);
|
|
||||||
|
|
||||||
// var jobDetail = JobBuilder.Create(jobConfig.JobType)
|
|
||||||
// .WithIdentity(jobKey)
|
|
||||||
// .WithDescription(jobConfig.Description)
|
|
||||||
// .DisallowConcurrentExecution()
|
|
||||||
// .Build();
|
|
||||||
|
|
||||||
// var trigger = TriggerBuilder.Create()
|
|
||||||
// .WithIdentity(triggerKey)
|
|
||||||
// .WithDescription($"{jobConfig.Description} - 单次执行")
|
|
||||||
// .StartNow()
|
|
||||||
// .Build();
|
|
||||||
|
|
||||||
// await scheduler.ScheduleJob(jobDetail, trigger);
|
|
||||||
// Log.Information("【任务服务】启动单次任务成功 - 任务描述: {JobDescription}", jobConfig.Description);
|
|
||||||
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// Log.Error(ex, "【任务服务】启动单次任务失败 - 任务描述: {JobDescription}", jobConfig.Description);
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 创建「定时触发器」(按表达式执行,仅第一个任务使用)
|
|
||||||
// /// </summary>
|
|
||||||
// private ITrigger CreateScheduledTrigger(TriggerKey triggerKey, string expression, string jobDescription)
|
|
||||||
// {
|
|
||||||
// // Cron表达式格式
|
|
||||||
// if (CronExpression.IsValidExpression(expression))
|
|
||||||
// {
|
|
||||||
// return TriggerBuilder.Create()
|
|
||||||
// .WithIdentity(triggerKey)
|
|
||||||
// .WithDescription($"{jobDescription} - Cron调度")
|
|
||||||
// .WithCronSchedule(expression)
|
|
||||||
// .StartAt(DateTime.Now.AddSeconds(DefaultCronStartDelaySeconds))
|
|
||||||
// .Build();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 数字间隔格式(分钟)
|
|
||||||
// if (int.TryParse(expression, out int intervalMinutes))
|
|
||||||
// {
|
|
||||||
// intervalMinutes = Math.Max(1, intervalMinutes); // 最小间隔1分钟
|
|
||||||
// return TriggerBuilder.Create()
|
|
||||||
// .WithIdentity(triggerKey)
|
|
||||||
// .WithDescription($"{jobDescription} - 间隔{intervalMinutes}分钟调度")
|
|
||||||
// .StartAt(DateTime.Now.AddSeconds(DefaultSimpleStartDelaySeconds))
|
|
||||||
// .WithSimpleSchedule(x => x
|
|
||||||
// .WithIntervalInMinutes(intervalMinutes)
|
|
||||||
// .RepeatForever())
|
|
||||||
// .Build();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 无效表达式,使用默认配置
|
|
||||||
// Log.Warning("【任务服务】无效的任务表达式: {Expression},使用默认间隔{DefaultMinutes}分钟",
|
|
||||||
// expression, DefaultIntervalMinutes);
|
|
||||||
|
|
||||||
// return TriggerBuilder.Create()
|
|
||||||
// .WithIdentity(triggerKey)
|
|
||||||
// .WithDescription($"{jobDescription} - 默认间隔调度")
|
|
||||||
// .StartAt(DateTime.Now.AddSeconds(DefaultSimpleStartDelaySeconds))
|
|
||||||
// .WithSimpleSchedule(x => x
|
|
||||||
// .WithIntervalInMinutes(DefaultIntervalMinutes)
|
|
||||||
// .RepeatForever())
|
|
||||||
// .Build();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 创建「依赖触发器」(立即执行,仅执行一次)
|
|
||||||
// /// </summary>
|
|
||||||
// private ITrigger CreateDependencyTrigger(TriggerKey triggerKey, string jobDescription)
|
|
||||||
// {
|
|
||||||
// return TriggerBuilder.Create()
|
|
||||||
// .WithIdentity(triggerKey)
|
|
||||||
// .WithDescription($"{jobDescription} - 依赖触发(立即执行)")
|
|
||||||
// .StartNow() // 立即触发
|
|
||||||
// .Build();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /// <summary>
|
|
||||||
// /// 移除已存在的任务(保持原有逻辑不变)
|
|
||||||
// /// </summary>
|
|
||||||
// private async Task RemoveExistingJobAsync(IScheduler scheduler, JobKey jobKey)
|
|
||||||
// {
|
|
||||||
// if (await scheduler.CheckExists(jobKey))
|
|
||||||
// {
|
|
||||||
// Log.Information("【任务服务】移除已存在的任务: {JobKey}", jobKey);
|
|
||||||
// await scheduler.DeleteJob(jobKey);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
@@ -3,13 +3,8 @@ using dy.net.model.dto;
|
|||||||
using dy.net.model.entity;
|
using dy.net.model.entity;
|
||||||
using dy.net.repository;
|
using dy.net.repository;
|
||||||
using dy.net.utils;
|
using dy.net.utils;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace dy.net.service
|
namespace dy.net.service
|
||||||
{
|
{
|
||||||
@@ -382,7 +377,7 @@ namespace dy.net.service
|
|||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<List<VideoChartItemDto>> GetChartData(int day=7)
|
public async Task<List<VideoChartItemDto>> GetChartData(int day = 7)
|
||||||
{
|
{
|
||||||
|
|
||||||
var date = DateTime.Now.AddDays(-day);
|
var date = DateTime.Now.AddDays(-day);
|
||||||
@@ -517,7 +512,7 @@ namespace dy.net.service
|
|||||||
public async Task<bool> HandOldFolderVideos()
|
public async Task<bool> HandOldFolderVideos()
|
||||||
{
|
{
|
||||||
// 1. 查询目标数据
|
// 1. 查询目标数据
|
||||||
var list = await _dyCollectVideoRepository.GetListAsync(x=>x.ViedoType == VideoTypeEnum.dy_favorite || x.ViedoType == VideoTypeEnum.dy_collects );
|
var list = await _dyCollectVideoRepository.GetListAsync(x => x.ViedoType == VideoTypeEnum.dy_favorite || x.ViedoType == VideoTypeEnum.dy_collects);
|
||||||
// 缓存已处理的「Tag1+下一级文件夹」组合(避免重复移动)
|
// 缓存已处理的「Tag1+下一级文件夹」组合(避免重复移动)
|
||||||
var processedFolderPairs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
var processedFolderPairs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using ClockSnowFlake;
|
using System.Text;
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace dy.net.utils
|
namespace dy.net.utils
|
||||||
@@ -22,7 +20,7 @@ namespace dy.net.utils
|
|||||||
string result = string.Empty;
|
string result = string.Empty;
|
||||||
// 1. 空值处理:直接返回默认名
|
// 1. 空值处理:直接返回默认名
|
||||||
if (string.IsNullOrWhiteSpace(originalName))
|
if (string.IsNullOrWhiteSpace(originalName))
|
||||||
result= defaultName.Replace(" ","");
|
result = defaultName.Replace(" ", "");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 2. 过滤 Linux 非法字符:
|
// 2. 过滤 Linux 非法字符:
|
||||||
@@ -44,7 +42,7 @@ namespace dy.net.utils
|
|||||||
// 3. 计算 UTF-8 字节数,若未超 255 字节,直接返回
|
// 3. 计算 UTF-8 字节数,若未超 255 字节,直接返回
|
||||||
byte[] utf8Bytes = Encoding.UTF8.GetBytes(sanitizedName);
|
byte[] utf8Bytes = Encoding.UTF8.GetBytes(sanitizedName);
|
||||||
if (utf8Bytes.Length <= 100)
|
if (utf8Bytes.Length <= 100)
|
||||||
result= sanitizedName.Replace(" ", "");
|
result = sanitizedName.Replace(" ", "");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 4. 超过 255 字节,截取前 255 字节(避免破坏 UTF-8 字符)
|
// 4. 超过 255 字节,截取前 255 字节(避免破坏 UTF-8 字符)
|
||||||
@@ -55,14 +53,14 @@ namespace dy.net.utils
|
|||||||
string truncatedName = Encoding.UTF8.GetString(truncatedBytes).TrimEnd('\0').Replace(" ", ""); // 移除可能的空字符
|
string truncatedName = Encoding.UTF8.GetString(truncatedBytes).TrimEnd('\0').Replace(" ", ""); // 移除可能的空字符
|
||||||
|
|
||||||
// 6. 极端情况:截取后为空(如全是非法字符替换后无有效内容),返回默认名
|
// 6. 极端情况:截取后为空(如全是非法字符替换后无有效内容),返回默认名
|
||||||
result= string.IsNullOrWhiteSpace(truncatedName) ? defaultName : truncatedName;
|
result = string.IsNullOrWhiteSpace(truncatedName) ? defaultName : truncatedName;
|
||||||
}
|
}
|
||||||
if (isfolder)
|
if (isfolder)
|
||||||
{
|
{
|
||||||
result = KeepChineseLettersAndNumbers(result);
|
result = KeepChineseLettersAndNumbers(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using dy.net.model.dto;
|
using dy.net.model.dto;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace dy.net.utils
|
namespace dy.net.utils
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
using dy.net.model.dto;
|
using dy.net.model.dto;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace dy.net.utils
|
namespace dy.net.utils
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="logDirectory">日志文件所在目录</param>
|
/// <param name="logDirectory">日志文件所在目录</param>
|
||||||
/// <param name="n">清除N天之前的日志文件</param>
|
/// <param name="n">清除N天之前的日志文件</param>
|
||||||
public static void CleanOldLogFiles(string logDirectory,int n)
|
public static void CleanOldLogFiles(string logDirectory, int n)
|
||||||
{
|
{
|
||||||
// 计算n天前的时间点
|
// 计算n天前的时间点
|
||||||
DateTime threeDaysAgo = DateTime.Now.AddDays(-n);
|
DateTime threeDaysAgo = DateTime.Now.AddDays(-n);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using dy.net.model.dto;
|
using dy.net.model.dto;
|
||||||
using dy.net.model.entity;
|
using dy.net.model.entity;
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
@@ -19,7 +18,7 @@ namespace dy.net.utils
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="video">视频信息</param>
|
/// <param name="video">视频信息</param>
|
||||||
/// <returns>一个表示异步操作的任务</returns>
|
/// <returns>一个表示异步操作的任务</returns>
|
||||||
public static void GenerateVideoNfoFile(DouyinVideo video)
|
public static void GenerateVideoNfoFile(DouyinVideo video)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -39,7 +38,7 @@ namespace dy.net.utils
|
|||||||
{
|
{
|
||||||
var fileExt = Path.GetExtension(video.AuthorAvatar);
|
var fileExt = Path.GetExtension(video.AuthorAvatar);
|
||||||
var actorsDir = Path.Combine(videoDirectory, ".actors");
|
var actorsDir = Path.Combine(videoDirectory, ".actors");
|
||||||
if(!Directory.Exists(actorsDir))
|
if (!Directory.Exists(actorsDir))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(actorsDir);
|
Directory.CreateDirectory(actorsDir);
|
||||||
}
|
}
|
||||||
@@ -55,7 +54,7 @@ namespace dy.net.utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var nfoInfo= new DouyinVideoNfo
|
var nfoInfo = new DouyinVideoNfo
|
||||||
{
|
{
|
||||||
Actors = new List<Actor>
|
Actors = new List<Actor>
|
||||||
{
|
{
|
||||||
@@ -90,7 +89,7 @@ namespace dy.net.utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateNfoFile(DouyinVideoNfo videoInfo, string filePath,string xmlRoot= "movie")
|
private static void GenerateNfoFile(DouyinVideoNfo videoInfo, string filePath, string xmlRoot = "movie")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -143,7 +142,7 @@ namespace dy.net.utils
|
|||||||
if (!string.IsNullOrWhiteSpace(actor.Role))
|
if (!string.IsNullOrWhiteSpace(actor.Role))
|
||||||
actorElement.Add(new XElement("role", CleanInvalidXmlChars(actor.Role)));
|
actorElement.Add(new XElement("role", CleanInvalidXmlChars(actor.Role)));
|
||||||
|
|
||||||
actorElement.Add(new XElement("tmdbid", ""));
|
actorElement.Add(new XElement("tmdbid", ""));
|
||||||
|
|
||||||
root.Add(actorElement);
|
root.Add(actorElement);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace dy.net.utils
|
|||||||
return placeholderMap.TryGetValue(placeholderKey, out var value) ? value : match.Value;
|
return placeholderMap.TryGetValue(placeholderKey, out var value) ? value : match.Value;
|
||||||
});
|
});
|
||||||
|
|
||||||
var fullName= finalTitle.Replace("--","-");
|
var fullName = finalTitle.Replace("--", "-");
|
||||||
|
|
||||||
if (fullName.Length > 60)
|
if (fullName.Length > 60)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user