|
|
|
@ -1,9 +1,255 @@
|
|
|
|
|
namespace STranslateDLL;
|
|
|
|
|
using System.IO.Compression;
|
|
|
|
|
using System.Text.Json;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
|
|
|
|
namespace STranslateDLL;
|
|
|
|
|
|
|
|
|
|
public class LocalMode
|
|
|
|
|
{
|
|
|
|
|
public async Task ExecuteAsync()
|
|
|
|
|
private static long NextId;
|
|
|
|
|
|
|
|
|
|
private static bool HasInit = false;
|
|
|
|
|
|
|
|
|
|
private static void Initial()
|
|
|
|
|
{
|
|
|
|
|
var rand = new Random();
|
|
|
|
|
var num = rand.NextInt64(99999) + 8300000;
|
|
|
|
|
NextId = num * 1000;
|
|
|
|
|
|
|
|
|
|
HasInit = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static async Task<string> ExecuteAsync(string content, string? sourceLang = null, string targetLang = "ZH", CancellationToken? token = null)
|
|
|
|
|
{
|
|
|
|
|
if (!HasInit)
|
|
|
|
|
{
|
|
|
|
|
Initial();
|
|
|
|
|
}
|
|
|
|
|
var getToken = token ?? CancellationToken.None;
|
|
|
|
|
long timeSpan = GenerateTimestamp(content);
|
|
|
|
|
long id = CreateId();
|
|
|
|
|
string reqStr = GenerateRequestStr(content, sourceLang, targetLang, timeSpan, id);
|
|
|
|
|
|
|
|
|
|
using var client = new HttpClient();
|
|
|
|
|
var request = new HttpRequestMessage(HttpMethod.Post, "https://www2.deepl.com/jsonrpc")
|
|
|
|
|
{
|
|
|
|
|
Content = new StringContent(reqStr, Encoding.UTF8, "application/json")
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Add headers to the request
|
|
|
|
|
request.Headers.Add("User-Agent", "DeepL-iOS/2.4.0 iOS 15.7.1 (iPhone14,2)");
|
|
|
|
|
request.Headers.Add("Accept", "*/*");
|
|
|
|
|
request.Headers.Add("x-app-os-name", "IOS");
|
|
|
|
|
request.Headers.Add("x-app-os-version", "15.7.1");
|
|
|
|
|
request.Headers.Add("Accept-Language", "en-US,en;q=0.9");
|
|
|
|
|
request.Headers.Add("Accept-Encoding", "gzip,deflate,br");
|
|
|
|
|
//request.Headers.Add("Content-Type", "application/json");
|
|
|
|
|
request.Headers.Add("x-app-device", "iPhone14,2");
|
|
|
|
|
request.Headers.Add("x-app-build", "353");
|
|
|
|
|
request.Headers.Add("x-app-version", "2.4");
|
|
|
|
|
request.Headers.Add("Referer", "https://www.deepl.com/");
|
|
|
|
|
request.Headers.Add("Connection", "keep-alive");
|
|
|
|
|
|
|
|
|
|
HttpResponseMessage resp = await client.SendAsync(request, getToken);
|
|
|
|
|
//resp.EnsureSuccessStatusCode();
|
|
|
|
|
|
|
|
|
|
string responseBody;
|
|
|
|
|
|
|
|
|
|
if (resp.Content.Headers.ContentEncoding.Contains("br"))
|
|
|
|
|
{
|
|
|
|
|
using var responseStream = await resp.Content.ReadAsStreamAsync(getToken);
|
|
|
|
|
using var decompressionStream = new BrotliStream(responseStream, CompressionMode.Decompress);
|
|
|
|
|
using var streamReader = new StreamReader(decompressionStream);
|
|
|
|
|
responseBody = await streamReader.ReadToEndAsync(getToken);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
responseBody = await resp.Content.ReadAsStringAsync(getToken);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var deeplResp = JsonConvert.DeserializeObject<DeepLResponse>(responseBody);
|
|
|
|
|
var response = new Response
|
|
|
|
|
{
|
|
|
|
|
Code = resp.StatusCode.GetHashCode(),
|
|
|
|
|
Data = deeplResp?.Result?.Texts?.FirstOrDefault()?.Text ?? deeplResp?.Error?.Message ?? "Empty Response"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return JsonConvert.SerializeObject(response);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static long GenerateTimestamp(string texts)
|
|
|
|
|
{
|
|
|
|
|
long iCount = texts.Split('i').Length - 1;
|
|
|
|
|
long ts = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
|
|
|
|
return iCount != 0 ? ts - ts % (iCount + 1) + (iCount + 1) : ts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static long CreateId()
|
|
|
|
|
{
|
|
|
|
|
return Interlocked.Increment(ref NextId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string GenerateRequestStr(string text, string? sourceLang, string targetLang, long timeSpan, long id)
|
|
|
|
|
{
|
|
|
|
|
await Task.Delay(3000);
|
|
|
|
|
var req = new DeepLRequest
|
|
|
|
|
{
|
|
|
|
|
Jsonrpc = "2.0",
|
|
|
|
|
Method = "LMT_handle_texts",
|
|
|
|
|
Params = new ReqParams
|
|
|
|
|
{
|
|
|
|
|
Texts =
|
|
|
|
|
[
|
|
|
|
|
new ReqParamsTexts
|
|
|
|
|
{
|
|
|
|
|
Text = text,
|
|
|
|
|
RequestAlternatives = 0
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
Splitting = "newlines",
|
|
|
|
|
Lang = new ReqParamsLang
|
|
|
|
|
{
|
|
|
|
|
SourceLangUserSelected = sourceLang,
|
|
|
|
|
TargetLang = targetLang
|
|
|
|
|
},
|
|
|
|
|
Timestamp = timeSpan,
|
|
|
|
|
CommonJobParams = new ReqParamsCommonJobParams
|
|
|
|
|
{
|
|
|
|
|
WasSpoken = false,
|
|
|
|
|
TranscribeAS = null
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
Id = id
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
string json = JsonConvert.SerializeObject(req);
|
|
|
|
|
return json;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class Response
|
|
|
|
|
{
|
|
|
|
|
public int Code { get; set; }
|
|
|
|
|
public string Data { get; set; } = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class DeepLRequest
|
|
|
|
|
{
|
|
|
|
|
[JsonProperty("jsonrpc")]
|
|
|
|
|
public string Jsonrpc { get; set; } = "";
|
|
|
|
|
[JsonProperty("method")]
|
|
|
|
|
public string Method { get; set; } = "";
|
|
|
|
|
[JsonProperty("params")]
|
|
|
|
|
public ReqParams? Params { get; set; }
|
|
|
|
|
[JsonProperty("id")]
|
|
|
|
|
public long Id { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class ReqParams
|
|
|
|
|
{
|
|
|
|
|
[JsonProperty("texts")]
|
|
|
|
|
public ReqParamsTexts[]? Texts { get; set; }
|
|
|
|
|
[JsonProperty("splitting")]
|
|
|
|
|
public string Splitting { get; set; } = "";
|
|
|
|
|
[JsonProperty("lang")]
|
|
|
|
|
public ReqParamsLang? Lang { get; set; }
|
|
|
|
|
[JsonProperty("timestamp")]
|
|
|
|
|
public long Timestamp { get; set; }
|
|
|
|
|
[JsonProperty("commonJobParams")]
|
|
|
|
|
public ReqParamsCommonJobParams? CommonJobParams { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class ReqParamsTexts
|
|
|
|
|
{
|
|
|
|
|
[JsonProperty("text")]
|
|
|
|
|
public string Text { get; set; } = "";
|
|
|
|
|
[JsonProperty("requestAlternatives")]
|
|
|
|
|
public int RequestAlternatives { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class ReqParamsLang
|
|
|
|
|
{
|
|
|
|
|
[JsonProperty("source_lang_user_selected", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
|
|
|
|
public string? SourceLangUserSelected { get; set; }
|
|
|
|
|
[JsonProperty("target_lang")]
|
|
|
|
|
public string TargetLang { get; set; } = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class ReqParamsCommonJobParams
|
|
|
|
|
{
|
|
|
|
|
[JsonProperty("wasSpoken")]
|
|
|
|
|
public bool WasSpoken { get; set; }
|
|
|
|
|
[JsonProperty("transcribe_as", DefaultValueHandling = DefaultValueHandling.Ignore)]
|
|
|
|
|
public string? TranscribeAS { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class DeepLResponse
|
|
|
|
|
{
|
|
|
|
|
[JsonProperty("jsonrpc")]
|
|
|
|
|
public string Jsonrpc { get; set; } = "";
|
|
|
|
|
[JsonProperty("id")]
|
|
|
|
|
public int Id { get; set; }
|
|
|
|
|
[JsonProperty("result")]
|
|
|
|
|
public RespResult? Result { get; set; }
|
|
|
|
|
[JsonProperty("error")]
|
|
|
|
|
public RespError? Error { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class RespResult
|
|
|
|
|
{
|
|
|
|
|
[JsonProperty("texts")]
|
|
|
|
|
public RespResultText[]? Texts { get; set; }
|
|
|
|
|
[JsonProperty("lang")]
|
|
|
|
|
public string Lang { get; set; } = "";
|
|
|
|
|
[JsonProperty("lang_is_confident")]
|
|
|
|
|
public bool LangIsConfident { get; set; }
|
|
|
|
|
[JsonProperty("detectedLanguages")]
|
|
|
|
|
public RespResultDetectedLanguages? DetectedLanguages { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class RespResultText
|
|
|
|
|
{
|
|
|
|
|
[JsonProperty("alternatives")]
|
|
|
|
|
public object[]? Alternatives { get; set; }
|
|
|
|
|
[JsonProperty("text")]
|
|
|
|
|
public string Text { get; set; } = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class RespResultDetectedLanguages
|
|
|
|
|
{
|
|
|
|
|
public float EN { get; set; }
|
|
|
|
|
public float DE { get; set; }
|
|
|
|
|
public float FR { get; set; }
|
|
|
|
|
public float ES { get; set; }
|
|
|
|
|
public float PT { get; set; }
|
|
|
|
|
public float IT { get; set; }
|
|
|
|
|
public float NL { get; set; }
|
|
|
|
|
public float PL { get; set; }
|
|
|
|
|
public float RU { get; set; }
|
|
|
|
|
public float ZH { get; set; }
|
|
|
|
|
public float JA { get; set; }
|
|
|
|
|
public float BG { get; set; }
|
|
|
|
|
public float CS { get; set; }
|
|
|
|
|
public float DA { get; set; }
|
|
|
|
|
public float EL { get; set; }
|
|
|
|
|
public float ET { get; set; }
|
|
|
|
|
public float FI { get; set; }
|
|
|
|
|
public float HU { get; set; }
|
|
|
|
|
public float LT { get; set; }
|
|
|
|
|
public float LV { get; set; }
|
|
|
|
|
public float RO { get; set; }
|
|
|
|
|
public float SK { get; set; }
|
|
|
|
|
public float SL { get; set; }
|
|
|
|
|
public float SV { get; set; }
|
|
|
|
|
public float TR { get; set; }
|
|
|
|
|
public float ID { get; set; }
|
|
|
|
|
public float Unsupported { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class RespError
|
|
|
|
|
{
|
|
|
|
|
[JsonProperty("code")]
|
|
|
|
|
public int Code { get; set; }
|
|
|
|
|
[JsonProperty("message")]
|
|
|
|
|
public string Message { get; set; } = "";
|
|
|
|
|
}
|