feat: add fnOS packaging, storage workflows and release pipeline
This commit is contained in:
@@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using dy.net.storage;
|
||||
|
||||
namespace dy.net.Controllers
|
||||
{
|
||||
@@ -25,10 +26,12 @@ namespace dy.net.Controllers
|
||||
private readonly DouyinFollowService douyinFollowService;
|
||||
private readonly DouyinCookieService douyinCookieService;
|
||||
private readonly DouyinHttpClientService httpClientService;
|
||||
private readonly WebDavSettingsService _webDavSettingsService;
|
||||
private readonly VideoTaskService _videoTaskService;
|
||||
|
||||
|
||||
|
||||
public ConfigController(DouyinCookieService dyCookieService, DouyinCommonService commonService, DouyinQuartzJobService quartzJobService, DouyinFollowService douyinFollowService, DouyinCookieService douyinCookieService, DouyinHttpClientService httpClientService)
|
||||
public ConfigController(DouyinCookieService dyCookieService, DouyinCommonService commonService, DouyinQuartzJobService quartzJobService, DouyinFollowService douyinFollowService, DouyinCookieService douyinCookieService, DouyinHttpClientService httpClientService, WebDavSettingsService webDavSettingsService, VideoTaskService videoTaskService)
|
||||
{
|
||||
this.dyCookieService = dyCookieService;
|
||||
this.commonService = commonService;
|
||||
@@ -36,6 +39,8 @@ namespace dy.net.Controllers
|
||||
this.douyinFollowService = douyinFollowService;
|
||||
this.douyinCookieService = douyinCookieService;
|
||||
this.httpClientService = httpClientService;
|
||||
_webDavSettingsService = webDavSettingsService;
|
||||
_videoTaskService = videoTaskService;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,6 +107,11 @@ namespace dy.net.Controllers
|
||||
{
|
||||
if (cookies?.Count > 0)
|
||||
{
|
||||
foreach (var cookie in cookies) ClearImportedSourceHealth(cookie);
|
||||
if (commonService.GetConfig()?.StorageType.IsRemote() == true)
|
||||
{
|
||||
foreach (var cookie in cookies) _webDavSettingsService.ApplyDefaultCookiePaths(cookie);
|
||||
}
|
||||
var imported = await douyinCookieService.ImportCookies(cookies);
|
||||
if (imported)
|
||||
Serilog.Log.Debug("抖音Cookie配置导入成功");
|
||||
@@ -164,6 +174,12 @@ namespace dy.net.Controllers
|
||||
if (!cookieValid)
|
||||
return ApiResult.Fail("Cookie无效或已过期,请按照文档提示重新获取有效Cookie,不要使用插件获取cookie");
|
||||
var result = await dyCookieService.FastResetCookie(dto.id, dto.cookie);
|
||||
if (result)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(dto.id)) await _videoTaskService.ResetSourceHealthAsync(dto.id);
|
||||
else
|
||||
foreach (var item in await dyCookieService.GetAllAsync()) await _videoTaskService.ResetSourceHealthAsync(item.Id);
|
||||
}
|
||||
|
||||
return result ? ApiResult.Success() : ApiResult.Fail("cookie设置失败");
|
||||
}
|
||||
@@ -193,8 +209,12 @@ namespace dy.net.Controllers
|
||||
// 1. 基础赋值
|
||||
dyUserCookies.Id = IdGener.GetLong().ToString();
|
||||
|
||||
var storageType = commonService.GetConfig()?.StorageType ?? StorageType.Local;
|
||||
if (storageType.IsRemote())
|
||||
_webDavSettingsService.ApplyDefaultCookiePaths(dyUserCookies);
|
||||
|
||||
// 2. 路径权限校验
|
||||
var (Success, Message) = ValidatePaths(dyUserCookies);
|
||||
var (Success, Message) = ValidatePaths(dyUserCookies, storageType);
|
||||
if (!Success)
|
||||
return ApiResult.Fail(Message);
|
||||
|
||||
@@ -212,8 +232,28 @@ namespace dy.net.Controllers
|
||||
return saved ? ApiResult.Success() : ApiResult.Fail("添加失败");
|
||||
}
|
||||
|
||||
private static (bool Success, string Message) ValidatePaths(DouyinCookie cookie)
|
||||
private static (bool Success, string Message) ValidatePaths(DouyinCookie cookie, StorageType storageType)
|
||||
{
|
||||
if (storageType.IsRemote())
|
||||
{
|
||||
var remotePaths = new Dictionary<string, string>
|
||||
{
|
||||
{ "收藏 OpenList 相对路径", cookie.WebDavCollectPath },
|
||||
{ "喜欢 OpenList 相对路径", cookie.WebDavFavoritePath },
|
||||
{ "关注 OpenList 相对路径", cookie.WebDavFollowPath },
|
||||
{ "合集 OpenList 相对路径", cookie.WebDavMixPath },
|
||||
{ "短剧 OpenList 相对路径", cookie.WebDavSeriesPath }
|
||||
};
|
||||
|
||||
foreach (var (label, path) in remotePaths)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path)) return (false, $"{label}不能为空");
|
||||
try { StoragePath.NormalizeRemote(path); }
|
||||
catch (ArgumentException ex) { return (false, $"{label}无效:{ex.Message}"); }
|
||||
}
|
||||
return (true, string.Empty);
|
||||
}
|
||||
|
||||
var pathsToCheck = new Dictionary<string, string>
|
||||
{
|
||||
{ "收藏存储路径", cookie.SavePath },
|
||||
@@ -262,6 +302,19 @@ namespace dy.net.Controllers
|
||||
[HttpPost("update")]
|
||||
public async Task<IActionResult> AddOrUpdateAsync([FromBody] DouyinCookie dyUserCookies)
|
||||
{
|
||||
if (dyUserCookies == null) return ApiResult.Fail("配置不能为空");
|
||||
|
||||
var isNewCookie = string.IsNullOrWhiteSpace(dyUserCookies.Id) || dyUserCookies.Id == "0";
|
||||
var storageType = commonService.GetConfig()?.StorageType ?? StorageType.Local;
|
||||
if (storageType.IsRemote())
|
||||
{
|
||||
if (isNewCookie)
|
||||
dyUserCookies.Id = IdGener.GetLong().ToString();
|
||||
_webDavSettingsService.ApplyDefaultCookiePaths(dyUserCookies);
|
||||
var (success, message) = ValidatePaths(dyUserCookies, storageType);
|
||||
if (!success) return ApiResult.Fail(message);
|
||||
}
|
||||
|
||||
RemoveCookieLineString(dyUserCookies);
|
||||
|
||||
var checkCk = await httpClientService.CheckCookie(dyUserCookies);
|
||||
@@ -271,9 +324,10 @@ namespace dy.net.Controllers
|
||||
}
|
||||
dyUserCookies.StatusCode = 0;
|
||||
dyUserCookies.StatusMsg = "正常";
|
||||
if (dyUserCookies.Id == "0")
|
||||
if (isNewCookie)
|
||||
{
|
||||
dyUserCookies.Id = IdGener.GetLong().ToString();
|
||||
if (string.IsNullOrWhiteSpace(dyUserCookies.Id) || dyUserCookies.Id == "0")
|
||||
dyUserCookies.Id = IdGener.GetLong().ToString();
|
||||
var result = await dyCookieService.Add(dyUserCookies);
|
||||
if (result)
|
||||
{
|
||||
@@ -287,6 +341,7 @@ namespace dy.net.Controllers
|
||||
var result = await dyCookieService.UpdateCookieAsync(dyUserCookies);
|
||||
if (result)
|
||||
{
|
||||
await _videoTaskService.ResetSourceHealthAsync(dyUserCookies.Id);
|
||||
ReStartJob();
|
||||
return ApiResult.Success();
|
||||
}
|
||||
@@ -305,6 +360,18 @@ namespace dy.net.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
private static void ClearImportedSourceHealth(DouyinCookie cookie)
|
||||
{
|
||||
cookie.ConsecutiveSourceForbidden = 0;
|
||||
cookie.SourceCooldownUntil = null;
|
||||
cookie.SourceRequiresAuthorization = false;
|
||||
cookie.SourceProbePending = false;
|
||||
cookie.SourceProbeInProgress = false;
|
||||
cookie.LastSourceStatusCode = null;
|
||||
cookie.LastSourceError = null;
|
||||
cookie.SourceHealthUpdatedAt = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量删除用户Cookie
|
||||
/// </summary>
|
||||
@@ -351,10 +418,15 @@ namespace dy.net.Controllers
|
||||
//[Authorize]
|
||||
public async Task<IActionResult> ExecuteJobNow()
|
||||
{
|
||||
var config = commonService.GetConfig();
|
||||
if (config != null)
|
||||
await quartzJobService.InitOrReStartAllJobs(config.Cron.ToString());
|
||||
return ApiResult.Success();
|
||||
try
|
||||
{
|
||||
var tasks = await quartzJobService.TriggerVideoJobsNowAsync();
|
||||
return ApiResult.Success(new { taskIds = tasks.Select(x => x.Id).ToList(), count = tasks.Count });
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
return ApiResult.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user