Files
jellyfin-plugin-metashark/Jellyfin.Plugin.MetaTube/Translation/TranslationHelper.cs

109 lines
4.0 KiB
C#

using System.Collections.Specialized;
using Jellyfin.Plugin.MetaTube.Configuration;
using Jellyfin.Plugin.MetaTube.Metadata;
namespace Jellyfin.Plugin.MetaTube.Translation;
public static class TranslationHelper
{
private const string AutoLanguageCode = "auto";
private const string JapaneseLanguageCode = "ja";
private static readonly SemaphoreSlim Semaphore = new(1);
private static PluginConfiguration Configuration => Plugin.Instance.Configuration;
private static async Task<string> TranslateAsync(string q, string from, string to,
CancellationToken cancellationToken)
{
int millisecondsDelay;
var nv = new NameValueCollection();
switch (Configuration.TranslationEngine)
{
case TranslationEngine.Baidu:
millisecondsDelay = 1000; // Limit Baidu API request rate to 1 rps.
nv.Add(new NameValueCollection
{
{ "baidu-app-id", Configuration.BaiduAppId },
{ "baidu-app-key", Configuration.BaiduAppKey }
});
break;
case TranslationEngine.Google:
millisecondsDelay = 100; // Limit Google API request rate to 10 rps.
nv.Add(new NameValueCollection
{
{ "google-api-key", Configuration.GoogleApiKey },
{ "google-api-url", Configuration.GoogleApiUrl }
});
break;
case TranslationEngine.GoogleFree:
millisecondsDelay = 100;
nv.Add(new NameValueCollection());
break;
case TranslationEngine.DeepL:
millisecondsDelay = 100;
nv.Add(new NameValueCollection
{
{ "deepl-api-key", Configuration.DeepLApiKey },
{ "deepl-api-url", Configuration.DeepLApiUrl }
});
break;
case TranslationEngine.OpenAi:
millisecondsDelay = 1000;
nv.Add(new NameValueCollection
{
{ "openai-api-key", Configuration.OpenAiApiKey },
{ "openai-api-url", Configuration.OpenAiApiUrl },
{ "openai-model", Configuration.OpenAiModel }
});
break;
default:
throw new ArgumentException($"Invalid translation engine: {Configuration.TranslationEngine}");
}
await Semaphore.WaitAsync(cancellationToken);
try
{
async Task<string> TranslateWithDelay()
{
await Task.Delay(millisecondsDelay, cancellationToken);
return (await ApiClient
.TranslateAsync(q, from, to, Configuration.TranslationEngine.ToString(), nv, cancellationToken)
.ConfigureAwait(false)).TranslatedText;
}
return await RetryAsync(TranslateWithDelay, 5);
}
finally
{
Semaphore.Release();
}
}
public static async Task TranslateAsync(MovieInfo m, string to, CancellationToken cancellationToken)
{
if (string.Equals(to, JapaneseLanguageCode, StringComparison.OrdinalIgnoreCase))
throw new ArgumentException($"language not allowed: {to}");
if (Configuration.TranslationMode.HasFlag(TranslationMode.Title) && !string.IsNullOrWhiteSpace(m.Title))
m.Title = await TranslateAsync(m.Title, AutoLanguageCode, to, cancellationToken);
if (Configuration.TranslationMode.HasFlag(TranslationMode.Summary) && !string.IsNullOrWhiteSpace(m.Summary))
m.Summary = await TranslateAsync(m.Summary, AutoLanguageCode, to, cancellationToken);
}
private static async Task<T> RetryAsync<T>(Func<Task<T>> func, int retryCount)
{
while (true)
{
try
{
return await func();
}
catch when (--retryCount > 0)
{
}
}
}
}