lq1405 3470ce9229 v 1.1.5
修改轮询请求逻辑 添加imageUrls属性,通过第三方生成
修改 mj fetch,不转发API 而是用系统的数据
2025-06-21 22:22:54 +08:00

191 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using LMS.Common.Extensions;
using LMS.DAO;
using LMS.Repository.DB;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace LMS.Tools.MJPackage
{
public class TaskService(ITokenService tokenService, ILogger<TaskService> logger, ApplicationDbContext dbContext, ITaskConcurrencyManager taskConcurrencyManager) : ITaskService
{
private readonly ITokenService _tokenService = tokenService;
private readonly ILogger<TaskService> _logger = logger;
private readonly ApplicationDbContext _dbContext = dbContext;
private readonly ITaskConcurrencyManager _taskConcurrencyManager = taskConcurrencyManager;
public async Task<Dictionary<string, object>?> FetchTaskAsync(MJApiTasks mJApiTasks)
{
try
{
// 获取UseToken先尝试 Token再尝试 TokenId
var tokenConfig = await _tokenService.GetTokenAsync(mJApiTasks.Token);
string useToken = string.Empty;
if (tokenConfig == null)
{
// Token 没找到 尝试用 TokenId 查找
MJApiTokens? mJApiTokens = await _tokenService.GetMJapiTokenByIdAsync(mJApiTasks.TokenId);
if (mJApiTokens == null)
{
return null;
}
useToken = mJApiTokens.UseToken;
}
else
{
useToken = tokenConfig.UseToken;
}
if (string.IsNullOrWhiteSpace(useToken))
{
_logger.LogInformation($"Token is empty for task ID: {mJApiTasks.TaskId}");
return null;
}
// 尝试原始API
var originResult = await TryOriginApiAsync(mJApiTasks.ThirdPartyTaskId);
var properties = new Dictionary<string, object>();
if (string.IsNullOrWhiteSpace(originResult))
{
originResult = await TryBackupApiAsync(mJApiTasks.ThirdPartyTaskId, useToken);
}
if (string.IsNullOrWhiteSpace(originResult))
{
// 没有找到数据
_logger.LogInformation($"备用API没有返回数据TaskId: {mJApiTasks.TaskId}");
return null;
}
try
{
// 不为空 开始解析数据
properties = JsonConvert.DeserializeObject<Dictionary<string, object>>(originResult);
}
catch (JsonException ex)
{
_logger.LogError($"解析API返回数据失败: {ex.Message}");
return null;
}
if (properties == null)
{
_logger.LogInformation($"API返回数据为空TaskId: {mJApiTasks.TaskId}");
return null;
}
return properties;
}
catch (Exception ex)
{
// 记录异常日志
_logger.LogError($"Error fetching task: {ex.Message}");
return null;
}
}
private async Task<string?> TryOriginApiAsync(string id)
{
string originUrl = $"https://mjapi.bzu.cn/mj/task/{id}/fetch";
// 判断 原始token 不存在 直接 返回空
string orginToken = await _tokenService.GetOriginToken();
if (string.IsNullOrWhiteSpace(orginToken))
{
return null;
}
try
{
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", orginToken);
client.Timeout = TimeSpan.FromSeconds(30);
var response = await client.GetAsync(originUrl);
var content = await response.Content.ReadAsStringAsync();
// 判断是不是返回空
if ((int)response.StatusCode == 204 || string.IsNullOrWhiteSpace(content))
{
return string.Empty;
}
if (!response.IsSuccessStatusCode)
{
_logger.LogWarning($"源API调用返回错误状态码TaskId: {id}, StatusCode: {response.StatusCode}");
return null;
}
return content;
}
catch (Exception ex)
{
_logger.LogWarning(ex, "原始API调用失败TaskId: {TaskId}准备尝试备用API", id);
return null;
}
}
private async Task<string?> TryBackupApiAsync(string id, string useToken)
{
string mjAPIBasicUrl = await _tokenService.GetMJAPIBasicUrl();
string backupUrl = $"{mjAPIBasicUrl}/mj/task/{id}/fetch";
const int maxRetries = 3;
const int baseDelayMs = 1000;
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "sk-" + useToken);
client.Timeout = TimeSpan.FromSeconds(30);
for (int attempt = 1; attempt <= maxRetries; attempt++)
{
try
{
var response = await client.GetAsync(backupUrl);
var content = await response.Content.ReadAsStringAsync();
// 判断请求是不是报错
if (!response.IsSuccessStatusCode)
{
_logger.LogWarning("备用API调用返回错误状态码TaskId: {TaskId}, Attempt: {Attempt}, StatusCode: {StatusCode}",
id, attempt, response.StatusCode);
return null;
}
return content;
}
catch (Exception ex) when (IsRetriableException(ex))
{
if (attempt < maxRetries)
{
var delay = baseDelayMs * (int)Math.Pow(2, attempt - 1);
_logger.LogWarning(ex, "备用API调用失败TaskId: {TaskId}, Attempt: {Attempt}, 将在{Delay}ms后重试",
id, attempt, delay);
await Task.Delay(delay);
}
else
{
_logger.LogError(ex, "备用API调用最终失败TaskId: {TaskId}, MaxAttempts: {MaxAttempts}",
id, maxRetries);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "备用API调用发生不可重试异常TaskId: {TaskId}, Attempt: {Attempt}",
id, attempt);
break;
}
}
return null;
}
private static bool IsRetriableException(Exception ex)
{
return ex is HttpRequestException ||
ex is TaskCanceledException ||
ex is SocketException;
}
}
}