Files
douyin/Controllers/FollowController.cs

272 lines
10 KiB
C#

using dy.net.model.dto;
using dy.net.model.entity;
using dy.net.service;
using dy.net.utils;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Serilog;
namespace dy.net.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class FollowController : ControllerBase
{
private readonly DouyinFollowService _douyinFollowService;
private readonly DouyinQuartzJobService _douyinQuartzJobService;
private readonly DouyinUserLookupService _douyinUserLookupService;
private readonly DouyinLiveStatusService _douyinLiveStatusService;
public FollowController(
DouyinFollowService douyinFollowService,
DouyinQuartzJobService douyinQuartzJobService,
DouyinUserLookupService douyinUserLookupService,
DouyinLiveStatusService douyinLiveStatusService)
{
this._douyinFollowService = douyinFollowService;
_douyinQuartzJobService = douyinQuartzJobService;
_douyinUserLookupService = douyinUserLookupService;
_douyinLiveStatusService = douyinLiveStatusService;
}
/// <summary>
/// 分页查询
/// </summary>
/// <returns>分页结果</returns>
[HttpPost("paged")]
public async Task<IActionResult> GetPagedAsync(
FollowRequestDto dto)
{
if (string.IsNullOrWhiteSpace(dto.MySelfId))
{
return ApiResult.Success(new { });
}
var (list, totalCount) = await _douyinFollowService.GetPagedAsync(dto);
return ApiResult.Success(new
{
data = list,
total = totalCount,
pageIndex = dto.PageIndex,
pageSize = dto.PageSize
});
}
/// <summary>
/// 重新同步-单次
/// </summary>
/// <returns></returns>
[HttpGet("sync")]
public async Task<IActionResult> SyncFollowList()
{
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");
}
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>
/// 修改关注同步状态
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost("openOrCloseSync")]
public async Task<IActionResult> OpenOrCloseSync(FollowUpdateDto dto)
{
if (dto.OpenSync)
{
if (!string.IsNullOrWhiteSpace(dto.SavePath))
{
if (!DouyinFileNameHelper.IsValidWithoutSpecialChars(dto.SavePath))
{
return ApiResult.Fail("请输入有效文件夹名称(字母数字中文简体)");
}
if (dto.SavePath.Length > 20)
{
return ApiResult.Fail("请输入有效文件夹名称(最长20)");
}
}
}
var result = await _douyinFollowService.OpenOrCloseSync(dto);
return ApiResult.SuccOrFail(result, result);
}
/// <summary>
/// 修改关注全量同步状态
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost("openOrCloseFullSync")]
public async Task<IActionResult> OpenOrCloseFullSync(FollowUpdateDto dto)
{
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>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost("delete")]
public async Task<IActionResult> DeleteFollow(FollowUpdateDto dto)
{
var result = await _douyinFollowService.DeleteFollow(dto);
return ApiResult.SuccOrFail(result, result);
}
}
}