feat: add fnOS packaging, storage workflows and release pipeline
This commit is contained in:
@@ -4,6 +4,7 @@ using dy.net.service;
|
||||
using dy.net.utils;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Serilog;
|
||||
|
||||
namespace dy.net.Controllers
|
||||
{
|
||||
@@ -14,11 +15,19 @@ namespace dy.net.Controllers
|
||||
{
|
||||
private readonly DouyinFollowService _douyinFollowService;
|
||||
private readonly DouyinQuartzJobService _douyinQuartzJobService;
|
||||
private readonly DouyinUserLookupService _douyinUserLookupService;
|
||||
private readonly DouyinLiveStatusService _douyinLiveStatusService;
|
||||
|
||||
public FollowController(DouyinFollowService douyinFollowService, DouyinQuartzJobService douyinQuartzJobService)
|
||||
public FollowController(
|
||||
DouyinFollowService douyinFollowService,
|
||||
DouyinQuartzJobService douyinQuartzJobService,
|
||||
DouyinUserLookupService douyinUserLookupService,
|
||||
DouyinLiveStatusService douyinLiveStatusService)
|
||||
{
|
||||
this._douyinFollowService = douyinFollowService;
|
||||
_douyinQuartzJobService = douyinQuartzJobService;
|
||||
_douyinUserLookupService = douyinUserLookupService;
|
||||
_douyinLiveStatusService = douyinLiveStatusService;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,20 +61,107 @@ namespace dy.net.Controllers
|
||||
[HttpGet("sync")]
|
||||
public async Task<IActionResult> SyncFollowList()
|
||||
{
|
||||
//后台异步
|
||||
_douyinQuartzJobService.StartFollowJobOnceAsync();
|
||||
await Task.Delay(1000);
|
||||
return ApiResult.Success();
|
||||
try
|
||||
{
|
||||
var started = await _douyinQuartzJobService.StartFollowJobOnceAsync();
|
||||
return started
|
||||
? ApiResult.Success(new { message = "关注列表更新任务已启动" })
|
||||
: ApiResult.Fail("关注列表更新任务启动失败,请查看错误日志。");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "手动启动关注列表更新任务失败");
|
||||
return ApiResult.Fail("关注列表更新任务启动失败:" + ex.GetBaseException().Message);
|
||||
}
|
||||
}
|
||||
[HttpPost("add")]
|
||||
public async Task<IActionResult> AddFollow(DouyinFollowed followed)
|
||||
{
|
||||
if (followed == null)
|
||||
{
|
||||
return ApiResult.Fail("新增信息不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(followed.mySelfId))
|
||||
{
|
||||
return ApiResult.Fail("请先配置抖音授权信息,抖音授权配置里面填写你的uid");
|
||||
}
|
||||
var res = await _douyinFollowService.AddAsync(followed);
|
||||
return ApiResult.SuccOrFail(res, "", res ? "" : "添加失败,或者已存在相同secuid和uid");
|
||||
if (string.IsNullOrWhiteSpace(followed.SecUid))
|
||||
{
|
||||
return ApiResult.Fail("博主 SecUid 不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(followed.UperId))
|
||||
{
|
||||
return ApiResult.Fail("博主 UID 不能为空");
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(followed.UperName))
|
||||
{
|
||||
return ApiResult.Fail("博主姓名不能为空");
|
||||
}
|
||||
|
||||
followed.mySelfId = followed.mySelfId.Trim();
|
||||
followed.SecUid = followed.SecUid.Trim();
|
||||
followed.UperId = followed.UperId.Trim();
|
||||
followed.UperName = followed.UperName.Trim();
|
||||
followed.DouyinNo = followed.DouyinNo?.Trim();
|
||||
followed.SavePath = followed.SavePath?.Trim();
|
||||
followed.Signature = Limit(followed.Signature, 500);
|
||||
followed.UperAvatar = Limit(followed.UperAvatar, 1000);
|
||||
followed.Enterprise = Limit(followed.Enterprise, 200);
|
||||
followed.FullSync = followed.OpenSync && followed.FullSync;
|
||||
|
||||
if (followed.mySelfId.Length > 200 || followed.SecUid.Length > 500 ||
|
||||
followed.UperId.Length > 100 || followed.UperName.Length > 200)
|
||||
{
|
||||
return ApiResult.Fail("新增信息长度超出限制,请检查 UID、SecUid 和博主姓名");
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(followed.DouyinNo) && followed.DouyinNo.Length > 100)
|
||||
{
|
||||
return ApiResult.Fail("抖音号长度不能超过 100 个字符");
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(followed.SavePath))
|
||||
{
|
||||
if (followed.SavePath.Length > 20)
|
||||
{
|
||||
return ApiResult.Fail("保存文件夹名称最长 20 个字符");
|
||||
}
|
||||
if (!DouyinFileNameHelper.IsValidWithoutSpecialChars(followed.SavePath))
|
||||
{
|
||||
return ApiResult.Fail("保存文件夹名称只能包含字母、数字或中文");
|
||||
}
|
||||
}
|
||||
|
||||
var result = await _douyinFollowService.TryAddAsync(followed);
|
||||
return result switch
|
||||
{
|
||||
AddFollowResult.Added => ApiResult.Success("新增非关注博主成功"),
|
||||
AddFollowResult.AlreadyExists => ApiResult.Fail("该博主已存在,无需重复添加"),
|
||||
_ => ApiResult.Fail("添加失败,请稍后重试")
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用展示在抖音资料页上的抖音号查找博主。结果需要用户确认后再调用 add。
|
||||
/// </summary>
|
||||
[HttpPost("resolve-by-douyin-no")]
|
||||
public async Task<IActionResult> ResolveByDouyinNo(
|
||||
DouyinFollowLookupRequest request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _douyinUserLookupService.ResolveAsync(request, cancellationToken);
|
||||
return ApiResult.Success(result);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
return ApiResult.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static string Limit(string value, int maxLength)
|
||||
{
|
||||
value = value?.Trim();
|
||||
return value != null && value.Length > maxLength ? value[..maxLength] : value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -107,6 +203,59 @@ namespace dy.net.Controllers
|
||||
return await OpenOrCloseSync(dto);
|
||||
}
|
||||
|
||||
[HttpPost("live-monitor")]
|
||||
public async Task<IActionResult> UpdateLiveMonitor(
|
||||
FollowLiveMonitorUpdateDto dto,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ApiResult.Success(await _douyinLiveStatusService.SetMonitorAsync(dto, cancellationToken));
|
||||
}
|
||||
catch (Exception ex) when (ex is InvalidOperationException or KeyNotFoundException)
|
||||
{
|
||||
return ApiResult.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("live-status/refresh")]
|
||||
public async Task<IActionResult> RefreshLiveStatus(
|
||||
FollowLiveStatusRefreshDto dto,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dto == null || string.IsNullOrWhiteSpace(dto.Id))
|
||||
return ApiResult.Fail("博主记录不能为空");
|
||||
return ApiResult.Success(await _douyinLiveStatusService.RefreshAsync(dto.Id, cancellationToken));
|
||||
}
|
||||
catch (Exception ex) when (ex is InvalidOperationException or KeyNotFoundException)
|
||||
{
|
||||
return ApiResult.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("live-status/query")]
|
||||
public async Task<IActionResult> QueryLiveStatus(FollowLiveStatusQueryDto dto)
|
||||
{
|
||||
if (dto?.Ids == null || dto.Ids.Count == 0)
|
||||
return ApiResult.Success(Array.Empty<FollowLiveStatusDto>());
|
||||
return ApiResult.Success(await _douyinLiveStatusService.QueryAsync(dto.Ids));
|
||||
}
|
||||
|
||||
[HttpPost("live-email")]
|
||||
public async Task<IActionResult> UpdateLiveEmail(FollowLiveEmailUpdateDto dto)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ApiResult.Success(await _douyinLiveStatusService.SetEmailNotificationAsync(dto));
|
||||
}
|
||||
catch (Exception ex) when (ex is InvalidOperationException or KeyNotFoundException)
|
||||
{
|
||||
return ApiResult.Fail(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除关注对象
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user