using dy.net.model.dto; using dy.net.service; using dy.net.storage; using jzc.http.lib; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace dy.net.Controllers { [Route("api/[controller]")] [ApiController] [Authorize] public class StorageController : ControllerBase { private readonly DouyinCommonService _commonService; private readonly OpenListSettingsService _openListSettingsService; private readonly OpenListMediaStorage _openListStorage; private readonly DouyinQuartzJobService _quartzJobService; private readonly DouyinVideoService _videoService; public StorageController( DouyinCommonService commonService, OpenListSettingsService openListSettingsService, OpenListMediaStorage openListStorage, DouyinQuartzJobService quartzJobService, DouyinVideoService videoService) { _commonService = commonService; _openListSettingsService = openListSettingsService; _openListStorage = openListStorage; _quartzJobService = quartzJobService; _videoService = videoService; } [HttpGet("inventory")] public async Task GetInventory() { var type = _commonService.GetConfig()?.StorageType ?? StorageType.Local; return ApiResult.Success(await _videoService.GetStorageInventoryAsync(type)); } [HttpGet("config")] public async Task GetConfig() { var type = _commonService.GetConfig()?.StorageType ?? StorageType.Local; var inventory = await _videoService.GetStorageInventoryAsync(type); var saved = await _openListSettingsService.HasSavedSettingsAsync(); var dto = await _openListSettingsService.ToDtoAsync(type); dto.RequiresCutover = type == StorageType.WebDav || inventory.WebDavRecordCount > 0; dto.LegacyWebDavRecordCount = inventory.WebDavRecordCount; dto.SuggestedFromLegacy = !saved; return ApiResult.Success(dto); } [HttpPost("test")] public async Task Test( [FromBody] StorageTestRequest request, CancellationToken cancellationToken) { if (request == null) return ApiResult.Fail("测试请求不能为空"); if (request.StorageType != StorageType.OpenList) return ApiResult.Fail("新远端存储只支持 OpenList 原生 API。"); var candidate = await _openListSettingsService.BuildCandidateAsync( new OpenListTestRequest { Endpoint = request.Endpoint, BasePath = request.BasePath, LocalStagingPath = request.LocalStagingPath, SourcePath = request.SourcePath, UserName = request.UserName, Password = request.Password }); var result = await _openListStorage.ProbeAsync(candidate, cancellationToken); return result.Success ? ApiResult.Success(new { message = result.Message }) : ApiResult.Fail(result.Message); } [HttpPost("openlist/directories")] public async Task ListOpenListDirectories( [FromBody] OpenListDirectoryRequest request, CancellationToken cancellationToken) { if (request == null) return ApiResult.Fail("目录请求不能为空"); try { var candidate = await _openListSettingsService.BuildCandidateAsync(request); return ApiResult.Success(await _openListStorage.ListDirectoriesAsync( candidate, request.Path, cancellationToken)); } catch (Exception ex) when (ex is InvalidOperationException or HttpRequestException) { return ApiResult.Fail(ex.GetBaseException().Message); } } [HttpPut("config")] public async Task Update( [FromBody] StorageSettingsDto dto, CancellationToken cancellationToken) { if (dto == null) return ApiResult.Fail("配置不能为空"); if (dto.StorageType == StorageType.WebDav) return ApiResult.Fail("WebDAV 已停止作为新存储目标,请改用 OpenList 原生 API。"); if (dto.StorageType == StorageType.OpenList) { var candidate = await _openListSettingsService.BuildCandidateAsync( new OpenListTestRequest { Endpoint = dto.Endpoint, BasePath = dto.BasePath, LocalStagingPath = dto.LocalStagingPath, SourcePath = dto.SourcePath, UserName = dto.UserName, Password = dto.Password }); var result = await _openListStorage.ProbeAsync(candidate, cancellationToken); if (!result.Success) return ApiResult.Fail("无法启用 OpenList:" + result.Message); await _openListSettingsService.SaveAsync(candidate, true, result.Message); await _openListSettingsService.InitializeCookiePathsAsync(); var config = _commonService.GetConfig(); if (config == null) return ApiResult.Fail("系统配置不存在"); config.StorageType = dto.StorageType; if (!await _commonService.UpdateConfig(config)) return ApiResult.Fail("存储模式保存失败"); await _quartzJobService.InitOrReStartAllJobs(config.Cron.ToString()); var response = await _openListSettingsService.ToDtoAsync(config.StorageType); var inventory = await _videoService.GetStorageInventoryAsync(config.StorageType); response.RequiresCutover = inventory.WebDavRecordCount > 0; response.LegacyWebDavRecordCount = inventory.WebDavRecordCount; return ApiResult.Success(response); } if (dto.StorageType == StorageType.Local) { var config = _commonService.GetConfig(); if (config == null) return ApiResult.Fail("系统配置不存在"); config.StorageType = StorageType.Local; if (!await _commonService.UpdateConfig(config)) return ApiResult.Fail("存储模式保存失败"); await _quartzJobService.InitOrReStartAllJobs(config.Cron.ToString()); var response = await _openListSettingsService.ToDtoAsync(config.StorageType); var inventory = await _videoService.GetStorageInventoryAsync(config.StorageType); response.RequiresCutover = inventory.WebDavRecordCount > 0; response.LegacyWebDavRecordCount = inventory.WebDavRecordCount; return ApiResult.Success(response); } return ApiResult.Fail("不支持的存储类型"); } } }