新增提示词翻译 所有的提示词 中文翻译为英文!!!
This commit is contained in:
parent
ee299c8538
commit
1f71879e0f
4
.gitignore
vendored
4
.gitignore
vendored
@ -360,4 +360,6 @@ MigrationBackup/
|
|||||||
.ionide/
|
.ionide/
|
||||||
|
|
||||||
# Fody - auto-generated XML schema
|
# Fody - auto-generated XML schema
|
||||||
FodyWeavers.xsd
|
FodyWeavers.xsd
|
||||||
|
/src/Configuration/config/transfer.json
|
||||||
|
/src/Configuration/config/transfer.json
|
||||||
|
|||||||
@ -55,5 +55,50 @@ namespace lai_transfer.Common.Extensions
|
|||||||
return fullPath;
|
return fullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从HttpContext的RequestServices中获取服务
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">服务类型</typeparam>
|
||||||
|
/// <param name="httpContext">Http上下文</param>
|
||||||
|
/// <returns>服务实例,如果未找到则返回null</returns>
|
||||||
|
public static T? GetService<T>(this HttpContext httpContext) where T : class
|
||||||
|
{
|
||||||
|
return httpContext.RequestServices.GetService<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从HttpContext的RequestServices中获取必需的服务
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">服务类型</typeparam>
|
||||||
|
/// <param name="httpContext">Http上下文</param>
|
||||||
|
/// <returns>服务实例</returns>
|
||||||
|
/// <exception cref="InvalidOperationException">如果服务未注册则抛出异常</exception>
|
||||||
|
public static T GetRequiredService<T>(this HttpContext httpContext) where T : notnull
|
||||||
|
{
|
||||||
|
return httpContext.RequestServices.GetRequiredService<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从HttpContext的RequestServices中获取服务(非泛型版本)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">Http上下文</param>
|
||||||
|
/// <param name="serviceType">服务类型</param>
|
||||||
|
/// <returns>服务实例,如果未找到则返回null</returns>
|
||||||
|
public static object? GetService(this HttpContext httpContext, Type serviceType)
|
||||||
|
{
|
||||||
|
return httpContext.RequestServices.GetService(serviceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从HttpContext的RequestServices中获取必需的服务(非泛型版本)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">Http上下文</param>
|
||||||
|
/// <param name="serviceType">服务类型</param>
|
||||||
|
/// <returns>服务实例</returns>
|
||||||
|
/// <exception cref="InvalidOperationException">如果服务未注册则抛出异常</exception>
|
||||||
|
public static object GetRequiredService(this HttpContext httpContext, Type serviceType)
|
||||||
|
{
|
||||||
|
return httpContext.RequestServices.GetRequiredService(serviceType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
using lai_transfer.Common.Filters;
|
using lai_transfer.Common.Filters;
|
||||||
using lai_transfer.Configuration;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
|
||||||
|
|
||||||
namespace lai_transfer.Common.Extensions
|
namespace lai_transfer.Common.Extensions
|
||||||
{
|
{
|
||||||
|
|||||||
@ -62,8 +62,6 @@
|
|||||||
return TypedResults.Unauthorized();
|
return TypedResults.Unauthorized();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6,14 +6,6 @@ namespace lai_transfer.Common.Helper
|
|||||||
{
|
{
|
||||||
private static readonly ILogger _logger = LogHelper.GetLogger<ConfigHelper>();
|
private static readonly ILogger _logger = LogHelper.GetLogger<ConfigHelper>();
|
||||||
|
|
||||||
// 存储Origin配置
|
|
||||||
public static class Origin
|
|
||||||
{
|
|
||||||
// 将private set改为internal set,允许同一程序集中的代码设置属性值
|
|
||||||
public static string BaseUrl { get; internal set; }
|
|
||||||
public static string Token { get; internal set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化配置
|
// 初始化配置
|
||||||
public static void Initialize()
|
public static void Initialize()
|
||||||
{
|
{
|
||||||
@ -24,15 +16,105 @@ namespace lai_transfer.Common.Helper
|
|||||||
// 读取配置文件
|
// 读取配置文件
|
||||||
var reader = new JsonConfigReader("Configuration/config/transfer.json");
|
var reader = new JsonConfigReader("Configuration/config/transfer.json");
|
||||||
|
|
||||||
// 加载Origin配置
|
// 初始化Origin配置
|
||||||
Origin.BaseUrl = reader.GetString("Origin.BaseUrl") ?? string.Empty;
|
Origin.Init(reader);
|
||||||
Origin.Token = reader.GetString("Origin.Token") ?? string.Empty;
|
|
||||||
|
Translate.Init(reader);
|
||||||
|
|
||||||
_logger.LogInformation("配置加载完成");
|
_logger.LogInformation("配置加载完成");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "加载配置文件失败");
|
_logger.LogError(ex, "加载配置文件失败");
|
||||||
|
// 报错,结束程序运行
|
||||||
|
throw new InvalidOperationException("无法加载应用程序配置,请检查配置文件是否存在或格式是否正确。", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Translate
|
||||||
|
{
|
||||||
|
// 将private set改为internal set,允许同一程序集中的代码设置属性值
|
||||||
|
public static bool Enable { get; internal set; } = false;
|
||||||
|
|
||||||
|
// 安全模式 会优先百度 百度 报错 再使用OpenAI
|
||||||
|
public static string Model { get; internal set; } = "BAIDU";
|
||||||
|
|
||||||
|
public static string BaiduAppId { get; internal set; } = string.Empty;
|
||||||
|
public static string BaiduAppSecret { get; internal set; } = string.Empty;
|
||||||
|
public static string OpenaiGptApiUrl { get; internal set; } = string.Empty;
|
||||||
|
public static string OpenaiGptApiKey { get; internal set; } = string.Empty;
|
||||||
|
public static TimeSpan TimeOut { get; internal set; } = TimeSpan.FromSeconds(10);
|
||||||
|
|
||||||
|
public static string OpenaiGptModel { get; internal set; } = "gpt-4o-mini";
|
||||||
|
|
||||||
|
public static int OpenaiGptMaxTokens { get; internal set; } = 2048;
|
||||||
|
|
||||||
|
public static double OpenaiGptTemperature { get; internal set; } = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化翻译配置
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
public static void Init(JsonConfigReader reader)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_logger.LogInformation("正在加载翻译配置...");
|
||||||
|
// 加载翻译配置
|
||||||
|
Enable = reader.GetBool("Translate.Enable") ?? false;
|
||||||
|
Model = reader.GetString("Translate.Model") ?? "BAIDU";
|
||||||
|
BaiduAppId = reader.GetString("Translate.BaiduAppId") ?? string.Empty;
|
||||||
|
BaiduAppSecret = reader.GetString("Translate.BaiduAppSecret") ?? string.Empty;
|
||||||
|
|
||||||
|
OpenaiGptApiUrl = reader.GetString("Translate.OpenaiGptApiUrl") ?? "https://laitooo.net";
|
||||||
|
OpenaiGptApiKey = reader.GetString("Translate.OpenaiGptApiKey") ?? string.Empty;
|
||||||
|
OpenaiGptModel = reader.GetString("Translate.OpenaiGptModel") ?? "Doubao-lite-32k";
|
||||||
|
|
||||||
|
OpenaiGptMaxTokens = reader.GetInt("Translate.OpenaiGptMaxTokens") ?? 2048;
|
||||||
|
OpenaiGptTemperature = reader.GetDouble("Translate.OpenaiGptTemperature") ?? 0;
|
||||||
|
|
||||||
|
TimeOut = TimeSpan.FromSeconds(reader.GetInt("Translate.TimeOut") ?? 20);
|
||||||
|
_logger.LogInformation("翻译配置加载完成");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "加载翻译配置失败");
|
||||||
|
// 报错,结束程序运行
|
||||||
|
throw new InvalidOperationException("无法加载翻译配置,请检查配置文件是否存在或格式是否正确。", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 存储Origin配置
|
||||||
|
public static class Origin
|
||||||
|
{
|
||||||
|
// 将private set改为internal set,允许同一程序集中的代码设置属性值
|
||||||
|
public static string BaseUrl { get; internal set; } = string.Empty;
|
||||||
|
public static string Token { get; internal set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化Origin配置
|
||||||
|
/// </summary>
|
||||||
|
public static void Init(JsonConfigReader reader)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
_logger.LogInformation("正在加载Origin配置...");
|
||||||
|
// 加载Origin配置
|
||||||
|
BaseUrl = reader.GetString("Origin.BaseUrl") ?? string.Empty;
|
||||||
|
Token = reader.GetString("Origin.Token") ?? string.Empty;
|
||||||
|
|
||||||
|
_logger.LogInformation("Origin配置加载完成");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "加载Origin配置失败");
|
||||||
|
// 报错,结束程序运行
|
||||||
|
throw new InvalidOperationException("无法加载Origin配置,请检查配置文件是否存在或格式是否正确。", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,5 +34,244 @@ namespace lai_transfer.Common.Helper
|
|||||||
|
|
||||||
return Encoding.UTF8.GetString(stream.ToArray());
|
return Encoding.UTF8.GetString(stream.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定属性的值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">JSON元素</param>
|
||||||
|
/// <param name="propertyName">属性名称</param>
|
||||||
|
/// <returns>属性值的JsonElement,如果属性不存在则返回null</returns>
|
||||||
|
public static JsonElement? GetJsonProperty(JsonElement element, string propertyName)
|
||||||
|
{
|
||||||
|
// 检查元素是否为对象
|
||||||
|
if (element.ValueKind != JsonValueKind.Object)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// 尝试获取属性
|
||||||
|
if (element.TryGetProperty(propertyName, out JsonElement property))
|
||||||
|
{
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定属性的字符串值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">JSON元素</param>
|
||||||
|
/// <param name="propertyName">属性名称</param>
|
||||||
|
/// <returns>属性的字符串值,如果属性不存在或无法转换则返回null</returns>
|
||||||
|
public static string? GetJsonPropertyString(JsonElement element, string propertyName)
|
||||||
|
{
|
||||||
|
var property = GetJsonProperty(element, propertyName);
|
||||||
|
return property?.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定属性的整数值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">JSON元素</param>
|
||||||
|
/// <param name="propertyName">属性名称</param>
|
||||||
|
/// <returns>属性的整数值,如果属性不存在或无法转换则返回null</returns>
|
||||||
|
public static int? GetJsonPropertyInt(JsonElement element, string propertyName)
|
||||||
|
{
|
||||||
|
var property = GetJsonProperty(element, propertyName);
|
||||||
|
if (property.HasValue && property.Value.TryGetInt32(out int value))
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定属性的布尔值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">JSON元素</param>
|
||||||
|
/// <param name="propertyName">属性名称</param>
|
||||||
|
/// <returns>属性的布尔值,如果属性不存在或无法转换则返回null</returns>
|
||||||
|
public static bool? GetJsonPropertyBool(JsonElement element, string propertyName)
|
||||||
|
{
|
||||||
|
var property = GetJsonProperty(element, propertyName);
|
||||||
|
if (property.HasValue)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return property.Value.GetBoolean();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置或更新JSON对象中指定属性的值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">JSON元素</param>
|
||||||
|
/// <param name="propertyName">属性名称</param>
|
||||||
|
/// <param name="value">要设置的值</param>
|
||||||
|
/// <returns>更新后的JsonElement</returns>
|
||||||
|
public static JsonElement SetJsonProperty(JsonElement element, string propertyName, object? value)
|
||||||
|
{
|
||||||
|
// 检查元素是否为对象
|
||||||
|
if (element.ValueKind != JsonValueKind.Object)
|
||||||
|
return element;
|
||||||
|
|
||||||
|
using var stream = new MemoryStream();
|
||||||
|
using var writer = new Utf8JsonWriter(stream);
|
||||||
|
|
||||||
|
writer.WriteStartObject();
|
||||||
|
|
||||||
|
bool propertyFound = false;
|
||||||
|
|
||||||
|
// 遍历所有现有属性
|
||||||
|
foreach (var property in element.EnumerateObject())
|
||||||
|
{
|
||||||
|
if (property.Name == propertyName)
|
||||||
|
{
|
||||||
|
// 写入新值
|
||||||
|
WritePropertyValue(writer, propertyName, value);
|
||||||
|
propertyFound = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 保留现有属性
|
||||||
|
property.WriteTo(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果属性不存在,添加新属性
|
||||||
|
if (!propertyFound)
|
||||||
|
{
|
||||||
|
WritePropertyValue(writer, propertyName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteEndObject();
|
||||||
|
writer.Flush();
|
||||||
|
|
||||||
|
// 解析生成的JSON并返回JsonElement
|
||||||
|
var jsonString = Encoding.UTF8.GetString(stream.ToArray());
|
||||||
|
using var document = JsonDocument.Parse(jsonString);
|
||||||
|
return document.RootElement.Clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置或更新JSON对象中指定属性的值,返回JSON字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">JSON元素</param>
|
||||||
|
/// <param name="propertyName">属性名称</param>
|
||||||
|
/// <param name="value">要设置的值</param>
|
||||||
|
/// <returns>更新后的JSON字符串</returns>
|
||||||
|
public static string SetJsonPropertyAsString(JsonElement element, string propertyName, object? value)
|
||||||
|
{
|
||||||
|
var updatedElement = SetJsonProperty(element, propertyName, value);
|
||||||
|
return updatedElement.GetRawText();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置多个属性的值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="element">JSON元素</param>
|
||||||
|
/// <param name="properties">属性名称和值的字典</param>
|
||||||
|
/// <returns>更新后的JSON字符串</returns>
|
||||||
|
public static string SetJsonProperties(JsonElement element, Dictionary<string, object?> properties)
|
||||||
|
{
|
||||||
|
// 检查元素是否为对象
|
||||||
|
if (element.ValueKind != JsonValueKind.Object)
|
||||||
|
return element.GetRawText();
|
||||||
|
|
||||||
|
using var stream = new MemoryStream();
|
||||||
|
using var writer = new Utf8JsonWriter(stream);
|
||||||
|
|
||||||
|
writer.WriteStartObject();
|
||||||
|
|
||||||
|
var processedProperties = new HashSet<string>();
|
||||||
|
|
||||||
|
// 遍历所有现有属性
|
||||||
|
foreach (var property in element.EnumerateObject())
|
||||||
|
{
|
||||||
|
if (properties.ContainsKey(property.Name))
|
||||||
|
{
|
||||||
|
// 写入新值
|
||||||
|
WritePropertyValue(writer, property.Name, properties[property.Name]);
|
||||||
|
processedProperties.Add(property.Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 保留现有属性
|
||||||
|
property.WriteTo(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加不存在的新属性
|
||||||
|
foreach (var kvp in properties)
|
||||||
|
{
|
||||||
|
if (!processedProperties.Contains(kvp.Key))
|
||||||
|
{
|
||||||
|
WritePropertyValue(writer, kvp.Key, kvp.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteEndObject();
|
||||||
|
writer.Flush();
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(stream.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写入属性值到JSON writer
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">JSON writer</param>
|
||||||
|
/// <param name="propertyName">属性名称</param>
|
||||||
|
/// <param name="value">属性值</param>
|
||||||
|
private static void WritePropertyValue(Utf8JsonWriter writer, string propertyName, object? value)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName(propertyName);
|
||||||
|
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case null:
|
||||||
|
writer.WriteNullValue();
|
||||||
|
break;
|
||||||
|
case string stringValue:
|
||||||
|
writer.WriteStringValue(stringValue);
|
||||||
|
break;
|
||||||
|
case int intValue:
|
||||||
|
writer.WriteNumberValue(intValue);
|
||||||
|
break;
|
||||||
|
case long longValue:
|
||||||
|
writer.WriteNumberValue(longValue);
|
||||||
|
break;
|
||||||
|
case float floatValue:
|
||||||
|
writer.WriteNumberValue(floatValue);
|
||||||
|
break;
|
||||||
|
case double doubleValue:
|
||||||
|
writer.WriteNumberValue(doubleValue);
|
||||||
|
break;
|
||||||
|
case decimal decimalValue:
|
||||||
|
writer.WriteNumberValue(decimalValue);
|
||||||
|
break;
|
||||||
|
case bool boolValue:
|
||||||
|
writer.WriteBooleanValue(boolValue);
|
||||||
|
break;
|
||||||
|
case DateTime dateTimeValue:
|
||||||
|
writer.WriteStringValue(dateTimeValue.ToString("O")); // ISO 8601 format
|
||||||
|
break;
|
||||||
|
case JsonElement jsonElement:
|
||||||
|
jsonElement.WriteTo(writer);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// 对于复杂对象,序列化为JSON字符串
|
||||||
|
var jsonString = JsonSerializer.Serialize(value);
|
||||||
|
using var doc = JsonDocument.Parse(jsonString);
|
||||||
|
doc.RootElement.WriteTo(writer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
83
src/Common/Helper/ServiceLocator.cs
Normal file
83
src/Common/Helper/ServiceLocator.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
namespace lai_transfer.Common.Helper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 全局服务定位器,用于在没有HttpContext的地方获取依赖注入的服务
|
||||||
|
/// </summary>
|
||||||
|
public static class ServiceLocator
|
||||||
|
{
|
||||||
|
private static IServiceProvider? _serviceProvider;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化服务提供者(在Program.cs中调用)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceProvider">服务提供者</param>
|
||||||
|
public static void Initialize(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取服务
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">服务类型</typeparam>
|
||||||
|
/// <returns>服务实例,如果未找到则返回null</returns>
|
||||||
|
public static T? GetService<T>() where T : class
|
||||||
|
{
|
||||||
|
EnsureInitialized();
|
||||||
|
return _serviceProvider!.GetService<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取必需的服务
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">服务类型</typeparam>
|
||||||
|
/// <returns>服务实例</returns>
|
||||||
|
/// <exception cref="InvalidOperationException">如果服务未注册则抛出异常</exception>
|
||||||
|
public static T GetRequiredService<T>() where T : notnull
|
||||||
|
{
|
||||||
|
EnsureInitialized();
|
||||||
|
return _serviceProvider!.GetRequiredService<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取服务(非泛型版本)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceType">服务类型</param>
|
||||||
|
/// <returns>服务实例,如果未找到则返回null</returns>
|
||||||
|
public static object? GetService(Type serviceType)
|
||||||
|
{
|
||||||
|
EnsureInitialized();
|
||||||
|
return _serviceProvider!.GetService(serviceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取必需的服务(非泛型版本)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceType">服务类型</param>
|
||||||
|
/// <returns>服务实例</returns>
|
||||||
|
/// <exception cref="InvalidOperationException">如果服务未注册则抛出异常</exception>
|
||||||
|
public static object GetRequiredService(Type serviceType)
|
||||||
|
{
|
||||||
|
EnsureInitialized();
|
||||||
|
return _serviceProvider!.GetRequiredService(serviceType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建服务范围
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>服务范围</returns>
|
||||||
|
public static IServiceScope CreateScope()
|
||||||
|
{
|
||||||
|
EnsureInitialized();
|
||||||
|
return _serviceProvider!.CreateScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EnsureInitialized()
|
||||||
|
{
|
||||||
|
if (_serviceProvider == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("ServiceLocator 未初始化。请在 Program.cs 中调用 ServiceLocator.Initialize(app.Services)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/Configuration/config/transfer-temp.json
Normal file
19
src/Configuration/config/transfer-temp.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"Origin": {
|
||||||
|
"BaseUrl": "https://mjapi.bzu.cn",
|
||||||
|
"Token": "23830faf80e8e69"
|
||||||
|
},
|
||||||
|
"Translate": {
|
||||||
|
"Enable": true,
|
||||||
|
"Model": "BAIDU",
|
||||||
|
"BaiduAppId": "2024032500",
|
||||||
|
"BaiduAppSecret": "hcCG8H",
|
||||||
|
"OpenaiGptApiUrl": "https://laitool.net/v1/chat/completions",
|
||||||
|
|
||||||
|
"OpenaiGptApiKey": "sk-r5",
|
||||||
|
"OpenaiGptModel": "Doubao-pro-32k",
|
||||||
|
"OpenaiGptMaxTokens": 2048,
|
||||||
|
"OpenaiGptTemperature": 0,
|
||||||
|
"TimeOut": 20
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"Origin": {
|
|
||||||
"BaseUrl": "https://mjapi.bzu.cn",
|
|
||||||
"Token": "23830faf80e8e69988b3fcd9aa08e9ad123"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,12 +1,17 @@
|
|||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using lai_transfer.Configuration;
|
using lai_transfer.Configuration;
|
||||||
using lai_transfer.Model.Entity;
|
using lai_transfer.Model.Entity;
|
||||||
|
using lai_transfer.Services;
|
||||||
|
using lai_transfer.EndpointServices.MJTransferEndpoint;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Midjourney.Infrastructure.Services;
|
||||||
|
using lai_transfer.Common.Helper;
|
||||||
|
|
||||||
namespace lai_transfer
|
namespace lai_transfer
|
||||||
{
|
{
|
||||||
@ -40,11 +45,31 @@ namespace lai_transfer
|
|||||||
// 添加JWT认证配置
|
// 添加JWT认证配置
|
||||||
builder.Services.AddJWTAuthentication();
|
builder.Services.AddJWTAuthentication();
|
||||||
|
|
||||||
|
builder.Services.AddService();
|
||||||
|
|
||||||
// 注册校验
|
// 注册校验
|
||||||
builder.Services.AddValidatorsFromAssembly(typeof(ConfigureServices).Assembly);
|
builder.Services.AddValidatorsFromAssembly(typeof(ConfigureServices).Assembly);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册一些服务
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="services"></param>
|
||||||
|
private static void AddService(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
if (ConfigHelper.Translate.Model == "GPT")
|
||||||
|
{
|
||||||
|
// 翻译服务注入
|
||||||
|
services.AddSingleton<ITranslateService, GPTTranslateService>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
services.AddSingleton<ITranslateService, BaiduTranslateService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// JWT 配置
|
/// JWT 配置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -220,7 +220,7 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
|||||||
|
|
||||||
if (isPartner && !string.IsNullOrEmpty(partnerTaskId))
|
if (isPartner && !string.IsNullOrEmpty(partnerTaskId))
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"处理合作伙伴任务: {partnerTaskId}");
|
_logger.LogInformation($"处理合作伙伴任务: {partnerTaskId}, TaskId : {data?.id ?? string.Empty}");
|
||||||
|
|
||||||
// 1111111111
|
// 1111111111
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
|||||||
|
|
||||||
if (isOfficial && !string.IsNullOrEmpty(officialTaskId))
|
if (isOfficial && !string.IsNullOrEmpty(officialTaskId))
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"处理官方任务: {officialTaskId}");
|
_logger.LogInformation($"处理官方任务: {officialTaskId}, TaskId : {data?.id ?? string.Empty}");
|
||||||
|
|
||||||
// 直接遍历,让异常处理兜底
|
// 直接遍历,让异常处理兜底
|
||||||
var imageUrls = new List<object>();
|
var imageUrls = new List<object>();
|
||||||
@ -336,7 +336,7 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
|||||||
|
|
||||||
if (isYouChuan && !string.IsNullOrEmpty(youChuanTaskId))
|
if (isYouChuan && !string.IsNullOrEmpty(youChuanTaskId))
|
||||||
{
|
{
|
||||||
_logger.LogInformation($"处理悠船任务: {youChuanTaskId}");
|
_logger.LogInformation($"处理悠船任务: {youChuanTaskId}, TaskId : {data?.id ?? string.Empty}");
|
||||||
|
|
||||||
// 直接遍历,让异常处理兜底
|
// 直接遍历,让异常处理兜底
|
||||||
var imageUrls = new List<object>();
|
var imageUrls = new List<object>();
|
||||||
|
|||||||
@ -1,23 +1,26 @@
|
|||||||
using lai_transfer.Common.Extensions;
|
using lai_transfer.Common.Extensions;
|
||||||
using lai_transfer.Common.Helper;
|
using lai_transfer.Common.Helper;
|
||||||
using lai_transfer.Common.Results;
|
using lai_transfer.Common.Results;
|
||||||
using lai_transfer.Configuration;
|
|
||||||
using lai_transfer.Endpoints;
|
using lai_transfer.Endpoints;
|
||||||
|
using lai_transfer.Services;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
||||||
{
|
{
|
||||||
public class MJPostImagineService : IEndpoint
|
public class MJPostImagineService : IEndpoint
|
||||||
{
|
{
|
||||||
|
private static readonly ILogger _logger = LogHelper.GetLogger<MJPostImagineService>();
|
||||||
|
|
||||||
public static void Map(IEndpointRouteBuilder app) => app
|
public static void Map(IEndpointRouteBuilder app) => app
|
||||||
.MapPost("/submit/imagine", Handle)
|
.MapPost("/submit/imagine", Handle)
|
||||||
.WithSummary("Midjourney 提交 Imagine 任务")
|
.WithSummary("Midjourney 提交 Imagine 任务")
|
||||||
.WithMJAuthorizationHeader();
|
.WithMJAuthorizationHeader();
|
||||||
|
|
||||||
private static async Task<IResult> Handle(JsonElement model, HttpContext httpContext, ILogger<MJPostImagineService> logger)
|
private static async Task<IResult> Handle(JsonElement model, HttpContext httpContext)
|
||||||
{
|
{
|
||||||
(string content, string contentType, int statusCode) = await SendOriginalImagine(model, httpContext, logger);
|
(string content, string contentType, int statusCode) = await SendOriginalImagine(model, httpContext);
|
||||||
return Results.Text(content, contentType, statusCode: statusCode);
|
return Results.Text(content, contentType, statusCode: statusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +30,7 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
|||||||
/// <param name="model"></param>
|
/// <param name="model"></param>
|
||||||
/// <param name="httpContext"></param>
|
/// <param name="httpContext"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private static async Task<(string content, string contentType, int statusCode)> SendOriginalImagine(JsonElement model, HttpContext httpContext, ILogger<MJPostImagineService> logger)
|
private static async Task<(string content, string contentType, int statusCode)> SendOriginalImagine(JsonElement model, HttpContext httpContext)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -39,9 +42,18 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
|||||||
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {authorizationResult.Token}");
|
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {authorizationResult.Token}");
|
||||||
client.Timeout = Timeout.InfiniteTimeSpan;
|
client.Timeout = Timeout.InfiniteTimeSpan;
|
||||||
|
|
||||||
// 删除回调参数 notifyHook
|
// 强制翻译提示词
|
||||||
|
string prompt = JSONHelper.GetJsonPropertyString(model, "prompt") ?? string.Empty;
|
||||||
|
|
||||||
|
// 使用HttpContext扩展方法获取翻译服务
|
||||||
|
var translateService = ServiceLocator.GetRequiredService<ITranslateService>();
|
||||||
|
prompt = await TranslatePrompt(prompt, translateService);
|
||||||
|
|
||||||
|
model = JSONHelper.SetJsonProperty(model, "prompt", prompt);
|
||||||
|
|
||||||
|
// 删除回调参数 notifyHook
|
||||||
string body = JSONHelper.RemoveJsonProperties(model, "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"));
|
var response = await client.PostAsync(url, new StringContent(body, Encoding.UTF8, "application/json"));
|
||||||
string content = await response.Content.ReadAsStringAsync();
|
string content = await response.Content.ReadAsStringAsync();
|
||||||
@ -49,10 +61,81 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogError(ex, $"请求 {httpContext.GetFullRequestPath()} 失败");
|
_logger.LogError(ex, $"请求 {httpContext.GetFullRequestPath()} 失败");
|
||||||
// 处理异常,返回错误信息
|
// 处理异常,返回错误信息
|
||||||
return (ex.Message, "application/json", StatusCodes.Status500InternalServerError);
|
return (ex.Message, "application/json", StatusCodes.Status500InternalServerError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 翻译提示词
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prompt">原始提示词</param>
|
||||||
|
/// <param name="translateService">翻译服务</param>
|
||||||
|
/// <returns>翻译后的提示词</returns>
|
||||||
|
public static async Task<string> 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<string> imageUrls = new List<string>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
using lai_transfer.Common.Helper;
|
using lai_transfer.Common.Helper;
|
||||||
using lai_transfer.Common.Results;
|
using lai_transfer.Common.Results;
|
||||||
using lai_transfer.Endpoints;
|
using lai_transfer.Endpoints;
|
||||||
|
using lai_transfer.Services;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
||||||
@ -30,6 +31,16 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
|||||||
using HttpClient client = new HttpClient();
|
using HttpClient client = new HttpClient();
|
||||||
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}");
|
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {transferAuthorizationResult.Token}");
|
||||||
client.Timeout = Timeout.InfiniteTimeSpan;
|
client.Timeout = Timeout.InfiniteTimeSpan;
|
||||||
|
|
||||||
|
// 强制翻译提示词
|
||||||
|
string prompt = JSONHelper.GetJsonPropertyString(model, "prompt") ?? string.Empty;
|
||||||
|
|
||||||
|
// 使用HttpContext扩展方法获取翻译服务
|
||||||
|
var translateService = ServiceLocator.GetRequiredService<ITranslateService>();
|
||||||
|
prompt = await MJPostImagineService.TranslatePrompt(prompt, translateService);
|
||||||
|
|
||||||
|
model = JSONHelper.SetJsonProperty(model, "prompt", prompt);
|
||||||
|
|
||||||
// 删除回调参数 notifyHook
|
// 删除回调参数 notifyHook
|
||||||
string body = JSONHelper.RemoveJsonProperties(model, "notifyHook");
|
string body = JSONHelper.RemoveJsonProperties(model, "notifyHook");
|
||||||
// 发送请求
|
// 发送请求
|
||||||
|
|||||||
@ -9,7 +9,6 @@ namespace lai_transfer.EndpointServices.MJTransferEndpoint
|
|||||||
{
|
{
|
||||||
public class MJPostUploadDiscordImages : IEndpoint
|
public class MJPostUploadDiscordImages : IEndpoint
|
||||||
{
|
{
|
||||||
|
|
||||||
private static readonly ILogger _logger = LogHelper.GetLogger<MJPostUploadDiscordImages>();
|
private static readonly ILogger _logger = LogHelper.GetLogger<MJPostUploadDiscordImages>();
|
||||||
public static void Map(IEndpointRouteBuilder app) => app
|
public static void Map(IEndpointRouteBuilder app) => app
|
||||||
.MapPost("/submit/upload-discord-images", Handle)
|
.MapPost("/submit/upload-discord-images", Handle)
|
||||||
|
|||||||
88
src/Examples/ServiceUsageExamples.cs
Normal file
88
src/Examples/ServiceUsageExamples.cs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
using lai_transfer.Common.Extensions;
|
||||||
|
using lai_transfer.Common.Helper;
|
||||||
|
using lai_transfer.Services;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace lai_transfer.Examples
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 展示如何使用服务获取扩展方法的示例
|
||||||
|
/// </summary>
|
||||||
|
public static class ServiceUsageExamples
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 在有HttpContext的场景下使用服务
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpContext">Http上下文</param>
|
||||||
|
public static async Task ExampleWithHttpContext(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
// 方式1:使用HttpContext扩展方法获取服务
|
||||||
|
var translateService = httpContext.GetRequiredService<ITranslateService>();
|
||||||
|
var loggerFactory = httpContext.GetService<ILoggerFactory>();
|
||||||
|
var logger = loggerFactory?.CreateLogger("ServiceUsageExamples");
|
||||||
|
|
||||||
|
// 使用服务
|
||||||
|
string result = await translateService.TranslateToEnglish("你好世界");
|
||||||
|
logger?.LogInformation($"翻译结果: {result}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在没有HttpContext的场景下使用服务(如静态方法、后台任务等)
|
||||||
|
/// </summary>
|
||||||
|
public static async Task ExampleWithoutHttpContext()
|
||||||
|
{
|
||||||
|
// 方式2:使用全局服务定位器获取服务
|
||||||
|
var translateService = ServiceLocator.GetRequiredService<ITranslateService>();
|
||||||
|
var loggerFactory = ServiceLocator.GetService<ILoggerFactory>();
|
||||||
|
var logger = loggerFactory?.CreateLogger("ServiceUsageExamples");
|
||||||
|
|
||||||
|
// 使用服务
|
||||||
|
string result = await translateService.TranslateToEnglish("你好世界");
|
||||||
|
logger?.LogInformation($"翻译结果: {result}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在需要服务作用域的场景下使用
|
||||||
|
/// </summary>
|
||||||
|
public static async Task ExampleWithScope()
|
||||||
|
{
|
||||||
|
// 创建新的作用域
|
||||||
|
using var scope = ServiceLocator.CreateScope();
|
||||||
|
var scopedServices = scope.ServiceProvider;
|
||||||
|
|
||||||
|
// 从作用域中获取服务
|
||||||
|
var translateService = scopedServices.GetRequiredService<ITranslateService>();
|
||||||
|
|
||||||
|
// 使用服务
|
||||||
|
string result = await translateService.TranslateToEnglish("你好世界");
|
||||||
|
|
||||||
|
// 作用域结束时会自动释放资源
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 在端点处理器中的使用示例
|
||||||
|
/// </summary>
|
||||||
|
public static async Task<IResult> EndpointExample(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 直接从HttpContext获取服务,无需在方法参数中声明
|
||||||
|
var translateService = httpContext.GetRequiredService<ITranslateService>();
|
||||||
|
var loggerFactory = httpContext.GetRequiredService<ILoggerFactory>();
|
||||||
|
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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,6 +16,9 @@ app.Configure();
|
|||||||
LogHelper.Initialize(app.Services.GetRequiredService<ILoggerFactory>());
|
LogHelper.Initialize(app.Services.GetRequiredService<ILoggerFactory>());
|
||||||
ConfigHelper.Initialize();
|
ConfigHelper.Initialize();
|
||||||
|
|
||||||
|
// 初始化服务定位器
|
||||||
|
ServiceLocator.Initialize(app.Services);
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
// Configure the HTTP request pipeline.
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
|
|||||||
104
src/Services/BaiduTranslateService.cs
Normal file
104
src/Services/BaiduTranslateService.cs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
|
||||||
|
using lai_transfer.Common.Helper;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace lai_transfer.Services
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 百度翻译服务
|
||||||
|
/// </summary>
|
||||||
|
public class BaiduTranslateService : ITranslateService
|
||||||
|
{
|
||||||
|
private const string TRANSLATE_API = "https://fanyi-api.baidu.com/api/trans/vip/translate";
|
||||||
|
private static readonly ILogger _logger = LogHelper.GetLogger<BaiduTranslateService>();
|
||||||
|
public BaiduTranslateService()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> TranslateToEnglish(string prompt)
|
||||||
|
{
|
||||||
|
var appid = ConfigHelper.Translate.BaiduAppId;
|
||||||
|
var appSecret = ConfigHelper.Translate.BaiduAppSecret;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(appid) || string.IsNullOrWhiteSpace(appSecret))
|
||||||
|
{
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ContainsChinese(prompt))
|
||||||
|
{
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
string salt = new Random().Next(10000, 99999).ToString();
|
||||||
|
string sign = ComputeMd5Hash(appid + prompt + salt + appSecret);
|
||||||
|
|
||||||
|
var body = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "from", "zh" },
|
||||||
|
{ "to", "en" },
|
||||||
|
{ "appid", appid },
|
||||||
|
{ "salt", salt },
|
||||||
|
{ "q", prompt },
|
||||||
|
{ "sign", sign }
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var client = new HttpClient())
|
||||||
|
{
|
||||||
|
var content = new FormUrlEncodedContent(body);
|
||||||
|
var response = await client.PostAsync(TRANSLATE_API, content);
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(response.Content.ReadAsStringAsync().Result))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"{response.StatusCode} - {response.Content.ReadAsStringAsync().Result}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = JsonDocument.Parse(response.Content.ReadAsStringAsync().Result);
|
||||||
|
if (result.RootElement.TryGetProperty("error_code", out var errorCode))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"{errorCode.GetString()} - {result.RootElement.GetProperty("error_msg").GetString()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var transResult = result.RootElement.GetProperty("trans_result").EnumerateArray();
|
||||||
|
var translatedStrings = new List<string>();
|
||||||
|
foreach (var item in transResult)
|
||||||
|
{
|
||||||
|
translatedStrings.Add(item.GetProperty("dst").GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join("\n", translatedStrings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(e, "Failed to call Baidu Translate");
|
||||||
|
}
|
||||||
|
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ComputeMd5Hash(string input)
|
||||||
|
{
|
||||||
|
using (var md5 = MD5.Create())
|
||||||
|
{
|
||||||
|
var inputBytes = Encoding.UTF8.GetBytes(input);
|
||||||
|
var hashBytes = md5.ComputeHash(inputBytes);
|
||||||
|
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsChinese(string prompt)
|
||||||
|
{
|
||||||
|
// 匹配基本汉字区、扩展A区和部分扩展B区
|
||||||
|
string chinesePattern = @"[\u4e00-\u9fa5\u3400-\u4DBF]";
|
||||||
|
|
||||||
|
return Regex.IsMatch(prompt, chinesePattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
src/Services/GPTTranslateService.cs
Normal file
105
src/Services/GPTTranslateService.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using lai_transfer.Common.Helper;
|
||||||
|
using lai_transfer.Services;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Midjourney.Infrastructure.Services
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// OpenAI GPT翻译服务
|
||||||
|
/// </summary>
|
||||||
|
public class GPTTranslateService : ITranslateService
|
||||||
|
{
|
||||||
|
private const string TRANSLATE_API = "https://api.openai.com/v1/chat/completions";
|
||||||
|
|
||||||
|
private static readonly ILogger _logger = LogHelper.GetLogger<GPTTranslateService>();
|
||||||
|
|
||||||
|
private readonly string _apiUrl;
|
||||||
|
private readonly string _apiKey;
|
||||||
|
private readonly TimeSpan _timeout;
|
||||||
|
private readonly string _model;
|
||||||
|
private readonly int _maxTokens;
|
||||||
|
private readonly double _temperature;
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
|
||||||
|
public GPTTranslateService()
|
||||||
|
{
|
||||||
|
|
||||||
|
_apiUrl = ConfigHelper.Translate.OpenaiGptApiUrl;
|
||||||
|
_apiKey = ConfigHelper.Translate.OpenaiGptApiKey;
|
||||||
|
_timeout = ConfigHelper.Translate.TimeOut;
|
||||||
|
_model = ConfigHelper.Translate.OpenaiGptModel;
|
||||||
|
_maxTokens = ConfigHelper.Translate.OpenaiGptMaxTokens;
|
||||||
|
_temperature = ConfigHelper.Translate.OpenaiGptTemperature;
|
||||||
|
|
||||||
|
_httpClient = new HttpClient() { Timeout = _timeout };
|
||||||
|
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> TranslateToEnglish(string prompt)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(_apiKey) || string.IsNullOrWhiteSpace(_apiUrl))
|
||||||
|
{
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ContainsChinese(prompt))
|
||||||
|
{
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
var requestBody = new
|
||||||
|
{
|
||||||
|
model = _model,
|
||||||
|
stream = false,
|
||||||
|
messages = new[]
|
||||||
|
{
|
||||||
|
new { role = "system", content = "把中文翻译成英文" },
|
||||||
|
new { role = "user", content = prompt }
|
||||||
|
},
|
||||||
|
max_tokens = _maxTokens,
|
||||||
|
temperature = _temperature
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var content = new StringContent(JsonSerializer.Serialize(requestBody), Encoding.UTF8, "application/json");
|
||||||
|
var response = await _httpClient.PostAsync(_apiUrl, content);
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode || string.IsNullOrWhiteSpace(response.Content.ReadAsStringAsync().Result))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"{response.StatusCode} - {response.Content.ReadAsStringAsync().Result}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = JsonDocument.Parse(response.Content.ReadAsStringAsync().Result);
|
||||||
|
var choices = result.RootElement.GetProperty("choices").EnumerateArray();
|
||||||
|
var translatedText = choices.First().GetProperty("message").GetProperty("content").GetString();
|
||||||
|
|
||||||
|
return translatedText?.Trim() ?? prompt;
|
||||||
|
}
|
||||||
|
catch (HttpRequestException e)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(e, "HTTP request failed");
|
||||||
|
}
|
||||||
|
catch (JsonException e)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(e, "Failed to parse JSON response");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(e, "Failed to call OpenAI Translate");
|
||||||
|
}
|
||||||
|
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsChinese(string prompt)
|
||||||
|
{
|
||||||
|
// 匹配基本汉字区、扩展A区和部分扩展B区
|
||||||
|
string chinesePattern = @"[\u4e00-\u9fa5\u3400-\u4DBF]";
|
||||||
|
|
||||||
|
return Regex.IsMatch(prompt, chinesePattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/Services/ITranslateService.cs
Normal file
9
src/Services/ITranslateService.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace lai_transfer.Services
|
||||||
|
{
|
||||||
|
public interface ITranslateService
|
||||||
|
{
|
||||||
|
Task<string> TranslateToEnglish(string prompt);
|
||||||
|
|
||||||
|
bool ContainsChinese(string prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -95,6 +95,13 @@ namespace lai_transfer.Tool.Extensions
|
|||||||
return section?.GetValue<int>();
|
return section?.GetValue<int>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加一个 getdouble 方法
|
||||||
|
public double? GetDouble(string path, bool forceReload = false)
|
||||||
|
{
|
||||||
|
var section = GetSection(path, forceReload);
|
||||||
|
return section?.GetValue<double>();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取指定路径的布尔值
|
/// 获取指定路径的布尔值
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user