mirror of
https://github.com/91270/MeiamSubtitles.git
synced 2026-05-12 02:56:37 +08:00
fix: 加固射手网 API 稳定性并进行全量代码格式化
- 修复:针对射手网 API 年久失修、无结果时返回乱码或非法内容的问题,增加了 JSON 合法性校验逻辑,确保插件在异常返回下能静默退出而不崩溃。 - 优化:执行了全量代码格式化 (dotnet format),确保缩进、换行及代码风格符合 .NET 官方规范。 - 维护:清理了所有项目中不再使用的提示性条目逻辑,保持代码简洁。
This commit is contained in:
@@ -20,7 +20,7 @@ namespace Emby.Subtitle.DevTool
|
||||
Console.OutputEncoding = Encoding.UTF8;
|
||||
|
||||
Console.WriteLine("================ MeiamSubtitles 调试工具 ================");
|
||||
|
||||
|
||||
// 待测试的影音文件路径
|
||||
var testFilePath = @"D:\Source\MeiamSubtitles\TestServer\Movie\2009\三傻大闹宝莱坞\三傻大闹宝莱坞 (2009) - 1080p.mkv";
|
||||
|
||||
@@ -69,7 +69,15 @@ namespace Emby.Subtitle.DevTool
|
||||
var response = await _httpClient.PostAsync(url, content);
|
||||
var result = await response.Content.ReadAsStringAsync();
|
||||
Console.WriteLine($" > STATUS: {response.StatusCode}");
|
||||
Console.WriteLine($" > RETURN: {result}");
|
||||
|
||||
if (!result.Trim().StartsWith("["))
|
||||
{
|
||||
Console.WriteLine($" > [警告] API 返回了非法内容 (可能已失效或乱码): {result}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($" > RETURN: {result}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -84,7 +92,7 @@ namespace Emby.Subtitle.DevTool
|
||||
// 迅雷搜索接口通常基于文件名,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");
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Emby.MeiamSub.Shooter
|
||||
#endregion
|
||||
|
||||
#region 构造函数
|
||||
public ShooterProvider(ILogManager logManager, IJsonSerializer jsonSerializer,IHttpClient httpClient)
|
||||
public ShooterProvider(ILogManager logManager, IJsonSerializer jsonSerializer, IHttpClient httpClient)
|
||||
{
|
||||
_logger = logManager.GetLogger(GetType().Name);
|
||||
_jsonSerializer = jsonSerializer;
|
||||
@@ -65,7 +65,7 @@ namespace Emby.MeiamSub.Shooter
|
||||
/// <returns>远程字幕信息列表</returns>
|
||||
public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Info("{0} Search | SubtitleSearchRequest -> {1}", new object[2] { Name , _jsonSerializer.SerializeToString(request) });
|
||||
_logger.Info("{0} Search | SubtitleSearchRequest -> {1}", new object[2] { Name, _jsonSerializer.SerializeToString(request) });
|
||||
|
||||
var subtitles = await SearchSubtitlesAsync(request);
|
||||
|
||||
@@ -127,7 +127,25 @@ namespace Emby.MeiamSub.Shooter
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.OK && response.ContentType.Contains("application/json"))
|
||||
{
|
||||
var subtitleResponse = _jsonSerializer.DeserializeFromStream<List<SubtitleResponseRoot>>(response.Content);
|
||||
// 修改人: Meiam
|
||||
// 修改时间: 2025-12-22
|
||||
// 备注: 增加对射手网 API 返回非法内容(如乱码)的校验
|
||||
|
||||
string responseBody;
|
||||
using (var reader = new StreamReader(response.Content, Encoding.UTF8))
|
||||
{
|
||||
responseBody = await reader.ReadToEndAsync();
|
||||
}
|
||||
|
||||
_logger.Info("{0} Search | ResponseBody -> {1}", new object[2] { Name, responseBody });
|
||||
|
||||
if (string.IsNullOrEmpty(responseBody) || !responseBody.Trim().StartsWith("["))
|
||||
{
|
||||
_logger.Info("{0} Search | Summary -> API returned invalid content (likely no subtitles found or API error).", Name);
|
||||
return Array.Empty<RemoteSubtitleInfo>();
|
||||
}
|
||||
|
||||
var subtitleResponse = _jsonSerializer.DeserializeFromString<List<SubtitleResponseRoot>>(responseBody);
|
||||
|
||||
if (subtitleResponse != null)
|
||||
{
|
||||
@@ -141,21 +159,22 @@ namespace Emby.MeiamSub.Shooter
|
||||
{
|
||||
remoteSubtitles.Add(new RemoteSubtitleInfo()
|
||||
{
|
||||
Id = Base64Encode(_jsonSerializer.SerializeToString(new DownloadSubInfo
|
||||
{
|
||||
Url = subFile.Link,
|
||||
Format = subFile.Ext,
|
||||
Id = Base64Encode(_jsonSerializer.SerializeToString(new DownloadSubInfo
|
||||
{
|
||||
Url = subFile.Link,
|
||||
Format = subFile.Ext,
|
||||
Language = request.Language,
|
||||
IsForced = request.IsForced
|
||||
})),
|
||||
Name = $"[MEIAMSUB] {Path.GetFileName(request.MediaPath)} | {request.Language} | 射手",
|
||||
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
|
||||
}); }
|
||||
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 });
|
||||
|
||||
@@ -286,7 +305,7 @@ namespace Emby.MeiamSub.Shooter
|
||||
if (text.Contains(ASS)) return ASS;
|
||||
if (text.Contains(SSA)) return SSA;
|
||||
if (text.Contains(SRT)) return SRT;
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Emby.MeiamSub.Thunder.Model
|
||||
public int Duration { get; set; }
|
||||
public string[] Languages { get; set; }
|
||||
|
||||
public string Langs=> Languages != null ? string.Join(",", Languages) : string.Empty;
|
||||
public string Langs => Languages != null ? string.Join(",", Languages) : string.Empty;
|
||||
|
||||
public int Source { get; set; }
|
||||
public int Score { get; set; }
|
||||
|
||||
@@ -132,21 +132,22 @@ namespace Emby.MeiamSub.Thunder
|
||||
{
|
||||
remoteSubtitles.Add(new RemoteSubtitleInfo()
|
||||
{
|
||||
Id = Base64Encode(_jsonSerializer.SerializeToString(new DownloadSubInfo
|
||||
{
|
||||
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,
|
||||
}); }
|
||||
Id = Base64Encode(_jsonSerializer.SerializeToString(new DownloadSubInfo
|
||||
{
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Info("{0} Search | Summary -> Get {1} Subtitles", new object[2] { Name, remoteSubtitles.Count });
|
||||
@@ -177,7 +178,7 @@ namespace Emby.MeiamSub.Thunder
|
||||
/// <returns>包含字幕流的响应对象</returns>
|
||||
public async Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Info("{0} DownloadSub | Request -> {1}", new object[2] { Name, id });
|
||||
_logger.Info("{0} DownloadSub | Request -> {1}", new object[2] { Name, id });
|
||||
|
||||
return await DownloadSubAsync(id);
|
||||
}
|
||||
@@ -324,7 +325,7 @@ namespace Emby.MeiamSub.Thunder
|
||||
{
|
||||
// 使用 BinaryReader 配合 BaseStream 需要小心,因为 BinaryReader 本身不支持异步 Read
|
||||
// 这里我们直接操作 stream 进行异步读取,不再使用 BinaryReader,因为只是读取字节数组
|
||||
|
||||
|
||||
var fileSize = new FileInfo(filePath).Length;
|
||||
using (var sha1 = SHA1.Create())
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Jellyfin.MeiamSub.Shooter
|
||||
/// <returns>远程字幕信息列表</returns>
|
||||
public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation($"{Name} Search | SubtitleSearchRequest -> { JsonSerializer.Serialize(request) }");
|
||||
_logger.LogInformation($"{Name} Search | SubtitleSearchRequest -> {JsonSerializer.Serialize(request)}");
|
||||
|
||||
var subtitles = await SearchSubtitlesAsync(request);
|
||||
|
||||
@@ -130,12 +130,43 @@ namespace Jellyfin.MeiamSub.Shooter
|
||||
_logger.LogInformation($"{Name} Search | Response -> {JsonSerializer.Serialize(response)}");
|
||||
|
||||
// 处理响应
|
||||
|
||||
if (response.IsSuccessStatusCode && response.Content.Headers.Any(m => m.Value.Contains("application/json; charset=utf-8")))
|
||||
|
||||
{
|
||||
|
||||
var responseBody = await response.Content.ReadAsStringAsync();
|
||||
|
||||
|
||||
|
||||
_logger.LogInformation($"{Name} Search | ResponseBody -> {responseBody} ");
|
||||
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty(responseBody) || !responseBody.Trim().StartsWith("["))
|
||||
|
||||
|
||||
|
||||
{
|
||||
|
||||
|
||||
|
||||
_logger.LogInformation($"{Name} Search | Summary -> API returned invalid content (likely no subtitles found or API error).");
|
||||
|
||||
|
||||
|
||||
return Array.Empty<RemoteSubtitleInfo>();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var subtitles = JsonSerializer.Deserialize<List<SubtitleResponseRoot>>(responseBody);
|
||||
|
||||
_logger.LogInformation($"{Name} Search | Response -> {JsonSerializer.Serialize(subtitles)}");
|
||||
@@ -151,20 +182,21 @@ namespace Jellyfin.MeiamSub.Shooter
|
||||
{
|
||||
remoteSubtitles.Add(new RemoteSubtitleInfo()
|
||||
{
|
||||
Id = Base64Encode(JsonSerializer.Serialize(new DownloadSubInfo
|
||||
{
|
||||
Url = subFile.Link,
|
||||
Id = Base64Encode(JsonSerializer.Serialize(new DownloadSubInfo
|
||||
{
|
||||
Url = subFile.Link,
|
||||
Format = subFile.Ext,
|
||||
Language = request.Language,
|
||||
TwoLetterISOLanguageName = request.TwoLetterISOLanguageName,
|
||||
})),
|
||||
Name = $"[MEIAMSUB] {Path.GetFileName(request.MediaPath)} | {request.TwoLetterISOLanguageName} | 射手",
|
||||
Author = "Meiam ",
|
||||
ProviderName = $"{Name}",
|
||||
Format = subFile.Ext,
|
||||
Language = request.Language,
|
||||
TwoLetterISOLanguageName = request.TwoLetterISOLanguageName,
|
||||
})),
|
||||
Name = $"[MEIAMSUB] {Path.GetFileName(request.MediaPath)} | {request.TwoLetterISOLanguageName} | 射手",
|
||||
Author = "Meiam ",
|
||||
ProviderName = $"{Name}",
|
||||
Format = subFile.Ext,
|
||||
Comment = $"Format : {ExtractFormat(subFile.Ext)}",
|
||||
IsHashMatch = true
|
||||
}); }
|
||||
Comment = $"Format : {ExtractFormat(subFile.Ext)}",
|
||||
IsHashMatch = true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation($"{Name} Search | Summary -> Get {remoteSubtitles.Count} Subtitles");
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace Jellyfin.MeiamSub.Thunder
|
||||
/// <returns>远程字幕信息列表</returns>
|
||||
public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation($"{Name} Search | SubtitleSearchRequest -> { JsonSerializer.Serialize(request) }");
|
||||
_logger.LogInformation($"{Name} Search | SubtitleSearchRequest -> {JsonSerializer.Serialize(request)}");
|
||||
|
||||
var subtitles = await SearchSubtitlesAsync(request);
|
||||
|
||||
@@ -138,16 +138,17 @@ namespace Jellyfin.MeiamSub.Thunder
|
||||
{
|
||||
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,
|
||||
}); }
|
||||
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");
|
||||
|
||||
Reference in New Issue
Block a user