diff --git a/src/Common/Extensions/HttpContextExtensions.cs b/src/Common/Extensions/HttpContextExtensions.cs index 45e8d88..74654f4 100644 --- a/src/Common/Extensions/HttpContextExtensions.cs +++ b/src/Common/Extensions/HttpContextExtensions.cs @@ -27,11 +27,17 @@ namespace lai_transfer.Common.Extensions { string? token = httpContext.GetContextItem("AuthToken"); string? baseUrl = httpContext.GetContextItem("BaseUrl"); + if (!String.IsNullOrWhiteSpace(baseUrl) && baseUrl.EndsWith('/')) + { + baseUrl = baseUrl.TrimEnd('/'); + } + bool storage = Convert.ToBoolean(httpContext.GetContextItem("Storage") ?? "false"); + bool splice = Convert.ToBoolean(httpContext.GetContextItem("Splice") ?? "false"); if (string.IsNullOrWhiteSpace(token) || string.IsNullOrWhiteSpace(baseUrl)) { throw new InvalidOperationException("Authentication token or base URL is not set in the context."); } - return new TransferAuthorizationResult(token, baseUrl); + return new TransferAuthorizationResult(token, baseUrl, storage, splice, ""); } /// diff --git a/src/Common/Filters/SplitMJAuthorizationFilter.cs b/src/Common/Filters/SplitMJAuthorizationFilter.cs index f7464c1..e1269d9 100644 --- a/src/Common/Filters/SplitMJAuthorizationFilter.cs +++ b/src/Common/Filters/SplitMJAuthorizationFilter.cs @@ -1,4 +1,7 @@ -namespace lai_transfer.Common.Filters +using lai_transfer.Common.Helper; +using Newtonsoft.Json.Linq; + +namespace lai_transfer.Common.Filters { public class SplitMJAuthorizationFilter(ILogger logger) : IEndpointFilter { @@ -25,43 +28,43 @@ _logger.LogWarning("Authorization header is missing"); return TypedResults.Unauthorized(); } - else + + // 2. 处理令牌,判断是不是有前缀 删除前缀 + if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { - // 2. 处理令牌,判断是不是有前缀 删除前缀 - if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) - { - authorization = authorization["Bearer ".Length..]; - } - if (authorization.Contains("?url=")) - { - // 使用Split方法拆分字符串 - string[] parts = authorization.Split("?url=", 2); - if (parts.Length == 2) - { - string token = parts[0].Trim(); - string baseUrl = parts[1].TrimEnd('/'); - if (string.IsNullOrWhiteSpace(authorization) || string.IsNullOrWhiteSpace(baseUrl)) - { - _logger.LogWarning("令牌或URL为空"); - return TypedResults.Unauthorized(); - } - httpContext.Items["AuthToken"] = token; - // 将baseUrl也存入HttpContext以便后续使用 - httpContext.Items["BaseUrl"] = baseUrl; - return await next(context); - } - else - { - _logger.LogWarning("令牌解析错误"); - return TypedResults.Unauthorized(); - } - } - else - { - _logger.LogWarning("令牌解析错误,没有包含 url"); - return TypedResults.Unauthorized(); - } + authorization = authorization["Bearer ".Length..]; } + + var result1 = QueryStringHelper.Parse(authorization); + + string token = result1.Prefix; + string baseUrl = result1.GetString("url"); + // 是否存储 + bool storage = result1.GetBool("storage", false); + + // 是否拼接 + bool splice = result1.GetBool("splice", false); + + // token 不能为空 + if (String.IsNullOrWhiteSpace(token)) + { + _logger.LogWarning("Authorization Invalid"); + return TypedResults.Unauthorized(); + } + + if (String.IsNullOrWhiteSpace(baseUrl)) + { + _logger.LogWarning("BaseUrl Invalid"); + return TypedResults.BadRequest("BaseUrl Invalid"); + } + + httpContext.Items["AuthToken"] = token; + // 将baseUrl也存入HttpContext以便后续使用 + httpContext.Items["BaseUrl"] = baseUrl; + httpContext.Items["Storage"] = storage; + httpContext.Items["Splice"] = splice; + return await next(context); + } } } \ No newline at end of file diff --git a/src/Common/Helper/ConfigHelper.cs b/src/Common/Helper/ConfigHelper.cs index 392a5a1..5a1e600 100644 --- a/src/Common/Helper/ConfigHelper.cs +++ b/src/Common/Helper/ConfigHelper.cs @@ -21,6 +21,8 @@ namespace lai_transfer.Common.Helper Translate.Init(reader); + Qiniu.Init(reader); + _logger.LogInformation("配置加载完成"); } catch (Exception ex) @@ -88,6 +90,43 @@ namespace lai_transfer.Common.Helper } // 存储Origin配置 + + public static class Qiniu + { + public static string AccessKey { get; internal set; } = string.Empty; + public static string SecretKey { get; internal set; } = string.Empty; + public static string BucketName { get; internal set; } = string.Empty; + public static string Domain { get; internal set; } = string.Empty; + public static double MaxFileSize { get; internal set; } = 10; // MB + public static bool OriginImage { get; internal set; } = false; + /// + /// 初始化Qiniu配置 + /// + public static void Init(JsonConfigReader reader) + { + try + { + _logger.LogInformation("正在加载Qiniu配置..."); + // 加载Qiniu配置 + AccessKey = reader.GetString("QiNiu.AccessKey") ?? string.Empty; + SecretKey = reader.GetString("QiNiu.SecretKey") ?? string.Empty; + BucketName = reader.GetString("QiNiu.BucketName") ?? string.Empty; + Domain = reader.GetString("QiNiu.Domain") ?? string.Empty; + MaxFileSize = reader.GetDouble("QiNiu.MaxFileSize") ?? 10; // MB + OriginImage = reader.GetBool("QiNiu.OriginImage") ?? false; + _logger.LogInformation("QiNiu配置加载完成"); + } + catch (Exception ex) + { + _logger.LogError(ex, "加载Qiniu配置失败"); + // 报错,结束程序运行 + throw new InvalidOperationException("无法加载Qiniu配置,请检查配置文件是否存在或格式是否正确。", ex); + } + } + + + } + public static class Origin { // 将private set改为internal set,允许同一程序集中的代码设置属性值 diff --git a/src/Common/Helper/QueryStringHelper.cs b/src/Common/Helper/QueryStringHelper.cs new file mode 100644 index 0000000..3dca810 --- /dev/null +++ b/src/Common/Helper/QueryStringHelper.cs @@ -0,0 +1,132 @@ +namespace lai_transfer.Common.Helper +{ + public static class QueryStringHelper + { + public class ParseResult + { + public string Prefix { get; set; } + public Dictionary Parameters { get; set; } + + public ParseResult() + { + Parameters = new Dictionary(); + } + + // 获取字符串值 + public string GetString(string key, string defaultValue = "") + { + return Parameters.TryGetValue(key, out string value) ? value : defaultValue; + } + + // 获取布尔值 + public bool GetBool(string key, bool defaultValue = false) + { + if (Parameters.TryGetValue(key, out string value)) + { + // 支持多种布尔值格式 + string lowerValue = value.ToLower(); + if (lowerValue == "true" || lowerValue == "1" || lowerValue == "yes") + return true; + if (lowerValue == "false" || lowerValue == "0" || lowerValue == "no") + return false; + } + return defaultValue; + } + + // 获取整数值 + public int GetInt(string key, int defaultValue = 0) + { + if (Parameters.TryGetValue(key, out string value)) + { + if (int.TryParse(value, out int result)) + return result; + } + return defaultValue; + } + + // 获取长整数值 + public long GetLong(string key, long defaultValue = 0) + { + if (Parameters.TryGetValue(key, out string value)) + { + if (long.TryParse(value, out long result)) + return result; + } + return defaultValue; + } + + // 获取双精度浮点数 + public double GetDouble(string key, double defaultValue = 0.0) + { + if (Parameters.TryGetValue(key, out string value)) + { + if (double.TryParse(value, out double result)) + return result; + } + return defaultValue; + } + + // 尝试获取布尔值 + public bool TryGetBool(string key, out bool result) + { + result = false; + if (Parameters.TryGetValue(key, out string value)) + { + string lowerValue = value.ToLower(); + if (lowerValue == "true" || lowerValue == "1" || lowerValue == "yes") + { + result = true; + return true; + } + if (lowerValue == "false" || lowerValue == "0" || lowerValue == "no") + { + result = false; + return true; + } + } + return false; + } + } + + public static ParseResult Parse(string input) + { + var result = new ParseResult(); + + if (string.IsNullOrEmpty(input)) + return result; + + // 找到第一个 ? 的位置 + int firstQuestionMark = input.IndexOf('?'); + + if (firstQuestionMark == -1) + { + // 没有参数,整个字符串都是前缀 + result.Prefix = input; + return result; + } + + // 提取前缀部分(第一个 ? 之前的内容) + result.Prefix = input.Substring(0, firstQuestionMark); + + // 从第一个 ? 之后开始处理参数 + string queryString = input.Substring(firstQuestionMark + 1); + + // 按 ? 分割参数 + var pairs = queryString.Split('?'); + + foreach (var pair in pairs) + { + if (string.IsNullOrWhiteSpace(pair)) + continue; + + var keyValue = pair.Split(new[] { '=' }, 2); + if (keyValue.Length == 2) + { + result.Parameters[keyValue[0]] = keyValue[1]; + } + } + + return result; + } + } +} diff --git a/src/Common/Helper/RetryHelper.cs b/src/Common/Helper/RetryHelper.cs new file mode 100644 index 0000000..eb2b728 --- /dev/null +++ b/src/Common/Helper/RetryHelper.cs @@ -0,0 +1,199 @@ +namespace lai_transfer.Common.Helper; + +public class RetryHelper +{ + private static readonly ILogger _logger = LogHelper.GetLogger(); + /// + /// 异步重试执行函数(无返回值) + /// + /// 要执行的函数 + /// 重试次数 + /// 重试间隔 + /// 取消令牌 + public static async Task RetryAsync( + Func action, + int retryCount = 3, + TimeSpan? delay = null, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(action); + + var exceptions = new List(); + var currentDelay = delay ?? TimeSpan.FromSeconds(1); + + for (int attempt = 0; attempt <= retryCount; attempt++) + { + try + { + if (attempt > 0) + { + _logger?.LogInformation("重试执行,第 {Attempt} 次尝试", attempt); + } + + await action().ConfigureAwait(false); + return; // 执行成功,直接返回 + } + catch (Exception ex) when (ex is not OperationCanceledException) + { + exceptions.Add(ex); + _logger?.LogWarning(ex, "第 {Attempt} 次执行失败", attempt + 1); + + if (attempt == retryCount) + { + throw new AggregateException($"在 {retryCount + 1} 次尝试后操作仍失败", exceptions); + } + + // 等待一段时间后重试 + if (currentDelay > TimeSpan.Zero) + { + _logger?.LogInformation("等待 {Delay} 后重试", currentDelay); + await Task.Delay(currentDelay, cancellationToken).ConfigureAwait(false); + } + } + } + } + + /// + /// 异步重试执行函数(有返回值) + /// + /// 返回值类型 + /// 要执行的函数 + /// 重试次数 + /// 重试间隔(默认1s) + /// 取消令牌 + /// 函数执行结果 + public static async Task RetryAsync( + Func> func, + int retryCount = 3, + TimeSpan? delay = null, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(func); + + var exceptions = new List(); + var currentDelay = delay ?? TimeSpan.FromSeconds(1); + + for (int attempt = 0; attempt <= retryCount; attempt++) + { + try + { + if (attempt > 0) + { + _logger?.LogInformation("重试执行,第 {Attempt} 次尝试", attempt); + } + + return await func().ConfigureAwait(false); + } + catch (Exception ex) when (ex is not OperationCanceledException) + { + exceptions.Add(ex); + _logger?.LogWarning(ex, "第 {Attempt} 次执行失败", attempt + 1); + + if (attempt == retryCount) + { + throw new AggregateException($"在 {retryCount + 1} 次尝试后操作仍失败", exceptions); + } + + // 等待一段时间后重试 + if (currentDelay > TimeSpan.Zero) + { + _logger?.LogInformation("等待 {Delay} 后重试", currentDelay); + await Task.Delay(currentDelay, cancellationToken).ConfigureAwait(false); + } + } + } + + throw new InvalidOperationException("不应该执行到这里"); + } + + /// + /// 同步重试执行函数(无返回值) + /// + public static void Retry( + Action action, + int retryCount = 3, + TimeSpan? delay = null) + { + ArgumentNullException.ThrowIfNull(action); + + var exceptions = new List(); + var currentDelay = delay ?? TimeSpan.FromSeconds(1); + + for (int attempt = 0; attempt <= retryCount; attempt++) + { + try + { + if (attempt > 0) + { + _logger?.LogInformation("重试执行,第 {Attempt} 次尝试", attempt); + } + + action(); + return; // 执行成功,直接返回 + } + catch (Exception ex) + { + exceptions.Add(ex); + _logger?.LogWarning(ex, "第 {Attempt} 次执行失败", attempt + 1); + + if (attempt == retryCount) + { + throw new AggregateException($"在 {retryCount + 1} 次尝试后操作仍失败", exceptions); + } + + // 等待一段时间后重试 + if (currentDelay > TimeSpan.Zero) + { + _logger?.LogInformation("等待 {Delay} 后重试", currentDelay); + Thread.Sleep(currentDelay); + } + } + } + } + + /// + /// 同步重试执行函数(有返回值) + /// + public static TResult Retry( + Func func, + int retryCount = 3, + TimeSpan? delay = null) + { + ArgumentNullException.ThrowIfNull(func); + + var exceptions = new List(); + var currentDelay = delay ?? TimeSpan.FromSeconds(1); + + for (int attempt = 0; attempt <= retryCount; attempt++) + { + try + { + if (attempt > 0) + { + _logger?.LogInformation("重试执行,第 {Attempt} 次尝试", attempt); + } + + return func(); + } + catch (Exception ex) + { + exceptions.Add(ex); + _logger?.LogWarning(ex, "第 {Attempt} 次执行失败", attempt + 1); + + if (attempt == retryCount) + { + throw new AggregateException($"在 {retryCount + 1} 次尝试后操作仍失败", exceptions); + } + + // 等待一段时间后重试 + if (currentDelay > TimeSpan.Zero) + { + _logger?.LogInformation("等待 {Delay} 后重试", currentDelay); + Thread.Sleep(currentDelay); + } + } + } + + throw new InvalidOperationException("不应该执行到这里"); + } +} diff --git a/src/Common/Results/TransferAuthorizationResult.cs b/src/Common/Results/TransferAuthorizationResult.cs index c23c770..8c51520 100644 --- a/src/Common/Results/TransferAuthorizationResult.cs +++ b/src/Common/Results/TransferAuthorizationResult.cs @@ -1,4 +1,22 @@ -namespace lai_transfer.Common.Results +using Newtonsoft.Json.Linq; + +namespace lai_transfer.Common.Results { - public record TransferAuthorizationResult(string Token, string BaseUrl); + public class TransferAuthorizationResult + { + public string Token { get; set; } + public string BaseUrl { get; set; } + public bool Storage { get; set; } + public bool Splice { get; set; } + public string FullPath { get; set; } + + public TransferAuthorizationResult(string Token, string BaseUrl, bool Storage, bool Splice, string FullPath) + { + this.Token = Token; + this.BaseUrl = BaseUrl; + this.Storage = Storage; + this.Splice = Splice; + this.FullPath = FullPath; + } + } } diff --git a/src/Common/Types/MJType.cs b/src/Common/Types/MJType.cs new file mode 100644 index 0000000..bb9fba9 --- /dev/null +++ b/src/Common/Types/MJType.cs @@ -0,0 +1,16 @@ +namespace lai_transfer.Common.Types +{ + public class MJType + { + public class MJOptionType + { + public const string IMAGINE = "IMAGINE"; + + } + + public class MJStatus + { + public const string NOT_START = "not_start"; + } + } +} diff --git a/src/Configuration/DataBase/db.realm b/src/Configuration/DataBase/db.realm new file mode 100644 index 0000000..bf00616 Binary files /dev/null and b/src/Configuration/DataBase/db.realm differ diff --git a/src/Configuration/DataBase/db.realm.lock b/src/Configuration/DataBase/db.realm.lock new file mode 100644 index 0000000..f199e01 Binary files /dev/null and b/src/Configuration/DataBase/db.realm.lock differ diff --git a/src/Configuration/config/transfer-temp.json b/src/Configuration/config/transfer-temp.json index a1fb908..501d071 100644 --- a/src/Configuration/config/transfer-temp.json +++ b/src/Configuration/config/transfer-temp.json @@ -15,5 +15,13 @@ "OpenaiGptMaxTokens": 2048, "OpenaiGptTemperature": 0, "TimeOut": 20 + }, + "QiNiu": { + "AccessKey": "akGxVLyV-xxx", + "SecretKey": "a0zHruUrouxCxxx", + "BucketName": "open-laitoolxxx", + "Domain": "https://opss.laitool.cn", + "MaxFileSize": 10, + "OriginImage": true } } diff --git a/src/ConfigureServices.cs b/src/ConfigureServices.cs index 35cade1..c1a999f 100644 --- a/src/ConfigureServices.cs +++ b/src/ConfigureServices.cs @@ -1,17 +1,20 @@ using FluentValidation; +using lai_transfer.Common.Helper; using lai_transfer.Configuration; using lai_transfer.Model.Entity; -using lai_transfer.Services; -using lai_transfer.EndpointServices.MJTransferEndpoint; +using lai_transfer.Services.Midjourney; +using lai_transfer.Services.PeriodicTimeService; +using lai_transfer.Services.RealmService; +using lai_transfer.Services.Translate; +using lai_transfer.Tool.HttpTool; +using lai_transfer.Tool.ImageTool; +using lai_transfer.Tool.QiniuService; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using Serilog; using System.Text; -using Midjourney.Infrastructure.Services; -using lai_transfer.Common.Helper; namespace lai_transfer { @@ -58,6 +61,19 @@ namespace lai_transfer /// private static void AddService(this IServiceCollection services) { + // 注册翻译服务 + services.AddScoped(); + services.AddSingleton(); + services.AddHttpClient(); + + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + services.AddHostedService(); + if (ConfigHelper.Translate.Model == "GPT") { // 翻译服务注入 diff --git a/src/EndpointServices/MJTransferEndpoint/MJGetFetchIdService.cs b/src/EndpointServices/MJTransferEndpoint/MJGetFetchIdService.cs index e745a43..82a08d7 100644 --- a/src/EndpointServices/MJTransferEndpoint/MJGetFetchIdService.cs +++ b/src/EndpointServices/MJTransferEndpoint/MJGetFetchIdService.cs @@ -2,6 +2,7 @@ using lai_transfer.Common.Helper; using lai_transfer.Common.Results; using lai_transfer.Endpoints; +using lai_transfer.Services.Midjourney; using lai_transfer.Tool.Extensions; using Newtonsoft.Json; @@ -18,16 +19,10 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint public static async Task Handle(string id, HttpContext httpContext) { - // 先尝试调用原始API - TransferResult? originTransferResult = await TryOriginApiAsync(id); - if (originTransferResult != null) - { - return Results.Text(originTransferResult.Content, originTransferResult.ContentType, statusCode: originTransferResult.StatusCode); - } - // 原始请求失败,请求到指定的API - TransferResult transferResult = await SendUrlTaskFetchById(id, httpContext); - // 返回结果 - return Results.Text(transferResult.Content, transferResult.ContentType, statusCode: transferResult.StatusCode); + TransferAuthorizationResult authorizationResult = httpContext.GetAuthorizationItemsAndValidation(); + authorizationResult.FullPath = httpContext.GetFullRequestPath(); + IMidjourneyService midjourneyService = httpContext.RequestServices.GetRequiredService(); + return await midjourneyService.MidjourneyFetchTaskById(id, authorizationResult); } /// diff --git a/src/EndpointServices/MJTransferEndpoint/MJGetImageSeedService.cs b/src/EndpointServices/MJTransferEndpoint/MJGetImageSeedService.cs index 13c4813..59cf4af 100644 --- a/src/EndpointServices/MJTransferEndpoint/MJGetImageSeedService.cs +++ b/src/EndpointServices/MJTransferEndpoint/MJGetImageSeedService.cs @@ -24,21 +24,26 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint { try { - //string baseUrl = TransferAuthorizationResult transferAuthorizationResult = httpContext.GetAuthorizationItemsAndValidation(); string url = $"{transferAuthorizationResult.BaseUrl}/mj/task/{id}/image-seed"; - // 设置HttpClient - using HttpClient client = new HttpClient(); - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}"); - client.Timeout = Timeout.InfiniteTimeSpan; + TransferResult res = await RetryHelper.RetryAsync(async () => + { + // 设置HttpClient + using HttpClient client = new HttpClient(); + client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}"); + client.DefaultRequestHeaders.Add("mj-api-secret", transferAuthorizationResult.Token); + client.Timeout = Timeout.InfiniteTimeSpan; - // 发送请求 - var response = await client.GetAsync(url); - string content = await response.Content.ReadAsStringAsync(); + // 发送请求 + var response = await client.GetAsync(url); + string content = await response.Content.ReadAsStringAsync(); - // 返回结果 - return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + // 返回结果 + return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + }, 5); + + return res; } catch (Exception ex) { diff --git a/src/EndpointServices/MJTransferEndpoint/MJPostActionService.cs b/src/EndpointServices/MJTransferEndpoint/MJPostActionService.cs index c4c175c..3a9d92d 100644 --- a/src/EndpointServices/MJTransferEndpoint/MJPostActionService.cs +++ b/src/EndpointServices/MJTransferEndpoint/MJPostActionService.cs @@ -27,16 +27,22 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint { TransferAuthorizationResult authorizationResult = httpContext.GetAuthorizationItemsAndValidation(); string url = $"{authorizationResult.BaseUrl}/mj/submit/action"; - // 设置HttpClient - using HttpClient client = new HttpClient(); - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {authorizationResult.Token}"); - client.Timeout = Timeout.InfiniteTimeSpan; - string body = JSONHelper.RemoveJsonProperties(model, "notifyHook"); - // 发送请求 - var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); - string content = await response.Content.ReadAsStringAsync(); - return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + TransferResult res = await RetryHelper.RetryAsync(async () => + { + // 设置HttpClient + using HttpClient client = new HttpClient(); + client.DefaultRequestHeaders.Add("Authorization", $"Bearer {authorizationResult.Token}"); + client.DefaultRequestHeaders.Add("mj-api-secret", authorizationResult.Token); + client.Timeout = Timeout.InfiniteTimeSpan; + + string body = JSONHelper.RemoveJsonProperties(model, "notifyHook"); + // 发送请求 + var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); + string content = await response.Content.ReadAsStringAsync(); + return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + }, 5); + return res; } catch (Exception ex) { diff --git a/src/EndpointServices/MJTransferEndpoint/MJPostBlendService.cs b/src/EndpointServices/MJTransferEndpoint/MJPostBlendService.cs index 102d491..39b2e58 100644 --- a/src/EndpointServices/MJTransferEndpoint/MJPostBlendService.cs +++ b/src/EndpointServices/MJTransferEndpoint/MJPostBlendService.cs @@ -26,17 +26,22 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint { TransferAuthorizationResult authorizationResult = httpContext.GetAuthorizationItemsAndValidation(); string url = $"{authorizationResult.BaseUrl}/mj/submit/blend"; - // 设置HttpClient - using HttpClient client = new HttpClient(); - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {authorizationResult.Token}"); - client.Timeout = Timeout.InfiniteTimeSpan; - // 删除回调参数 notifyHook - string body = JSONHelper.RemoveJsonProperties(model, "notifyHook"); - // 发送请求 - var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); - string content = await response.Content.ReadAsStringAsync(); + TransferResult res = await RetryHelper.RetryAsync(async () => + { + // 设置HttpClient + using HttpClient client = new HttpClient(); + client.DefaultRequestHeaders.Add("Authorization", $"Bearer {authorizationResult.Token}"); + client.DefaultRequestHeaders.Add("mj-api-secret", authorizationResult.Token); + client.Timeout = Timeout.InfiniteTimeSpan; + // 删除回调参数 notifyHook + string body = JSONHelper.RemoveJsonProperties(model, "notifyHook"); + // 发送请求 + var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); + string content = await response.Content.ReadAsStringAsync(); - return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + }, 5); + return res; } catch (Exception ex) { diff --git a/src/EndpointServices/MJTransferEndpoint/MJPostDescribeService.cs b/src/EndpointServices/MJTransferEndpoint/MJPostDescribeService.cs index 35e937f..1936ff6 100644 --- a/src/EndpointServices/MJTransferEndpoint/MJPostDescribeService.cs +++ b/src/EndpointServices/MJTransferEndpoint/MJPostDescribeService.cs @@ -26,18 +26,23 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint { TransferAuthorizationResult authorizationResult = httpContext.GetAuthorizationItemsAndValidation(); string url = $"{authorizationResult.BaseUrl}/mj/submit/describe"; - // 设置HttpClient - using HttpClient client = new HttpClient(); - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {authorizationResult.Token}"); - client.Timeout = Timeout.InfiniteTimeSpan; + TransferResult res = await RetryHelper.RetryAsync(async () => + { + // 设置HttpClient + using HttpClient client = new HttpClient(); + client.DefaultRequestHeaders.Add("Authorization", $"Bearer {authorizationResult.Token}"); + client.DefaultRequestHeaders.Add("mj-api-secret", authorizationResult.Token); + client.Timeout = Timeout.InfiniteTimeSpan; - // 删除回调参数 notifyHook - string body = JSONHelper.RemoveJsonProperties(model, "notifyHook"); - // 发送请求 - var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); - string content = await response.Content.ReadAsStringAsync(); + // 删除回调参数 notifyHook + string body = JSONHelper.RemoveJsonProperties(model, "notifyHook"); + // 发送请求 + var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); + string content = await response.Content.ReadAsStringAsync(); - return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + }, 5); + return res; } catch (Exception ex) { diff --git a/src/EndpointServices/MJTransferEndpoint/MJPostFetchListByConditionService.cs b/src/EndpointServices/MJTransferEndpoint/MJPostFetchListByConditionService.cs index 56aaf61..304d05e 100644 --- a/src/EndpointServices/MJTransferEndpoint/MJPostFetchListByConditionService.cs +++ b/src/EndpointServices/MJTransferEndpoint/MJPostFetchListByConditionService.cs @@ -2,10 +2,8 @@ using lai_transfer.Common.Helper; using lai_transfer.Common.Results; using lai_transfer.Endpoints; -using lai_transfer.Tool.Extensions; -using Microsoft.AspNetCore.Authorization; -using Newtonsoft.Json; -using System.Text.Json; +using lai_transfer.Services.Midjourney; +using static lai_transfer.Model.Midjourney.MidjourneyRequest; namespace lai_transfer.EndpointServices.MJTransferEndpoint { @@ -17,133 +15,13 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint .WithSummary("Midjourney 根据ID列表查询任务") .WithMJAuthorizationHeader(); - private static async Task Handle(JsonElement model, HttpContext httpContext) + private static async Task Handle(FetchListByCondition model, HttpContext httpContext) { + TransferAuthorizationResult transferAuthorizationResult = httpContext.GetAuthorizationItemsAndValidation(); - // 先尝试调用原始API - TransferResult? originTransferResult = await TryOriginApiAsync(model); - if (originTransferResult != null) - { - return Results.Text(originTransferResult.Content, originTransferResult.ContentType, statusCode: originTransferResult.StatusCode); - } + IMidjourneyService midjourneyService = httpContext.RequestServices.GetRequiredService(); - TransferResult transferResult = await SendOriginalFetchListByCondition(model, httpContext); - return Results.Text(transferResult.Content, transferResult.ContentType, statusCode: transferResult.StatusCode); - } - - private static async Task SendOriginalFetchListByCondition(JsonElement model, HttpContext httpContext) - { - try - { - TransferAuthorizationResult transferAuthorizationResult = httpContext.GetAuthorizationItemsAndValidation(); - string url = $"{transferAuthorizationResult.BaseUrl}/mj/task/list-by-condition"; - // 设置HttpClient - using HttpClient client = new HttpClient(); - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}"); - client.Timeout = Timeout.InfiniteTimeSpan; - - string body = model.GetRawText(); - // 发送请求 - var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); - string content = await response.Content.ReadAsStringAsync(); - return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); - } - catch (Exception ex) - { - _logger.LogError(ex, $"转发 {httpContext.GetFullRequestPath()} 失败"); - // 处理异常,返回错误信息 - return new TransferResult(ex.Message, "application/json", StatusCodes.Status500InternalServerError); - } - } - - /// - /// 获取原始数据信息 bzu - /// - /// - /// - private static async Task TryOriginApiAsync(JsonElement model) - { - // 如果要访问任意JSON节点,可以使用JsonConfigReader - //var reader = new JsonConfigReader("Configuration/config/transfer.json"); - string? baseUrl = ConfigHelper.Origin.BaseUrl; - string? token = ConfigHelper.Origin.Token; - - if (string.IsNullOrWhiteSpace(baseUrl) || string.IsNullOrWhiteSpace(token)) - { - _logger.LogWarning("配置文件中未找到 Origin.BaseUrl 或 Origin.Token"); - return null; - } - - string originUrl = $"{baseUrl.TrimEnd('/')}/mj/task/list-by-condition"; - - try - { - using var client = new HttpClient(); - client.DefaultRequestHeaders.Add("Authorization", token); - client.Timeout = TimeSpan.FromSeconds(30); - - string body = model.GetRawText(); - var response = await client.PostAsync(originUrl, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); - var content = await response.Content.ReadAsStringAsync(); - - // 判断是不是返回空 - if ((int)response.StatusCode == 204 || string.IsNullOrWhiteSpace(content)) - { - return null; - } - if (!response.IsSuccessStatusCode) - { - _logger.LogWarning($"源API调用 /mj/task/list-by-condition 返回错误状态码, StatusCode: {response.StatusCode}"); - return null; - } - - // 有返回结果 这这边开始处理返回的数据信息 - List>? properties = ProcessTaskArrayData(content); - if (properties != null && properties.Count > 0) - { - return new TransferResult( - JsonConvert.SerializeObject(properties), - "application/json", - StatusCodes.Status200OK); - } - else - { - return null; - } - } - catch (Exception ex) - { - _logger.LogWarning(ex, "原始API /mj/task/list-by-condition 调用失败"); - return null; - } - } - - private static List>? ProcessTaskArrayData(string content) - { - try - { - List> result = []; - // 解析 JSON 数据 - var jsonObject = JsonConvert.DeserializeObject>>(content); - if (jsonObject == null || jsonObject.Count == 0) - { - return []; - } - // 处理每个任务数据 - for (int i = 0; i < jsonObject.Count; i++) - { - var properties = MJGetFetchIdService.ProcessTaskObjectData(jsonObject[i]); - result.Add(properties); - } - - // 返回数据 - return result; - } - catch (Exception ex) - { - _logger.LogError(ex, "处理任务数据失败"); - return null; - } + return await midjourneyService.FetchListByCondition(model, transferAuthorizationResult); } } } diff --git a/src/EndpointServices/MJTransferEndpoint/MJPostImagineService.cs b/src/EndpointServices/MJTransferEndpoint/MJPostImagineService.cs index d417159..26292ce 100644 --- a/src/EndpointServices/MJTransferEndpoint/MJPostImagineService.cs +++ b/src/EndpointServices/MJTransferEndpoint/MJPostImagineService.cs @@ -2,7 +2,8 @@ using lai_transfer.Common.Helper; using lai_transfer.Common.Results; using lai_transfer.Endpoints; -using lai_transfer.Services; +using lai_transfer.Services.Midjourney; +using lai_transfer.Services.Translate; using System.Text; using System.Text.Json; using System.Text.RegularExpressions; @@ -20,8 +21,7 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint private static async Task Handle(JsonElement model, HttpContext httpContext) { - (string content, string contentType, int statusCode) = await SendOriginalImagine(model, httpContext); - return Results.Text(content, contentType, statusCode: statusCode); + return await SendOriginalImagine(model, httpContext); } /// @@ -30,111 +30,23 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint /// /// /// - private static async Task<(string content, string contentType, int statusCode)> SendOriginalImagine(JsonElement model, HttpContext httpContext) + private static async Task SendOriginalImagine(JsonElement model, HttpContext httpContext) { try { TransferAuthorizationResult authorizationResult = httpContext.GetAuthorizationItemsAndValidation(); - string url = $"{authorizationResult.BaseUrl}/mj/submit/imagine"; + string requestUrl = httpContext.GetFullRequestPath(); + authorizationResult.FullPath = requestUrl; + IMidjourneyService midjourneyService = httpContext.RequestServices.GetRequiredService(); - // 设置HttpClient - using HttpClient client = new HttpClient(); - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {authorizationResult.Token}"); - client.Timeout = Timeout.InfiniteTimeSpan; - - // 强制翻译提示词 - string prompt = JSONHelper.GetJsonPropertyString(model, "prompt") ?? string.Empty; - - // 使用HttpContext扩展方法获取翻译服务 - var translateService = ServiceLocator.GetRequiredService(); - prompt = await TranslatePrompt(prompt, translateService); - - model = JSONHelper.SetJsonProperty(model, "prompt", prompt); - - // 删除回调参数 notifyHook - string body = JSONHelper.RemoveJsonProperties(model, "notifyHook"); - //return (body, "application/json", 200); - // 发送请求 - var response = await client.PostAsync(url, new StringContent(body, Encoding.UTF8, "application/json")); - string content = await response.Content.ReadAsStringAsync(); - return (content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + IResult t = await midjourneyService.MidjourneyImagine(model, authorizationResult); + return t; } catch (Exception ex) { _logger.LogError(ex, $"请求 {httpContext.GetFullRequestPath()} 失败"); // 处理异常,返回错误信息 - return (ex.Message, "application/json", StatusCodes.Status500InternalServerError); - } - } - - /// - /// 翻译提示词 - /// - /// 原始提示词 - /// 翻译服务 - /// 翻译后的提示词 - public static async Task TranslatePrompt(string prompt, ITranslateService translateService) - { - if (string.IsNullOrWhiteSpace(prompt)) - return prompt; - - try - { - - // 检查是否启用翻译功能 - if (!ConfigHelper.Translate.Enable) - return prompt; - - // 如果不包含中文,直接返回 - if (string.IsNullOrWhiteSpace(prompt) || !translateService.ContainsChinese(prompt)) - return prompt; - - string paramStr = ""; - var paramMatcher = Regex.Match(prompt, "\\x20+--[a-z]+.*$", RegexOptions.IgnoreCase); - if (paramMatcher.Success) - { - paramStr = paramMatcher.Value; - } - string promptWithoutParam = prompt.Substring(0, prompt.Length - paramStr.Length); - List imageUrls = new List(); - var imageMatcher = Regex.Matches(promptWithoutParam, "https?://[a-z0-9-_:@&?=+,.!/~*'%$]+\\x20+", RegexOptions.IgnoreCase); - foreach (Match match in imageMatcher) - { - imageUrls.Add(match.Value); - } - string text = promptWithoutParam; - foreach (string imageUrl in imageUrls) - { - text = text.Replace(imageUrl, ""); - } - text = text.Trim(); - if (!string.IsNullOrWhiteSpace(text)) - { - text = await translateService.TranslateToEnglish(text); - } - if (!string.IsNullOrWhiteSpace(paramStr)) - { - // 当有 --no 参数时, 翻译 --no 参数, 并替换原参数 - // --sref https://mjcdn.googlec.cc/1.jpg --no aa, bb, cc - var paramNomatcher = Regex.Match(paramStr, "--no\\s+(.*?)(?=--|$)"); - if (paramNomatcher.Success) - { - string paramNoStr = paramNomatcher.Groups[1].Value.Trim(); - string paramNoStrEn = await translateService.TranslateToEnglish(paramNoStr); - - // 提取 --no 之前的参数 - paramStr = paramStr.Substring(0, paramNomatcher.Index); - - // 替换 --no 参数 - paramStr = paramStr + paramNomatcher.Result("--no " + paramNoStrEn + " "); - } - } - return string.Concat(imageUrls) + text.Trim() + paramStr; - } - catch (Exception ex) - { - LogHelper.LogError(ex, "翻译提示词失败,使用原始提示词"); - return prompt; + return Results.BadRequest("request error : " + ex.Message); } } } diff --git a/src/EndpointServices/MJTransferEndpoint/MJPostModalService.cs b/src/EndpointServices/MJTransferEndpoint/MJPostModalService.cs index 75bbbab..1cb6594 100644 --- a/src/EndpointServices/MJTransferEndpoint/MJPostModalService.cs +++ b/src/EndpointServices/MJTransferEndpoint/MJPostModalService.cs @@ -2,7 +2,8 @@ using lai_transfer.Common.Helper; using lai_transfer.Common.Results; using lai_transfer.Endpoints; -using lai_transfer.Services; +using lai_transfer.Services.Translate; +using Microsoft.AspNetCore.Authorization; using System.Text.Json; namespace lai_transfer.EndpointServices.MJTransferEndpoint @@ -27,26 +28,35 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint { TransferAuthorizationResult transferAuthorizationResult = httpContext.GetAuthorizationItemsAndValidation(); string url = $"{transferAuthorizationResult.BaseUrl}/mj/submit/modal"; - // 设置HttpClient - using HttpClient client = new HttpClient(); - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}"); - client.Timeout = Timeout.InfiniteTimeSpan; // 强制翻译提示词 string prompt = JSONHelper.GetJsonPropertyString(model, "prompt") ?? string.Empty; + if (string.IsNullOrWhiteSpace(prompt)) + { + prompt = JSONHelper.GetJsonPropertyString(model, "Prompt") ?? string.Empty; + } // 使用HttpContext扩展方法获取翻译服务 - var translateService = ServiceLocator.GetRequiredService(); - prompt = await MJPostImagineService.TranslatePrompt(prompt, translateService); + var translateService = ServiceLocator.GetRequiredService(); + prompt = await translateService.TranslatePrompt(prompt); model = JSONHelper.SetJsonProperty(model, "prompt", prompt); // 删除回调参数 notifyHook string body = JSONHelper.RemoveJsonProperties(model, "notifyHook"); - // 发送请求 - var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); - string content = await response.Content.ReadAsStringAsync(); - return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + + TransferResult res = await RetryHelper.RetryAsync(async () => + { + // 设置HttpClient + using HttpClient client = new HttpClient(); + client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}"); + client.DefaultRequestHeaders.Add("mj-api-secret", transferAuthorizationResult.Token); + client.Timeout = Timeout.InfiniteTimeSpan; + var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); + string content = await response.Content.ReadAsStringAsync(); + return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + }, 5); + return res; } catch (Exception ex) { diff --git a/src/EndpointServices/MJTransferEndpoint/MJPostShortenService.cs b/src/EndpointServices/MJTransferEndpoint/MJPostShortenService.cs index 1d08e93..c237998 100644 --- a/src/EndpointServices/MJTransferEndpoint/MJPostShortenService.cs +++ b/src/EndpointServices/MJTransferEndpoint/MJPostShortenService.cs @@ -2,6 +2,7 @@ using lai_transfer.Common.Helper; using lai_transfer.Common.Results; using lai_transfer.Endpoints; +using Microsoft.AspNetCore.Authorization; using System.Text.Json; namespace lai_transfer.EndpointServices.MJTransferEndpoint @@ -26,17 +27,22 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint { TransferAuthorizationResult transferAuthorizationResult = httpContext.GetAuthorizationItemsAndValidation(); string url = $"{transferAuthorizationResult.BaseUrl}/mj/submit/shorten"; - - // 设置HttpClient - using HttpClient client = new HttpClient(); - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}"); - client.Timeout = Timeout.InfiniteTimeSpan; // 删除回调参数 notifyHook string body = JSONHelper.RemoveJsonProperties(model, "notifyHook"); - // 发送请求 - var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); - string content = await response.Content.ReadAsStringAsync(); - return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + + TransferResult res = await RetryHelper.RetryAsync(async () => + { + // 设置HttpClient + using HttpClient client = new HttpClient(); + client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}"); + client.DefaultRequestHeaders.Add("mj-api-secret", transferAuthorizationResult.Token); + client.Timeout = Timeout.InfiniteTimeSpan; + // 发送请求 + var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); + string content = await response.Content.ReadAsStringAsync(); + return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + }, 5); + return res; } catch (Exception ex) { diff --git a/src/EndpointServices/MJTransferEndpoint/MJPostSwapFaceService.cs b/src/EndpointServices/MJTransferEndpoint/MJPostSwapFaceService.cs index 9d82bb6..24aab98 100644 --- a/src/EndpointServices/MJTransferEndpoint/MJPostSwapFaceService.cs +++ b/src/EndpointServices/MJTransferEndpoint/MJPostSwapFaceService.cs @@ -2,6 +2,7 @@ using lai_transfer.Common.Helper; using lai_transfer.Common.Results; using lai_transfer.Endpoints; +using Microsoft.AspNetCore.Authorization; using System.Text.Json; namespace lai_transfer.EndpointServices.MJTransferEndpoint @@ -26,17 +27,22 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint { TransferAuthorizationResult transferAuthorizationResult = httpContext.GetAuthorizationItemsAndValidation(); string url = $"{transferAuthorizationResult.BaseUrl}/mj/insight-face/swap"; - - // 设置HttpClient - using HttpClient client = new(); - client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}"); - client.Timeout = Timeout.InfiniteTimeSpan; // 删除回调参数 notifyHook string body = JSONHelper.RemoveJsonProperties(model, "notifyHook"); - // 发送请求 - var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); - string content = await response.Content.ReadAsStringAsync(); - return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + + TransferResult res = await RetryHelper.RetryAsync(async () => + { + // 设置HttpClient + using HttpClient client = new(); + client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}"); + client.DefaultRequestHeaders.Add("mj-api-secret", transferAuthorizationResult.Token); + client.Timeout = Timeout.InfiniteTimeSpan; + // 发送请求 + var response = await client.PostAsync(url, new StringContent(body, System.Text.Encoding.UTF8, "application/json")); + string content = await response.Content.ReadAsStringAsync(); + return new TransferResult(content, response.Content.Headers.ContentType?.ToString() ?? "application/json", (int)response.StatusCode); + }, 5); + return res; } catch (Exception ex) { diff --git a/src/Examples/ServiceUsageExamples.cs b/src/Examples/ServiceUsageExamples.cs deleted file mode 100644 index 23cdd7b..0000000 --- a/src/Examples/ServiceUsageExamples.cs +++ /dev/null @@ -1,88 +0,0 @@ -using lai_transfer.Common.Extensions; -using lai_transfer.Common.Helper; -using lai_transfer.Services; -using System.Threading.Tasks; - -namespace lai_transfer.Examples -{ - /// - /// չʾʹ÷ȡչʾ - /// - public static class ServiceUsageExamples - { - /// - /// HttpContextijʹ÷ - /// - /// Http - public static async Task ExampleWithHttpContext(HttpContext httpContext) - { - // ʽ1ʹHttpContextչȡ - var translateService = httpContext.GetRequiredService(); - var loggerFactory = httpContext.GetService(); - var logger = loggerFactory?.CreateLogger("ServiceUsageExamples"); - - // ʹ÷ - string result = await translateService.TranslateToEnglish(""); - logger?.LogInformation($": {result}"); - } - - /// - /// ûHttpContextijʹ÷羲̨̬ȣ - /// - public static async Task ExampleWithoutHttpContext() - { - // ʽ2ʹȫַλȡ - var translateService = ServiceLocator.GetRequiredService(); - var loggerFactory = ServiceLocator.GetService(); - var logger = loggerFactory?.CreateLogger("ServiceUsageExamples"); - - // ʹ÷ - string result = await translateService.TranslateToEnglish(""); - logger?.LogInformation($": {result}"); - } - - /// - /// Ҫijʹ - /// - public static async Task ExampleWithScope() - { - // µ - using var scope = ServiceLocator.CreateScope(); - var scopedServices = scope.ServiceProvider; - - // лȡ - var translateService = scopedServices.GetRequiredService(); - - // ʹ÷ - string result = await translateService.TranslateToEnglish(""); - - // ʱԶͷԴ - } - - /// - /// ڶ˵㴦еʹʾ - /// - public static async Task EndpointExample(HttpContext httpContext) - { - try - { - // ֱӴHttpContextȡڷ - var translateService = httpContext.GetRequiredService(); - var loggerFactory = httpContext.GetRequiredService(); - var logger = loggerFactory.CreateLogger("ServiceUsageExamples"); - - // ҵ߼ - string prompt = "ı"; - string translatedPrompt = await translateService.TranslateToEnglish(prompt); - - logger.LogInformation($": {prompt} -> {translatedPrompt}"); - - return Results.Ok(new { original = prompt, translated = translatedPrompt }); - } - catch (Exception ex) - { - return Results.Problem($"ʧ: {ex.Message}"); - } - } - } -} \ No newline at end of file diff --git a/src/FodyWeavers.xml b/src/FodyWeavers.xml new file mode 100644 index 0000000..cc07b89 --- /dev/null +++ b/src/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/Model/Entity/MJTask.cs b/src/Model/Entity/MJTask.cs new file mode 100644 index 0000000..bad84b7 --- /dev/null +++ b/src/Model/Entity/MJTask.cs @@ -0,0 +1,59 @@ +using lai_transfer.Tool.Extensions; +using Realms; + +namespace lai_transfer.Model.Entity +{ + [MapTo("MJTask")] + public class MJTask : RealmObject + { + [PrimaryKey] + [MapTo("_id")] + public string ID { get; set; } = string.Empty; + + [MapTo("mjId")] + public string MJId { get; set; } + + [MapTo("type")] + public string Type { get; set; } + + [MapTo("status")] + public string Status { get; set; } + + [MapTo("baseUrl")] + public string BaseUrl { get; set; } + + [MapTo("property")] + public string Property { get; set; } + + [MapTo("authorizationResult")] + public string AuthorizationResult { get; set; } + + [MapTo("createdTime")] + public DateTimeOffset CreatedTime { get; set; } = BeijingTimeExtension.GetBeijingTime(); + + [MapTo("checkedTime")] + public DateTimeOffset CheckedTime { get; set; } = BeijingTimeExtension.GetBeijingTime(); + } + + public class MJTaskDTO + { + + public string ID { get; set; } = string.Empty; + + public string MJId { get; set; } + + public string Type { get; set; } + + public string Status { get; set; } + + public string BaseUrl { get; set; } + + public string Property { get; set; } + + public string AuthorizationResult { get; set; } + + public DateTimeOffset CreatedTime { get; set; } = BeijingTimeExtension.GetBeijingTime(); + + public DateTimeOffset CheckedTime { get; set; } = BeijingTimeExtension.GetBeijingTime(); + } +} diff --git a/src/Model/Midjourney/MidjourneyRequest.cs b/src/Model/Midjourney/MidjourneyRequest.cs new file mode 100644 index 0000000..6d23d93 --- /dev/null +++ b/src/Model/Midjourney/MidjourneyRequest.cs @@ -0,0 +1,10 @@ +namespace lai_transfer.Model.Midjourney +{ + public class MidjourneyRequest + { + public class FetchListByCondition + { + public List Ids { get; set; } = []; + } + } +} diff --git a/src/Model/Midjourney/MidjourneyTaskResponse.cs b/src/Model/Midjourney/MidjourneyTaskResponse.cs new file mode 100644 index 0000000..8fbc5e7 --- /dev/null +++ b/src/Model/Midjourney/MidjourneyTaskResponse.cs @@ -0,0 +1,158 @@ +using System.Text.Json.Serialization; + +namespace lai_transfer.Model.Midjourney +{ + public class MidjourneyTaskResponse + { + + public class TaskResponse + { + [JsonPropertyName("id")] + public string Id { get; set; } + + [JsonPropertyName("accountId")] + public string AccountId { get; set; } + + [JsonPropertyName("action")] + public string Action { get; set; } + + [JsonPropertyName("status")] + public string Status { get; set; } + + [JsonPropertyName("mode")] + public string Mode { get; set; } + + [JsonPropertyName("prompt")] + public string Prompt { get; set; } + + [JsonPropertyName("promptEn")] + public string PromptEn { get; set; } + + [JsonPropertyName("description")] + public string Description { get; set; } + + [JsonPropertyName("submitTime")] + public long? SubmitTime { get; set; } + + [JsonPropertyName("startTime")] + public long? StartTime { get; set; } + + [JsonPropertyName("finishTime")] + public long? FinishTime { get; set; } + + [JsonPropertyName("progress")] + public string Progress { get; set; } + + [JsonPropertyName("imageUrl")] + public string ImageUrl { get; set; } + + [JsonPropertyName("imageUrls")] + public List ImageUrls { get; set; } + + [JsonPropertyName("videoUrl")] + public string? VideoUrl { get; set; } + + [JsonPropertyName("videoUrls")] + public object? VideoUrls { get; set; } + + [JsonPropertyName("imageHeight")] + public int? ImageHeight { get; set; } + + [JsonPropertyName("imageWidth")] + public int? ImageWidth { get; set; } + + [JsonPropertyName("failReason")] + public string? FailReason { get; set; } + + [JsonPropertyName("notifyHook")] + public string NotifyHook { get; set; } + + [JsonPropertyName("state")] + public object? State { get; set; } + + [JsonPropertyName("buttons")] + public List