feat: 升级调试工具并还原哈希匹配逻辑

1. 调试工具升级:在 DevTool 中实现了射手网和迅雷影音的实时 HASH 计算与 API 接口测试功能。
2. 还原匹配逻辑:确认 Open Subtitles 冲突并非由于 IsHashMatch 引起,现已恢复精准哈希匹配 (IsHashMatch = true) 逻辑。
3. 优化语言识别:完善了 NormalizeLanguage 逻辑,确保支持 zho, chi, zh 等多种语言代码。
4. 日志级别调整:为了方便排查搜索不到字幕的问题,将字幕接口的原始返回内容恢复为 Info 记录级别。
This commit is contained in:
Meiam
2025-12-22 17:49:39 +08:00
parent e7d1629166
commit 8f79853e00
5 changed files with 389 additions and 273 deletions

View File

@@ -1,96 +1,211 @@
using System;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.Intrinsics.Arm;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Emby.Subtitle.DevTool
{
class Program
{
static void Main(string[] args)
private static readonly HttpClient _httpClient = new HttpClient();
static async Task Main(string[] args)
{
//Console.WriteLine(ComputeFileHash($"X:\\Favorites\\Movie\\八佰 (2020)\\八佰 (2020) 1080p TrueHD.mkv"));
Console.WriteLine(ComputeFileHash($"D:\\Documents\\Downloads\\testidx.avi"));
// 设置控制台编码为 UTF8 防止中文乱码
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine("================ MeiamSubtitles 调试工具 ================");
// 待测试的影音文件路径
var testFilePath = @"D:\Source\MeiamSubtitles\TestServer\Movie\2009\三傻大闹宝莱坞\三傻大闹宝莱坞 (2009) - 1080p.mkv";
if (!File.Exists(testFilePath))
{
Console.WriteLine($"[错误] 文件不存在: {testFilePath}");
return;
}
Console.WriteLine($"[文件] {testFilePath}");
Console.WriteLine("-------------------------------------------------------");
// 1. 射手网 (Shooter)
Console.WriteLine("\n[1/2] 正在请求:射手网 (Shooter)...");
var shooterHash = ComputeShooterHash(testFilePath);
Console.WriteLine($" > HASH: {shooterHash}");
await TestShooterApi(testFilePath, shooterHash);
// 2. 迅雷影音 (Thunder)
Console.WriteLine("\n[2/2] 正在请求:迅雷影音 (Thunder)...");
var thunderCid = await GetThunderCidAsync(testFilePath);
Console.WriteLine($" > CID: {thunderCid}");
await TestThunderApi(testFilePath, thunderCid);
Console.WriteLine("\n-------------------------------------------------------");
Console.WriteLine("调试结束,按任意键退出...");
Console.ReadKey();
}
private static string GetCid(string filePath)
{
var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var reader = new BinaryReader(stream);
var fileSize = new FileInfo(filePath).Length;
var sha1 = SHA1.Create();
var buffer = new byte[0xf000];
if (fileSize < 0xf000)
{
reader.Read(buffer, 0, (int)fileSize);
buffer = sha1.ComputeHash(buffer, 0, (int)fileSize);
}
else
{
reader.Read(buffer, 0, 0x5000);
stream.Seek(fileSize / 3, SeekOrigin.Begin);
reader.Read(buffer, 0x5000, 0x5000);
stream.Seek(fileSize - 0x5000, SeekOrigin.Begin);
reader.Read(buffer, 0xa000, 0x5000);
#region API
buffer = sha1.ComputeHash(buffer, 0, 0xf000);
}
var result = "";
foreach (var i in buffer)
private static async Task TestShooterApi(string filePath, string hash)
{
try
{
result += string.Format("{0:X2}", i);
var url = "https://www.shooter.cn/api/subapi.php";
var formData = new Dictionary<string, string>
{
{ "filehash", hash},
{ "pathinfo", Path.GetFileName(filePath)},
{ "format", "json"},
{ "lang", "chn"}
};
var content = new FormUrlEncodedContent(formData);
var response = await _httpClient.PostAsync(url, content);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine($" > STATUS: {response.StatusCode}");
Console.WriteLine($" > RETURN: {result}");
}
catch (Exception ex)
{
Console.WriteLine($" > ERROR: {ex.Message}");
}
return result;
}
public static string ComputeFileHash(string filePath)
private static async Task TestThunderApi(string filePath, string cid)
{
try
{
// 迅雷搜索接口通常基于文件名CID 用于后续匹配校验
var fileName = Path.GetFileName(filePath);
var url = $"https://api-shoulei-ssl.xunlei.com/oracle/subtitle?name={HttpUtility.UrlEncode(fileName)}";
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Add("User-Agent", "MeiamSub.Thunder");
var response = await _httpClient.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine($" > STATUS: {response.StatusCode}");
Console.WriteLine($" > RETURN: {result}");
}
catch (Exception ex)
{
Console.WriteLine($" > ERROR: {ex.Message}");
}
}
#endregion
#region HASH
/// <summary>
/// 射手网 HASH 算法
/// </summary>
public static string ComputeShooterHash(string filePath)
{
FileInfo fileInfo = new FileInfo(filePath);
if (!fileInfo.Exists || fileInfo.Length < 8 * 1024) return "";
string ret = "";
if (!fileInfo.Exists || fileInfo.Length < 8 * 1024)
using (FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read))
{
long[] offset = new long[4];
offset[3] = fileInfo.Length - 8 * 1024;
offset[2] = fileInfo.Length / 3;
offset[1] = fileInfo.Length / 3 * 2;
offset[0] = 4 * 1024;
string ret = "";
byte[] bBuf = new byte[4096];
using (MD5 md5 = MD5.Create())
{
for (int i = 0; i < 4; ++i)
{
fs.Seek(offset[i], SeekOrigin.Begin);
fs.Read(bBuf, 0, 4096);
byte[] data = md5.ComputeHash(bBuf);
StringBuilder sBuilder = new StringBuilder();
for (int j = 0; j < data.Length; j++) sBuilder.Append(data[j].ToString("x2"));
if (!string.IsNullOrEmpty(ret)) ret += ";";
ret += sBuilder.ToString();
}
}
return ret;
}
FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read);
long[] offset = new long[4];
offset[3] = fileInfo.Length - 8 * 1024;
offset[2] = fileInfo.Length / 3;
offset[1] = fileInfo.Length / 3 * 2;
offset[0] = 4 * 1024;
byte[] bBuf = new byte[1024 * 4];
for (int i = 0; i < 4; ++i)
{
fs.Seek(offset[i], 0);
fs.Read(bBuf, 0, 4 * 1024);
MD5 md5Hash = MD5.Create();
byte[] data = md5Hash.ComputeHash(bBuf);
StringBuilder sBuilder = new StringBuilder();
for (int j = 0; j < data.Length; j++)
{
sBuilder.Append(data[j].ToString("x2"));
}
if (!string.IsNullOrEmpty(ret))
{
ret += ";";
}
ret += sBuilder.ToString();
}
fs.Close();
return ret;
}
/// <summary>
/// 迅雷 CID 算法 (基于 SHA1)
/// </summary>
public static async Task<string> GetThunderCidAsync(string filePath)
{
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous))
{
var fileSize = new FileInfo(filePath).Length;
using (var sha1 = SHA1.Create())
{
var buffer = new byte[0xf000];
if (fileSize < 0xf000)
{
await stream.ReadAsync(buffer, 0, (int)fileSize);
buffer = sha1.ComputeHash(buffer, 0, (int)fileSize);
}
else
{
await stream.ReadAsync(buffer, 0, 0x5000);
stream.Seek(fileSize / 3, SeekOrigin.Begin);
await stream.ReadAsync(buffer, 0x5000, 0x5000);
stream.Seek(fileSize - 0x5000, SeekOrigin.Begin);
await stream.ReadAsync(buffer, 0xa000, 0x5000);
buffer = sha1.ComputeHash(buffer, 0, 0xf000);
}
var result = "";
foreach (var i in buffer) result += string.Format("{0:X2}", i);
return result;
}
}
}
/// <summary>
/// QQ 播放器 VUID 算法
/// </summary>
public static async Task<string> ComputeQQVuidAsync(string filePath)
{
FileInfo fileInfo = new FileInfo(filePath);
if (!fileInfo.Exists || fileInfo.Length < 8 * 1024) return "";
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous))
{
long[] offsets = new long[3];
offsets[0] = 0;
offsets[1] = fileInfo.Length / 3;
offsets[2] = fileInfo.Length - 8 * 1024;
StringBuilder combinedMd5 = new StringBuilder();
byte[] buffer = new byte[4096];
using (var md5 = MD5.Create())
{
foreach (var offset in offsets)
{
fs.Seek(offset, SeekOrigin.Begin);
await fs.ReadAsync(buffer, 0, 4096);
byte[] hashBytes = md5.ComputeHash(buffer);
foreach (byte b in hashBytes) combinedMd5.Append(b.ToString("x2"));
}
byte[] finalHash = md5.ComputeHash(Encoding.ASCII.GetBytes(combinedMd5.ToString()));
StringBuilder result = new StringBuilder();
foreach (byte b in finalHash) result.Append(b.ToString("x2"));
return result.ToString();
}
}
}
#endregion
}
}

View File

@@ -35,7 +35,7 @@ namespace Emby.MeiamSub.Shooter
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
public int Order => 1;
public int Order => 100;
public string Name => "MeiamSub.Shooter";
/// <summary>
@@ -145,17 +145,17 @@ namespace Emby.MeiamSub.Shooter
{
Url = subFile.Link,
Format = subFile.Ext,
Language = request.Language,
IsForced = request.IsForced
})),
Name = $"[MEIAMSUB] {Path.GetFileName(request.MediaPath)} | {language} | 射手",
Language = request.Language,
Author = "Meiam ",
ProviderName = $"{Name}",
Format = subFile.Ext,
Comment = $"Format : {ExtractFormat(subFile.Ext)}",
IsHashMatch = true
}); }
Language = request.Language,
IsForced = request.IsForced
})),
Name = $"[MEIAMSUB] {Path.GetFileName(request.MediaPath)} | {request.Language} | 射手",
Language = request.Language,
Author = "Meiam ",
ProviderName = $"{Name}",
Format = subFile.Ext,
Comment = $"Format : {ExtractFormat(subFile.Ext)}",
IsHashMatch = true
}); }
}
_logger.Info("{0} Search | Summary -> Get {1} Subtitles", new object[2] { Name, remoteSubtitles.Count });

View File

@@ -35,7 +35,7 @@ namespace Emby.MeiamSub.Thunder
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
public int Order => 1;
public int Order => 100;
public string Name => "MeiamSub.Thunder";
@@ -136,17 +136,17 @@ namespace Emby.MeiamSub.Thunder
{
Url = item.Url,
Format = item.Ext,
Language = request.Language,
IsForced = request.IsForced
})),
Name = $"[MEIAMSUB] {item.Name} | {(item.Langs == string.Empty ? "" : item.Langs)} | 迅雷",
Language = request.Language,
Author = "Meiam ",
ProviderName = $"{Name}",
Format = item.Ext,
Comment = $"Format : {item.Ext}",
IsHashMatch = cid == item.Cid,
}); }
Language = request.Language,
IsForced = request.IsForced
})),
Name = $"[MEIAMSUB] {item.Name} | {(item.Langs == string.Empty ? "" : item.Langs)} | 迅雷",
Language = request.Language,
Author = "Meiam ",
ProviderName = $"{Name}",
Format = item.Ext,
Comment = $"Format : {item.Ext}",
IsHashMatch = cid == item.Cid,
}); }
}
_logger.Info("{0} Search | Summary -> Get {1} Subtitles", new object[2] { Name, remoteSubtitles.Count });

View File

@@ -41,7 +41,7 @@ namespace Jellyfin.MeiamSub.Shooter
private const string ApiUrl = "https://www.shooter.cn/api/subapi.php";
public int Order => 1;
public int Order => 100;
public string Name => "MeiamSub.Shooter";

View File

@@ -1,170 +1,170 @@
using Jellyfin.MeiamSub.Thunder.Model;
using Jellyfin.MeiamSub.Thunder.Model;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Providers;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

namespace Jellyfin.MeiamSub.Thunder
{
 /// <summary>
 /// 迅雷看看字幕提供程序
 /// 负责与迅雷 API 进行交互,通过 CID (Content ID) 匹配并下载字幕。
 /// <para>修改人: Meiam</para>
 /// <para>修改时间: 2025-12-22</para>
 /// </summary>
 public class ThunderProvider : ISubtitleProvider, IHasOrder
 {
 #region
 public const string ASS = "ass";
 public const string SSA = "ssa";
 public const string SRT = "srt";

 private readonly ILogger<ThunderProvider> _logger;
 private readonly IHttpClientFactory _httpClientFactory;
 private static readonly JsonSerializerOptions _deserializeOptions = new JsonSerializerOptions
 {
 PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
 };

 public int Order => 1;
 public string Name => "MeiamSub.Thunder";

 /// <summary>
 /// 支持电影、剧集
 /// </summary>
 public IEnumerable<VideoContentType> SupportedMediaTypes => new[] { VideoContentType.Movie, VideoContentType.Episode };
 #endregion

 #region
 public ThunderProvider(ILogger<ThunderProvider> logger, IHttpClientFactory httpClientFactory)
 {
 _logger = logger;
 _httpClientFactory = httpClientFactory;
 _logger.LogInformation($"{Name} Init");
 }
 #endregion

 #region

 /// <summary>
 /// 搜索字幕 (ISubtitleProvider 接口实现)
 /// 根据媒体信息请求字幕列表。
 /// </summary>
 /// <param name="request">包含媒体路径、语言等信息的搜索请求对象</param>
 /// <param name="cancellationToken">取消令牌</param>
 /// <returns>远程字幕信息列表</returns>
 public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
 {
 _logger.LogInformation($"{Name} Search | SubtitleSearchRequest -> { JsonSerializer.Serialize(request) }");

 var subtitles = await SearchSubtitlesAsync(request);

 return subtitles;
 }

 /// <summary>
 /// 查询字幕
 /// </summary>
 /// <param name="request"></param>
 /// <returns></returns>
 private async Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitlesAsync(SubtitleSearchRequest request)
 {
 // 修改人: Meiam
 // 修改时间: 2025-12-22
 // 备注: 增加异常处理

 try
 {
 var language = NormalizeLanguage(request.Language);

 _logger.LogInformation("{Provider} Search | Target -> {File} | Language -> {Lang}", Name, Path.GetFileName(request.MediaPath), language);

 if (language != "chi")
 {
 _logger.LogInformation("{Provider} Search | Summary -> Language not supported, skip search.", Name);
 return Array.Empty<RemoteSubtitleInfo>();
 }

 var stopWatch = Stopwatch.StartNew();
 var cid = await GetCidByFileAsync(request.MediaPath);
 stopWatch.Stop();

 _logger.LogInformation("{Provider} Search | FileHash -> {Hash} (Took {Elapsed}ms)", Name, cid, stopWatch.ElapsedMilliseconds);

 using var options = new HttpRequestMessage
 {
 Method = HttpMethod.Get,
 RequestUri = new Uri($"https://api-shoulei-ssl.xunlei.com/oracle/subtitle?name={Path.GetFileName(request.MediaPath)}")
 };

 using var httpClient = _httpClientFactory.CreateClient(Name);

 var response = await httpClient.SendAsync(options);

 _logger.LogInformation($"{Name} Search | Response -> {JsonSerializer.Serialize(response)}");

 if (response.StatusCode == HttpStatusCode.OK)
 {
 var subtitleResponse = JsonSerializer.Deserialize<SubtitleResponseRoot>(await response.Content.ReadAsStringAsync(), _deserializeOptions);

 if (subtitleResponse != null)
 {
 _logger.LogInformation($"{Name} Search | Response -> {JsonSerializer.Serialize(subtitleResponse)}");

 var subtitles = subtitleResponse.Data.Where(m => !string.IsNullOrEmpty(m.Name));

 var remoteSubtitles = new List<RemoteSubtitleInfo>();

 if (subtitles.Count() > 0)
 {
 foreach (var item in subtitles)
 {
 remoteSubtitles.Add(new RemoteSubtitleInfo()
 {
 Id = Base64Encode(JsonSerializer.Serialize(new DownloadSubInfo
 {
 Url = item.Url,
 Format = item.Ext,
 Language = request.Language,
 TwoLetterISOLanguageName = request.TwoLetterISOLanguageName,
 })),
 Name = $"[MEIAMSUB] {item.Name} | {(item.Langs == string.Empty ? "" : item.Langs)} | 迅雷",
 Author = "Meiam ",
 ProviderName = $"{Name}",
 Format = item.Ext,
 Comment = $"Format : {item.Ext}",
 IsHashMatch = cid == item.Cid,
 }); }
 }

 _logger.LogInformation($"{Name} Search | Summary -> Get {subtitles.Count()} Subtitles");

 return remoteSubtitles;
 }
 }
 }
 catch (Exception ex)
 {
 _logger.LogError(ex, "{Provider} Search | Exception -> [{Type}] {Message}", Name, ex.GetType().Name, ex.Message);
 }

 _logger.LogInformation($"{Name} Search | Summary -> Get 0 Subtitles");

 return Array.Empty<RemoteSubtitleInfo>();
 }
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Providers;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace Jellyfin.MeiamSub.Thunder
{
/// <summary>
/// 迅雷看看字幕提供程序
/// 负责与迅雷 API 进行交互,通过 CID (Content ID) 匹配并下载字幕。
/// <para>修改人: Meiam</para>
/// <para>修改时间: 2025-12-22</para>
/// </summary>
public class ThunderProvider : ISubtitleProvider, IHasOrder
{
#region
public const string ASS = "ass";
public const string SSA = "ssa";
public const string SRT = "srt";
private readonly ILogger<ThunderProvider> _logger;
private readonly IHttpClientFactory _httpClientFactory;
private static readonly JsonSerializerOptions _deserializeOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
};
public int Order => 100;
public string Name => "MeiamSub.Thunder";
/// <summary>
/// 支持电影、剧集
/// </summary>
public IEnumerable<VideoContentType> SupportedMediaTypes => new[] { VideoContentType.Movie, VideoContentType.Episode };
#endregion
#region
public ThunderProvider(ILogger<ThunderProvider> logger, IHttpClientFactory httpClientFactory)
{
_logger = logger;
_httpClientFactory = httpClientFactory;
_logger.LogInformation($"{Name} Init");
}
#endregion
#region
/// <summary>
/// 搜索字幕 (ISubtitleProvider 接口实现)
/// 根据媒体信息请求字幕列表。
/// </summary>
/// <param name="request">包含媒体路径、语言等信息的搜索请求对象</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>远程字幕信息列表</returns>
public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
{
_logger.LogInformation($"{Name} Search | SubtitleSearchRequest -> { JsonSerializer.Serialize(request) }");
var subtitles = await SearchSubtitlesAsync(request);
return subtitles;
}
/// <summary>
/// 查询字幕
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private async Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitlesAsync(SubtitleSearchRequest request)
{
// 修改人: Meiam
// 修改时间: 2025-12-22
// 备注: 增加异常处理
try
{
var language = NormalizeLanguage(request.Language);
_logger.LogInformation("{Provider} Search | Target -> {File} | Language -> {Lang}", Name, Path.GetFileName(request.MediaPath), language);
if (language != "chi")
{
_logger.LogInformation("{Provider} Search | Summary -> Language not supported, skip search.", Name);
return Array.Empty<RemoteSubtitleInfo>();
}
var stopWatch = Stopwatch.StartNew();
var cid = await GetCidByFileAsync(request.MediaPath);
stopWatch.Stop();
_logger.LogInformation("{Provider} Search | FileHash -> {Hash} (Took {Elapsed}ms)", Name, cid, stopWatch.ElapsedMilliseconds);
using var options = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri($"https://api-shoulei-ssl.xunlei.com/oracle/subtitle?name={Path.GetFileName(request.MediaPath)}")
};
using var httpClient = _httpClientFactory.CreateClient(Name);
var response = await httpClient.SendAsync(options);
_logger.LogInformation($"{Name} Search | Response -> {JsonSerializer.Serialize(response)}");
if (response.StatusCode == HttpStatusCode.OK)
{
var subtitleResponse = JsonSerializer.Deserialize<SubtitleResponseRoot>(await response.Content.ReadAsStringAsync(), _deserializeOptions);
if (subtitleResponse != null)
{
_logger.LogInformation($"{Name} Search | Response -> {JsonSerializer.Serialize(subtitleResponse)}");
var subtitles = subtitleResponse.Data.Where(m => !string.IsNullOrEmpty(m.Name));
var remoteSubtitles = new List<RemoteSubtitleInfo>();
if (subtitles.Count() > 0)
{
foreach (var item in subtitles)
{
remoteSubtitles.Add(new RemoteSubtitleInfo()
{
Id = Base64Encode(JsonSerializer.Serialize(new DownloadSubInfo
{
Url = item.Url,
Format = item.Ext,
Language = request.Language,
TwoLetterISOLanguageName = request.TwoLetterISOLanguageName,
})),
Name = $"[MEIAMSUB] {item.Name} | {(item.Langs == string.Empty ? "" : item.Langs)} | 迅雷",
Author = "Meiam ",
ProviderName = $"{Name}",
Format = item.Ext,
Comment = $"Format : {item.Ext}",
IsHashMatch = cid == item.Cid,
}); }
}
_logger.LogInformation($"{Name} Search | Summary -> Get {subtitles.Count()} Subtitles");
return remoteSubtitles;
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "{Provider} Search | Exception -> [{Type}] {Message}", Name, ex.GetType().Name, ex.Message);
}
_logger.LogInformation($"{Name} Search | Summary -> Get 0 Subtitles");
return Array.Empty<RemoteSubtitleInfo>();
}
#endregion
#region
@@ -204,16 +204,17 @@ using MediaBrowser.Controller.Providers;
_logger.LogInformation($"{Name} DownloadSub | Url -> {downloadSub.Url} | Format -> {downloadSub.Format} | Language -> {downloadSub.Language} ");
using var options = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri(downloadSub.Url)
};
using var httpClient = _httpClientFactory.CreateClient(Name);
var response = await httpClient.SendAsync(options);
_logger.LogInformation($"{Name} DownloadSub | Response -> {response.StatusCode}");
using var options = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri(downloadSub.Url)
};
using var httpClient = _httpClientFactory.CreateClient(Name);
var response = await httpClient.SendAsync(options);
_logger.LogInformation($"{Name} DownloadSub | Response -> {response.StatusCode}");
if (response.StatusCode == HttpStatusCode.OK)
{
@@ -230,7 +231,7 @@ using MediaBrowser.Controller.Providers;
}
catch (Exception ex)
{
_logger.LogError(ex, "{0} DownloadSub | Error -> {1}", Name, ex.Message);
_logger.LogError(ex, "{Provider} DownloadSub | Exception -> [{Type}] {Message}", Name, ex.GetType().Name, ex.Message);
}
return new SubtitleResponse();
@@ -353,4 +354,4 @@ using MediaBrowser.Controller.Providers;
}
#endregion
}
}
}