using ClockSnowFlake;
using dy.net.extension;
using dy.net.model.dto;
using dy.net.model.entity;
using dy.net.service;
using dy.net.utils;
using dy.sync.lib;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace dy.net.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ConfigController : ControllerBase
{
private readonly DouyinCookieService dyCookieService;
private readonly DouyinCommonService commonService;
private readonly DouyinQuartzJobService quartzJobService;
private readonly DouyinFollowService douyinFollowService;
private readonly DouyinCookieService douyinCookieService;
private readonly DouyinHttpClientService httpClientService;
public ConfigController(DouyinCookieService dyCookieService, DouyinCommonService commonService, DouyinQuartzJobService quartzJobService, DouyinFollowService douyinFollowService, DouyinCookieService douyinCookieService, DouyinHttpClientService httpClientService)
{
this.dyCookieService = dyCookieService;
this.commonService = commonService;
this.quartzJobService = quartzJobService;
this.douyinFollowService = douyinFollowService;
this.douyinCookieService = douyinCookieService;
this.httpClientService = httpClientService;
}
///
/// 导出配置
///
///
[HttpGet("exportConf")]
public async Task ExportConf()
{
// 1. 组装导出数据
var dto = new AppConfigImportDto()
{
follows = await douyinFollowService.GetHandFollows(),
conf = commonService.GetConfig(),
cookies = await douyinCookieService.GetAllAsync()
};
return ApiResult.Success(dto);
}
[HttpPost("importConf")]
public async Task ImportConf(AppConfigImportDto dto)
{
if (dto == null)
return ApiResult.Fail("json数据为空");
await HandleFollowsImport(dto.follows);
await HandleConfigImport(dto.conf);
await HandleCookiesImport(dto.cookies);
return ApiResult.Success();
}
private async Task HandleFollowsImport(List 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 cookies)
{
if (cookies?.Count > 0)
{
var imported = await douyinCookieService.ImportCookies(cookies);
if (imported)
Serilog.Log.Debug("抖音Cookie配置导入成功");
}
}
///
/// 分页查询
///
/// 分页结果
[HttpPost("paged")]
public async Task GetPagedAsync(
PageRequestDto dto)
{
var (list, totalCount) = await dyCookieService.GetPagedAsync(dto.PageIndex, dto.PageSize);
return ApiResult.Success(new
{
data = list,
total = totalCount,
pageIndex = dto.PageIndex,
pageSize = dto.PageSize
});
}
///
/// 查询所有用户Cookie
///
///
[HttpGet("list")]
public async Task GetAllList()
{
var follows = await douyinFollowService.GetGroupByCookieAsync();
return ApiResult.Success(follows);
}
///
/// 是否已经初始化了
///
///
[HttpGet("isInit")]
[AllowAnonymous]
public async Task IsInit()
{
var init = await dyCookieService.IsInit();
return ApiResult.Success(init);
}
///
/// 新增用户Cookie
///
[HttpPost("add")]
public async Task AddAsync([FromBody] DouyinCookie dyUserCookies)
{
var checkCk = await httpClientService.CheckCookie(dyUserCookies);
if (!checkCk)
{
return ApiResult.Fail("Cookie无效,请按照文档提示重新获取有效Cookie,不要使用插件获取cookie");
}
var result = await dyCookieService.Add(dyUserCookies);
if (result)
{
ReStartJob();
return ApiResult.Success();
}
return ApiResult.Fail("添加失败");
}
///
/// 非docker初始化
///
[HttpPost("deskinit")]
[AllowAnonymous]
public async Task DeskInitAsync([FromBody] DouyinCookie dyUserCookies)
{
// 1. 基础赋值
dyUserCookies.Id = IdGener.GetLong().ToString();
// 2. 路径权限校验
var pathValidationResult = ValidatePaths(dyUserCookies);
if (!pathValidationResult.Success)
return ApiResult.Fail(pathValidationResult.Message);
// 3. Cookie 有效性校验
var cookieValid = await httpClientService.CheckCookie(dyUserCookies);
if (!cookieValid)
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
{
{ "收藏存储路径", 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})");
}
}
}
if (string.IsNullOrWhiteSpace(cookie.SavePath))
{
return (false, "收藏存储路径不能为空");
}
return (true, string.Empty);
}
///
/// 快速开启或停止
///
[HttpPost("switch")]
public async Task SwitchAsync([FromBody] DouyinCookieSwitchDto dto)
{
var result = await dyCookieService.Switch(dto);
if (result)
{
ReStartJob();
return ApiResult.Success();
}
return ApiResult.Fail("添加失败");
}
///
/// 更新用户Cookie
///
[HttpPost("update")]
public async Task UpdateAsync([FromBody] DouyinCookie dyUserCookies)
{
var checkCk = await httpClientService.CheckCookie(dyUserCookies);
if (!checkCk)
{
return ApiResult.Fail("Cookie无效,请按照文档提示重新获取有效Cookie,不要使用插件获取cookie");
}
if (dyUserCookies.Id == "0")
{
dyUserCookies.Id = IdGener.GetLong().ToString();
var result = await dyCookieService.Add(dyUserCookies);
if (result)
{
ReStartJob();
return ApiResult.Success();
}
return ApiResult.Fail("添加失败");
}
else
{
var result = await dyCookieService.UpdateCookieAsync(dyUserCookies);
if (result)
{
ReStartJob();
return ApiResult.Success();
}
return ApiResult.Fail("更新失败");
}
}
///
/// 批量删除用户Cookie
///
[HttpGet("delete")]
public async Task DeleteAsync(string id)
{
var count = await dyCookieService.DeleteByIdsAsync(new List { id });
if (count > 0)
{
ReStartJob();
}
return ApiResult.Success(count);
}
[HttpGet("GetConfig")]
public IActionResult GetConfig()
{
var data = commonService.GetConfig();
return ApiResult.Success(data);
}
[HttpPost("UpdateConfig")]
public async Task UpdateConfig(AppConfig config)
{
var update = await commonService.UpdateConfig(config);
if (update)
{
if (config.OnlySyncNew)
{
Serilog.Log.Debug("仅同步新视频配置已生效,后续所有类型的视频同步将只会读取最近一页约20条数据");
}
ReStartJob();
}
return ApiResult.Success(update);
}
///
///
///
///
[HttpGet("ExecuteJobNow")]
//[Authorize]
public async Task ExecuteJobNow()
{
var config = commonService.GetConfig();
if (config != null)
await quartzJobService.InitOrReStartAllJobs(config.Cron.ToString());
return ApiResult.Success();
}
private void ReStartJob()
{
var config = commonService.GetConfig();
if (config != null)
quartzJobService.InitOrReStartAllJobs(config.Cron.ToString());
//避免前端等待
}
///
/// 镜像标签
///
///
[HttpGet("mytag")]
public async Task GetMyTag()
{
var deploy = Appsettings.Get("deploy");
var tag = Appsettings.Get("tagName");
tag = deploy == "fn" ? "fn_" + Appsettings.Get("fnVersion") : tag;
deploy = deploy == "fn" ? "fnos" : "docker";
return ApiResult.Success(new { tag, deploy });
}
[AllowAnonymous]
[HttpGet("checktag")]
public async Task CheckTag()
{
var deploy = Appsettings.Get("deploy");
if (string.IsNullOrWhiteSpace(deploy))
{
return await GetDockerTagVersions();
}
else
{
if (deploy == "fn")//飞牛
{
return ApiResult.Success(new List { "fn_" + Appsettings.Get("fnVersion") });
}
else
{
return await GetDockerTagVersions();
}
}
}
private static async Task GetDockerTagVersions()
{
var data = await DouyinHttpHelper.GetTenImage(Appsettings.Get("tagName"));
if (data.IsSuccessStatusCode)
{
var content = await data.Content.ReadAsStringAsync();
var tagData = JsonConvert.DeserializeObject>>(content);
if (tagData != null && tagData.Data != null && tagData.Data.Count > 0)
return ApiResult.Success(tagData.Data);
return ApiResult.Fail();
}
else
{
return ApiResult.Fail("请求失败");
}
}
///
/// 查询mp3目录下有没有音频文件
///
///
[HttpGet("mp3List")]
public async Task GetExistMps()
{
var path = Path.Combine(AppContext.BaseDirectory, "mp3");
if (!string.IsNullOrWhiteSpace(ServiceExtension.FnDataFolder))
{
path = ServiceExtension.FnDataFolder;
}
if (Directory.Exists(path))
{
var allowedExtensions = new HashSet { ".mp3", ".wav" };
var customMusics = Directory.GetFiles(path)
.Where(filePath =>
allowedExtensions.Contains(Path.GetExtension(filePath).ToLowerInvariant()) &&
Path.GetFileNameWithoutExtension(filePath) != "silent_10")
.ToList();
var fileNames = customMusics.Select(f => new { filename = Path.GetFileName(f) }).Where(x => x.filename != "silent_10.mp3").ToList();
return ApiResult.Success(fileNames);
}
else
{
return ApiResult.Fail("没有找到默认音频文件");
}
}
///
/// 播放音频流
///
///
///
[AllowAnonymous]
[HttpGet("getmp3")]
public async Task GetMp3([FromQuery] string name)
{
var path = Path.Combine(AppContext.BaseDirectory, "mp3", name);
if (!string.IsNullOrWhiteSpace(ServiceExtension.FnDataFolder))
{
path = Path.Combine(ServiceExtension.FnDataFolder, name);
}
if (System.IO.File.Exists(path))
{
//返回mp3文件流
var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
return new FileStreamResult(fileStream, "audio/mpeg")
{
FileDownloadName = name
};
}
else
{
return ApiResult.Fail("文件不存在");
}
}
}
}