38 Commits

Author SHA1 Message Date
91270
5cd133bc07 Merge pull request #110 from moetayuko/master
Fix thunder json deserialization for jellyfin
2025-03-05 11:25:12 +08:00
Moeta Yuko
fe089c6cb5 Fix thunder json deserialization for jellyfin
Fixes #107
2025-02-24 19:58:09 +08:00
Meiam
5fa9433908 支持新版本 Emby , 迅雷调整到新接口 2025-01-14 17:38:16 +08:00
Meiam
7e960e028c Update 2024-10-27 10:29:24 +08:00
Meiam
ffbe5ce39b update 2024-10-27 10:28:47 +08:00
Meiam
8000919485 Update 2024-10-27 10:27:38 +08:00
Meiam
8095bb9fe4 Update README.md 2024-06-25 13:04:53 +08:00
Meiam
2f80603f99 Update Readme.md 2024-06-25 13:01:34 +08:00
Meiam
bb8135590f Emby .NET 框架更换到 netstandard2.0 适配最新版本 2024-05-24 09:37:43 +08:00
Meiam
f82702f844 解决 Jellyfin 新版调整依赖注入 2024-05-23 19:51:52 +08:00
Meiam
ded87375e1 适配新版 Jellyfin 2024-05-23 16:58:41 +08:00
91270
706971992d Update README.md 2023-06-09 17:24:54 +08:00
Meiam
bbcfd01580 Update README.md 2023-02-15 13:08:59 +08:00
Meiam
008383cf1e Update 2023-02-14 21:58:18 +08:00
Meiam
a6feb50e45 Update 2023-02-14 21:41:57 +08:00
Meiam
0ef2a92705 Update 2023-02-14 21:41:14 +08:00
Meiam
af2d333106 Update 2023-02-14 21:40:21 +08:00
Meiam
630147e853 更新库文件 2023-02-14 21:36:02 +08:00
Meiam
d05afc5ffd 插件库更新 2023-02-14 21:14:40 +08:00
Meiam
237839efea 添加插件库 2023-02-14 21:07:23 +08:00
Meiam
0e5a5d1b0d 编译后执行操作 2023-02-14 19:57:08 +08:00
Meiam
8bebe5ba5b 修复射手无法查询无字幕问题 2023-02-09 22:38:29 +08:00
91270
0c5a3656c8 Update README.md 2023-02-09 16:29:38 +08:00
Meiam
339b05b763 Update 2023-02-07 20:50:19 +08:00
91270
54b13d647d Update README.md 2023-02-02 21:01:48 +08:00
91270
2e06131f8d Update README.md 2023-02-02 21:00:57 +08:00
91270
8f69a7ffca Update README.md 2023-02-02 21:00:40 +08:00
Meiam
bf178f7cef 适配 Emby v4.7.1.0 2022-06-02 13:07:33 +08:00
91270
39aafddd23 Merge pull request #46 from LuckyPuppy514/master
适配Emby v4.7.1.0
2022-06-01 17:34:49 +08:00
LuckyPuppy514
f8854e2a85 适配EMBY v4.7.1.0 2022-06-01 17:00:45 +08:00
LuckyPuppy514
d63de08b8e 适配EMBY v4.7.1.0 2022-06-01 16:57:38 +08:00
Meiam
ac28e193e3 版本号修改 2022-05-28 10:10:14 +08:00
Meiam
f796c05f99 适配新版本 2022-05-28 10:02:49 +08:00
91270
ddeb8e0c14 Merge pull request #38 from hisune/master
readme增加威联通的位置说明
2022-04-21 21:56:16 +08:00
Hisune
7a0fb35fc5 Update README.md 2022-04-18 10:11:45 +08:00
Meiam
74e576de93 程序逻辑优化 2022-04-10 14:21:09 +08:00
Meiam
bc72ca4ab0 降低依赖侵入,适配低版本 2022-04-09 16:07:26 +08:00
Meiam
2d4940156d 修改说明文件 2022-03-31 21:32:22 +08:00
22 changed files with 511 additions and 339 deletions

View File

@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Runtime.Intrinsics.Arm;
using System.Security.Cryptography;
using System.Text;
@@ -19,12 +20,12 @@ namespace Emby.Subtitle.DevTool
var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var reader = new BinaryReader(stream);
var fileSize = new FileInfo(filePath).Length;
var SHA1 = new SHA1CryptoServiceProvider();
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);
buffer = sha1.ComputeHash(buffer, 0, (int)fileSize);
}
else
{
@@ -34,7 +35,7 @@ namespace Emby.Subtitle.DevTool
stream.Seek(fileSize - 0x5000, SeekOrigin.Begin);
reader.Read(buffer, 0xa000, 0x5000);
buffer = SHA1.ComputeHash(buffer, 0, 0xf000);
buffer = sha1.ComputeHash(buffer, 0, 0xf000);
}
var result = "";
foreach (var i in buffer)

View File

@@ -1,26 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyVersion>1.0.5.0</AssemblyVersion>
<FileVersion>1.0.4.0</FileVersion>
<Version>1.0.5</Version>
<AssemblyVersion>1.0.11.0</AssemblyVersion>
<FileVersion>1.0.11.0</FileVersion>
<Version>1.0.11</Version>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<WarningLevel>2</WarningLevel>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>..\Release</OutputPath>
</PropertyGroup>
<ItemGroup>
<None Remove="Thumb.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Thumb.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MediaBrowser.Common" Version="4.4.2" />
<PackageReference Include="MediaBrowser.Server.Core" Version="4.4.2" />
<PackageReference Include="MediaBrowser.Common" Version="4.8.10" />
<PackageReference Include="MediaBrowser.Server.Core" Version="4.8.10" />
</ItemGroup>
</Project>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="Copy $(TargetDir)$(TargetFileName) $(SolutionDir)$(ConfigurationName)\$(TargetFileName) /y&#xD;&#xA;" />
</Target>
</Project>

View File

@@ -9,7 +9,6 @@ namespace Emby.MeiamSub.Shooter.Model
public string Url { get; set; }
public string Format { get; set; }
public string Language { get; set; }
public string TwoLetterISOLanguageName { get; set; }
public bool? IsForced { get; set; }
}
}

View File

@@ -1,4 +1,5 @@
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Drawing;
using System;
using System.IO;
@@ -11,6 +12,12 @@ namespace Emby.MeiamSub.Shooter
/// </summary>
public class Plugin : BasePlugin, IHasThumbImage
{
public Plugin(IApplicationPaths applicationPaths)
{
Instance = this;
}
/// <summary>
/// 插件ID
/// </summary>
@@ -31,6 +38,9 @@ namespace Emby.MeiamSub.Shooter
/// </summary>
public ImageFormat ThumbImageFormat => ImageFormat.Gif;
public static Plugin Instance { get; private set; }
/// <summary>
/// 缩略图资源文件
/// </summary>

View File

@@ -8,7 +8,6 @@ using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
@@ -28,11 +27,11 @@ namespace Emby.MeiamSub.Shooter
public const string SSA = "ssa";
public const string SRT = "srt";
private readonly ILogger _logger;
protected readonly ILogger _logger;
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
public int Order => 0;
public int Order => 1;
public string Name => "MeiamSub.Shooter";
/// <summary>
@@ -42,11 +41,12 @@ namespace Emby.MeiamSub.Shooter
#endregion
#region
public ShooterProvider(ILogger logger, IJsonSerializer jsonSerializer,IHttpClient httpClient)
public ShooterProvider(ILogManager logManager, IJsonSerializer jsonSerializer,IHttpClient httpClient)
{
_logger = logger;
_logger = logManager.GetLogger(GetType().Name);
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
_logger.Info("{0} Init", new object[1] { Name });
}
#endregion
@@ -60,7 +60,7 @@ namespace Emby.MeiamSub.Shooter
/// <returns></returns>
public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
{
_logger.Debug($"MeiamSub.Shooter Search | Request -> { _jsonSerializer.SerializeToString(request) }");
_logger.Info("{0} Search | SubtitleSearchRequest -> {1}", new object[2] { Name , _jsonSerializer.SerializeToString(request) });
var subtitles = await SearchSubtitlesAsync(request);
@@ -74,6 +74,12 @@ namespace Emby.MeiamSub.Shooter
/// <returns></returns>
private async Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitlesAsync(SubtitleSearchRequest request)
{
if(request.Language == "zh-CN" || request.Language == "zh-TW" || request.Language == "zh-HK"){
request.Language = "chi";
}
if(request.Language == "en"){
request.Language = "eng";
}
if (request.Language != "chi" && request.Language != "eng")
{
return Array.Empty<RemoteSubtitleInfo>();
@@ -83,10 +89,12 @@ namespace Emby.MeiamSub.Shooter
var hash = ComputeFileHash(fileInfo);
_logger.Info("{0} Search | FileHash -> {1}", new object[2] { Name, hash });
HttpRequestOptions options = new HttpRequestOptions
{
Url = $"http://www.shooter.cn/api/subapi.php",
UserAgent = "Emby.MeiamSub.Shooter",
Url = $"https://www.shooter.cn/api/subapi.php",
UserAgent = $"{Name}",
TimeoutMs = 30000,
AcceptHeader = "*/*",
};
@@ -99,11 +107,11 @@ namespace Emby.MeiamSub.Shooter
{ "lang",request.Language == "chi" ? "chn" : "eng"}
});
_logger.Debug($"MeiamSub.Shooter Search | Request -> { _jsonSerializer.SerializeToString(options) }");
_logger.Info("{0} Search | Request -> {1}", new object[2] { Name, _jsonSerializer.SerializeToString(options) });
var response = await _httpClient.Post(options);
_logger.Debug($"MeiamSub.Shooter Search | Response -> { _jsonSerializer.SerializeToString(response) }");
_logger.Info("{0} Search | Response -> {1}", new object[2] { Name, _jsonSerializer.SerializeToString(response) });
if (response.StatusCode == HttpStatusCode.OK && response.ContentType.Contains("application/json"))
{
@@ -111,7 +119,7 @@ namespace Emby.MeiamSub.Shooter
if (subtitleResponse != null)
{
_logger.Debug($"MeiamSub.Shooter Search | Response -> { _jsonSerializer.SerializeToString(subtitleResponse) }");
_logger.Info("{0} Search | Response -> {1}", new object[2] { Name, _jsonSerializer.SerializeToString(subtitleResponse) });
var remoteSubtitleInfos = new List<RemoteSubtitleInfo>();
@@ -126,25 +134,25 @@ namespace Emby.MeiamSub.Shooter
Url = subFile.Link,
Format = subFile.Ext,
Language = request.Language,
TwoLetterISOLanguageName = request.TwoLetterISOLanguageName,
IsForced = request.IsForced
})),
Name = $"[MEIAMSUB] { Path.GetFileName(request.MediaPath) } | {request.TwoLetterISOLanguageName} | 射手",
Name = $"[MEIAMSUB] { Path.GetFileName(request.MediaPath) } | {request.Language} | 射手",
Author = "Meiam ",
ProviderName = "MeiamSub.Shooter",
ProviderName = $"{Name}",
Format = subFile.Ext,
Comment = $"Format : { ExtractFormat(subFile.Ext)}"
Comment = $"Format : { ExtractFormat(subFile.Ext)}",
IsHashMatch = true
});
}
}
_logger.Info("{0} Search | Summary -> Get {1} Subtitles", new object[2] { Name, remoteSubtitleInfos.Count });
_logger.Debug($"MeiamSub.Shooter Search | Summary -> Get { remoteSubtitleInfos.Count } Subtitles");
return remoteSubtitleInfos;
}
}
_logger.Debug($"MeiamSub.Shooter Search | Summary -> Get 0 Subtitles");
_logger.Info("{0} Search | Summary -> Get 0 Subtitles", new object[1] { Name });
return Array.Empty<RemoteSubtitleInfo>();
}
@@ -159,10 +167,7 @@ namespace Emby.MeiamSub.Shooter
/// <returns></returns>
public async Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
{
await Task.Run(() =>
{
_logger.Debug($"MeiamSub.Shooter DownloadSub | Request -> {id}");
});
_logger.Info("{0} DownloadSub | Request -> {1}", new object[2] { Name, id });
return await DownloadSubAsync(id);
}
@@ -176,20 +181,25 @@ namespace Emby.MeiamSub.Shooter
{
var downloadSub = _jsonSerializer.DeserializeFromString<DownloadSubInfo>(Base64Decode(info));
downloadSub.Url = downloadSub.Url.Replace("https://www.shooter.cn", "http://www.shooter.cn");
if (downloadSub == null)
{
return new SubtitleResponse();
}
_logger.Debug($"MeiamSub.Shooter DownloadSub | Url -> { downloadSub.Url } | Format -> { downloadSub.Format } | Language -> { downloadSub.Language } ");
_logger.Info($"{0} DownloadSub | Url -> {1} | Format -> {2} | Language -> {3} " ,
new object[4] { Name, downloadSub.Url, downloadSub.Format, downloadSub.Language });
var response = await _httpClient.GetResponse(new HttpRequestOptions
{
Url = downloadSub.Url,
UserAgent = "Emby.MeiamSub.Shooter",
UserAgent = $"{Name}",
TimeoutMs = 30000,
AcceptHeader = "*/*",
});
_logger.Debug($"MeiamSub.Shooter DownloadSub | Response -> { response.StatusCode }");
_logger.Info("{0} DownloadSub | Request -> {1}", new object[2] { Name, response.StatusCode });
if (response.StatusCode == HttpStatusCode.OK)
{

View File

@@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyVersion>1.0.5.0</AssemblyVersion>
<FileVersion>1.0.5.0</FileVersion>
<Version>1.0.5</Version>
<AssemblyVersion>1.0.11.0</AssemblyVersion>
<FileVersion>1.0.11.0</FileVersion>
<Version>1.0.11</Version>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>..\Release</OutputPath>
</PropertyGroup>
@@ -22,9 +22,20 @@
<EmbeddedResource Include="Thumb.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MediaBrowser.Common" Version="4.4.2" />
<PackageReference Include="MediaBrowser.Server.Core" Version="4.4.2" />
<PackageReference Include="MediaBrowser.Common" Version="4.8.10" />
<PackageReference Include="MediaBrowser.Server.Core" Version="4.8.10" />
</ItemGroup>
<ItemGroup>
<Folder Include="Configuration\" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="Copy $(TargetDir)$(TargetFileName) $(SolutionDir)$(ConfigurationName)\$(TargetFileName) /y&#xD;&#xA;" />
</Target>
</Project>

View File

@@ -9,7 +9,6 @@ namespace Emby.MeiamSub.Thunder.Model
public string Url { get; set; }
public string Format { get; set; }
public string Language { get; set; }
public string TwoLetterISOLanguageName { get; set; }
public bool? IsForced { get; set; }
}
}

View File

@@ -2,43 +2,30 @@
namespace Emby.MeiamSub.Thunder.Model
{
public class SublistItem
{
/// <summary>
///
/// </summary>
public string scid { get; set; }
/// <summary>
///
/// </summary>
public string sname { get; set; }
/// <summary>
/// 未知语言
/// </summary>
public string language { get; set; }
/// <summary>
///
/// </summary>
public string rate { get; set; }
/// <summary>
///
/// </summary>
public string surl { get; set; }
/// <summary>
///
/// </summary>
public int svote { get; set; }
/// <summary>
///
/// </summary>
public int roffset { get; set; }
}
public class SubtitleResponseRoot
{
/// <summary>
///
/// </summary>
public List<SublistItem> sublist { get; set; }
public int Code { get; set; }
public List<SublistItem> Data { get; set; }
public string Result { get; set; }
}
public class SublistItem
{
public string Gcid { get; set; }
public string Cid { get; set; }
public string Url { get; set; }
public string Ext { get; set; }
public string Name { get; set; }
public int Duration { get; set; }
public string[] Languages { get; set; }
public string Langs=> Languages != null ? string.Join(",", Languages) : string.Empty;
public int Source { get; set; }
public int Score { get; set; }
public int FingerprintfScore { get; set; }
public string ExtraName { get; set; }
}
}

View File

@@ -1,5 +1,8 @@
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Serialization;
using System;
using System.IO;
@@ -11,6 +14,12 @@ namespace Emby.MeiamSub.Thunder
/// </summary>
public class Plugin : BasePlugin, IHasThumbImage
{
public Plugin(IApplicationPaths applicationPaths)
{
Instance = this;
}
/// <summary>
/// 插件ID
/// </summary>
@@ -31,6 +40,9 @@ namespace Emby.MeiamSub.Thunder
/// </summary>
public ImageFormat ThumbImageFormat => ImageFormat.Gif;
public static Plugin Instance { get; private set; }
/// <summary>
/// 缩略图资源文件
/// </summary>

View File

@@ -14,7 +14,7 @@ using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using static System.Net.WebRequestMethods;
namespace Emby.MeiamSub.Thunder
{
@@ -28,11 +28,12 @@ namespace Emby.MeiamSub.Thunder
public const string SSA = "ssa";
public const string SRT = "srt";
private readonly ILogger _logger;
protected readonly ILogger _logger;
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
public int Order => 0;
public int Order => 1;
public string Name => "MeiamSub.Thunder";
/// <summary>
@@ -42,11 +43,12 @@ namespace Emby.MeiamSub.Thunder
#endregion
#region
public ThunderProvider(ILogger logger, IJsonSerializer jsonSerializer,IHttpClient httpClient)
public ThunderProvider(ILogManager logManager, IJsonSerializer jsonSerializer, IHttpClient httpClient)
{
_logger = logger;
_logger = logManager.GetLogger(GetType().Name);
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
_logger.Info("{0} Init", new object[1] { Name });
}
#endregion
@@ -60,7 +62,7 @@ namespace Emby.MeiamSub.Thunder
/// <returns></returns>
public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
{
_logger.Debug($"MeiamSub.Thunder Search | Request -> { _jsonSerializer.SerializeToString(request) }");
_logger.Info("{0} Search | SubtitleSearchRequest -> {1}", new object[2] { Name, _jsonSerializer.SerializeToString(request) });
var subtitles = await SearchSubtitlesAsync(request);
@@ -74,6 +76,9 @@ namespace Emby.MeiamSub.Thunder
/// <returns></returns>
private async Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitlesAsync(SubtitleSearchRequest request)
{
if(request.Language == "zh-CN" || request.Language == "zh-TW" || request.Language == "zh-HK"){
request.Language = "chi";
}
if (request.Language != "chi")
{
return Array.Empty<RemoteSubtitleInfo>();
@@ -81,52 +86,63 @@ namespace Emby.MeiamSub.Thunder
var cid = GetCidByFile(request.MediaPath);
var response = await _httpClient.GetResponse(new HttpRequestOptions
_logger.Info("{0} Search | FileHash -> {1}", new object[2] { Name, cid });
HttpRequestOptions options = new HttpRequestOptions
{
Url = $"http://sub.xmp.sandai.net:8000/subxl/{cid}.json",
UserAgent = "Emby.MeiamSub.Thunder",
Url = $"https://api-shoulei-ssl.xunlei.com/oracle/subtitle?name={Path.GetFileName(request.MediaPath)}",
UserAgent = $"{Name}",
TimeoutMs = 30000,
AcceptHeader = "*/*",
});
};
var response = await _httpClient.GetResponse(options);
_logger.Debug($"MeiamSub.Thunder Search | Response -> { _jsonSerializer.SerializeToString(response) }");
_logger.Info("{0} Search | Response -> {1}", new object[2] { Name, _jsonSerializer.SerializeToString(response) });
if (response.StatusCode == HttpStatusCode.OK)
{
var subtitleResponse = _jsonSerializer.DeserializeFromStream<SubtitleResponseRoot>(response.Content);
if (subtitleResponse != null)
if (subtitleResponse.Code == 0)
{
_logger.Debug($"MeiamSub.Thunder Search | Response -> { _jsonSerializer.SerializeToString(subtitleResponse) }");
_logger.Info("{0} Search | Response -> {1}", new object[2] { Name, _jsonSerializer.SerializeToString(subtitleResponse) });
var subtitles = subtitleResponse.sublist.Where(m => !string.IsNullOrEmpty(m.sname));
var subtitles = subtitleResponse.Data.Where(m => !string.IsNullOrEmpty(m.Name));
var remoteSubtitleInfos = new List<RemoteSubtitleInfo>();
if (subtitles.Count() > 0)
{
_logger.Debug($"MeiamSub.Thunder Search | Summary -> Get { subtitles.Count() } Subtitles");
return subtitles.Select(m => new RemoteSubtitleInfo()
foreach (var item in subtitles)
{
Id = Base64Encode(_jsonSerializer.SerializeToString(new DownloadSubInfo
remoteSubtitleInfos.Add(new RemoteSubtitleInfo()
{
Url = m.surl,
Format = ExtractFormat(m.sname),
Language = request.Language,
TwoLetterISOLanguageName = request.TwoLetterISOLanguageName,
IsForced = request.IsForced
})),
Name = $"[MEIAMSUB] { Path.GetFileName(request.MediaPath) } | {request.TwoLetterISOLanguageName} | 迅雷",
Author = "Meiam ",
CommunityRating = Convert.ToSingle(m.rate),
ProviderName = "MeiamSub.Thunder",
Format = ExtractFormat(m.sname),
Comment = $"Format : { ExtractFormat(m.sname)} - Rate : { m.rate }"
}).OrderByDescending(m => m.CommunityRating);
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)} | 迅雷",
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, remoteSubtitleInfos.Count });
return remoteSubtitleInfos;
}
}
_logger.Debug($"MeiamSub.Thunder Search | Summary -> Get 0 Subtitles");
_logger.Info("{0} Search | Summary -> Get 0 Subtitles", new object[1] { Name });
return Array.Empty<RemoteSubtitleInfo>();
}
@@ -141,10 +157,7 @@ namespace Emby.MeiamSub.Thunder
/// <returns></returns>
public async Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
{
await Task.Run(() =>
{
_logger.Debug($"MeiamSub.Thunder DownloadSub | Request -> {id}");
});
_logger.Info("{0} DownloadSub | Request -> {1}", new object[2] { Name, id });
return await DownloadSubAsync(id);
}
@@ -158,17 +171,23 @@ namespace Emby.MeiamSub.Thunder
{
var downloadSub = _jsonSerializer.DeserializeFromString<DownloadSubInfo>(Base64Decode(info));
_logger.Debug($"MeiamSub.Thunder DownloadSub | Url -> { downloadSub.Url } | Format -> { downloadSub.Format } | Language -> { downloadSub.Language } ");
if (downloadSub == null)
{
return new SubtitleResponse();
}
_logger.Info("{0} DownloadSub | Url -> {1} | Format -> {2} | Language -> {3} ",
new object[4] { Name, downloadSub.Url, downloadSub.Format, downloadSub.Language });
var response = await _httpClient.GetResponse(new HttpRequestOptions
{
Url = downloadSub.Url,
UserAgent = "Emby.MeiamSub.Thunder",
UserAgent = $"{Name}",
TimeoutMs = 30000,
AcceptHeader = "*/*",
});
_logger.Debug($"MeiamSub.Thunder DownloadSub | Response -> { response.StatusCode }");
_logger.Info("{0} DownloadSub | Response -> {1}", new object[2] { Name, response.StatusCode });
if (response.StatusCode == HttpStatusCode.OK)
{

View File

@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<Version>1.0.5</Version>
<AssemblyVersion>1.0.5.0</AssemblyVersion>
<FileVersion>1.0.5.0</FileVersion>
<TargetFramework>net8.0</TargetFramework>
<Version>1.0.11</Version>
<AssemblyVersion>1.0.11.0</AssemblyVersion>
<FileVersion>1.0.11.0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -12,7 +12,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Jellyfin.Controller" Version="10.7.7" />
<PackageReference Include="Jellyfin.Controller" Version="10.10.3" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="Copy $(TargetDir)$(TargetFileName) $(SolutionDir)$(ConfigurationName)\$(TargetFileName) /y&#xD;&#xA;" />
</Target>
</Project>

View File

@@ -7,7 +7,7 @@ namespace Jellyfin.MeiamSub.Shooter.Model
{
public string Desc { get; set; }
public int Delay { get; set; }
public SubFileInfo[] Files { get; set; }
public List<SubFileInfo> Files { get; set; }
}
public class SubFileInfo

View File

@@ -0,0 +1,20 @@
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Controller;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Jellyfin.MeiamSub.Shooter
{
public class PluginServiceRegistrator : IPluginServiceRegistrator
{
public void RegisterServices(IServiceCollection serviceCollection, IServerApplicationHost applicationHos)
{
serviceCollection.AddSingleton<ISubtitleProvider, ShooterProvider>();
}
}
}

View File

@@ -1,8 +1,10 @@
using Jellyfin.MeiamSub.Shooter.Model;
using Jellyfin.Data.Entities.Libraries;
using Jellyfin.MeiamSub.Shooter.Model;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
@@ -11,12 +13,13 @@ using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using static System.Net.WebRequestMethods;
namespace Jellyfin.MeiamSub.Shooter
{
@@ -31,10 +34,13 @@ namespace Jellyfin.MeiamSub.Shooter
public const string SRT = "srt";
private readonly ILogger<ShooterProvider> _logger;
private readonly IJsonSerializer _jsonSerializer;
private static readonly HttpClient Client = new HttpClient();
public int Order => 0;
private static readonly HttpClient _httpClient = new HttpClient();
private string apiUrl => "https://www.shooter.cn/api/subapi.php";
public int Order => 1;
public string Name => "MeiamSub.Shooter";
/// <summary>
@@ -44,10 +50,11 @@ namespace Jellyfin.MeiamSub.Shooter
#endregion
#region
public ShooterProvider(ILogger<ShooterProvider> logger, IJsonSerializer jsonSerializer)
public ShooterProvider(ILogger<ShooterProvider> logger)
{
_logger = logger;
_jsonSerializer = jsonSerializer;
_httpClient.Timeout = TimeSpan.FromSeconds(30);
_logger.LogInformation($"{Name} Init");
}
#endregion
@@ -61,7 +68,7 @@ namespace Jellyfin.MeiamSub.Shooter
/// <returns></returns>
public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
{
_logger.LogInformation($"MeiamSub.Shooter Search | Request -> { _jsonSerializer.SerializeToString(request) }");
_logger.LogInformation($"{Name} Search | SubtitleSearchRequest -> { JsonSerializer.Serialize(request) }");
var subtitles = await SearchSubtitlesAsync(request);
@@ -80,67 +87,78 @@ namespace Jellyfin.MeiamSub.Shooter
return Array.Empty<RemoteSubtitleInfo>();
}
FileInfo fileInfo = new FileInfo(request.MediaPath);
FileInfo fileInfo = new(request.MediaPath);
var hash = ComputeFileHash(fileInfo);
using (var _httpClient = new HttpClient())
_logger.LogInformation($"{Name} Search | FileHash -> { hash }");
var formData = new Dictionary<string, string>
{
var options = new {
{ "filehash", hash},
{ "pathinfo", request.MediaPath},
{ "format", "json"},
{ "lang", request.Language == "chi" ? "chn" : "eng"}
};
filehash = HttpUtility.UrlEncode(hash),
pathinfo = HttpUtility.UrlEncode(request.MediaPath),
format = "json",
lang = request.Language == "chi" ? "chn" : "eng"
};
var content = new FormUrlEncodedContent(formData);
_logger.LogInformation($"MeiamSub.Shooter Search | Request -> { _jsonSerializer.SerializeToString(options) }");
// 设置请求头
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var response = await PostAsync($"http://www.shooter.cn/api/subapi.php", options);
// 发送 POST 请求
var response = await _httpClient.PostAsync(apiUrl, content);
_logger.LogInformation($"MeiamSub.Shooter Search | Response -> { _jsonSerializer.SerializeToString(response) }");
_logger.LogInformation($"{Name} Search | Response -> {JsonSerializer.Serialize(response)}");
if (response.StatusCode == HttpStatusCode.OK && response.Headers.Any(m => m.Value.Contains("application/json")))
// 处理响应
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 } ");
var subtitles = JsonSerializer.Deserialize<List<SubtitleResponseRoot>>(responseBody);
_logger.LogInformation($"{Name} Search | Response -> {JsonSerializer.Serialize(subtitles)}");
if (subtitles != null)
{
var subtitleResponse = _jsonSerializer.DeserializeFromStream<List<SubtitleResponseRoot>>(await response.Content.ReadAsStreamAsync());
if (subtitleResponse != null)
var remoteSubtitles = new List<RemoteSubtitleInfo>();
foreach (var subFileInfo in subtitles)
{
_logger.LogInformation($"MeiamSub.Shooter Search | Response -> { _jsonSerializer.SerializeToString(subtitleResponse) }");
var remoteSubtitleInfos = new List<RemoteSubtitleInfo>();
foreach (var subFileInfo in subtitleResponse)
foreach (var subFile in subFileInfo.Files)
{
foreach (var subFile in subFileInfo.Files)
remoteSubtitles.Add(new RemoteSubtitleInfo()
{
remoteSubtitleInfos.Add(new RemoteSubtitleInfo()
Id = Base64Encode(JsonSerializer.Serialize(new DownloadSubInfo
{
Id = Base64Encode(_jsonSerializer.SerializeToString(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 = "MeiamSub.Shooter",
Url = subFile.Link,
Format = subFile.Ext,
Comment = $"Format : { ExtractFormat(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
});
}
_logger.LogInformation($"MeiamSub.Shooter Search | Summary -> Get { remoteSubtitleInfos.Count } Subtitles");
return remoteSubtitleInfos;
}
_logger.LogInformation($"{Name} Search | Summary -> Get {remoteSubtitles.Count} Subtitles");
return remoteSubtitles;
}
_logger.LogInformation($"MeiamSub.Shooter Search | Summary -> Get 0 Subtitles");
}
_logger.LogInformation($"{Name} Search | Summary -> Get 0 Subtitles");
return Array.Empty<RemoteSubtitleInfo>();
}
#endregion
@@ -154,10 +172,7 @@ namespace Jellyfin.MeiamSub.Shooter
/// <returns></returns>
public async Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
{
await Task.Run(() =>
{
_logger.LogInformation($"MeiamSub.Shooter DownloadSub | Request -> {id}");
});
_logger.LogInformation($"{Name} DownloadSub | Request -> {id}");
return await DownloadSubAsync(id);
}
@@ -169,31 +184,43 @@ namespace Jellyfin.MeiamSub.Shooter
/// <returns></returns>
private async Task<SubtitleResponse> DownloadSubAsync(string info)
{
var downloadSub = _jsonSerializer.DeserializeFromString<DownloadSubInfo>(Base64Decode(info));
var downloadSub = JsonSerializer.Deserialize<DownloadSubInfo>(Base64Decode(info));
downloadSub.Url = downloadSub.Url.Replace("https://www.shooter.cn", "http://www.shooter.cn");
_logger.LogInformation($"MeiamSub.Shooter DownloadSub | Url -> { downloadSub.Url } | Format -> { downloadSub.Format } | Language -> { downloadSub.Language } ");
using (var _httpClient = new HttpClient())
if (downloadSub == null)
{
var response = await _httpClient.GetAsync(downloadSub.Url);
_logger.LogInformation($"MeiamSub.Shooter DownloadSub | Response -> { response.StatusCode }");
if (response.StatusCode == HttpStatusCode.OK)
{
return new SubtitleResponse()
{
Language = downloadSub.Language,
IsForced = false,
Format = downloadSub.Format,
Stream = await response.Content.ReadAsStreamAsync(),
};
}
return new SubtitleResponse();
}
_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),
Headers =
{
UserAgent = { new ProductInfoHeaderValue(new ProductHeaderValue($"{Name}")) },
Accept = { new MediaTypeWithQualityHeaderValue("*/*") }
}
};
var response = await _httpClient.SendAsync(options);
_logger.LogInformation($"{Name} DownloadSub | Response -> { response.StatusCode }");
if (response.StatusCode == HttpStatusCode.OK)
{
var stream = await response.Content.ReadAsStreamAsync();
return new SubtitleResponse()
{
Language = downloadSub.Language,
IsForced = false,
Format = downloadSub.Format,
Stream = stream,
};
}
return new SubtitleResponse();
}
@@ -201,6 +228,7 @@ namespace Jellyfin.MeiamSub.Shooter
#region
/// <summary>
/// Base64 加密
/// </summary>
@@ -293,16 +321,10 @@ namespace Jellyfin.MeiamSub.Shooter
return ret;
}
#endregion
#region HTTP
public async Task<HttpResponseMessage> PostAsync(string url, object data)
public Task<ItemUpdateType> FetchAsync(Movie item, MetadataRefreshOptions options, CancellationToken cancellationToken)
{
string content = _jsonSerializer.SerializeToString(data);
var buffer = Encoding.UTF8.GetBytes(content);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return await Client.PostAsync(url, byteContent);
throw new NotImplementedException();
}
#endregion
}

View File

@@ -2,10 +2,11 @@
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>
<ApplicationIcon />
<StartupObject />
<Version>1.0.5</Version>
<Version>1.0.11</Version>
<AssemblyVersion>1.0.11.0</AssemblyVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
@@ -13,7 +14,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Jellyfin.Controller" Version="10.7.7" />
<PackageReference Include="Jellyfin.Controller" Version="10.10.3" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="Copy $(TargetDir)$(TargetFileName) $(SolutionDir)$(ConfigurationName)\$(TargetFileName) /y&#xD;&#xA;" />
</Target>
</Project>

View File

@@ -10,6 +10,5 @@ namespace Jellyfin.MeiamSub.Thunder.Model
public string Format { get; set; }
public string Language { get; set; }
public string TwoLetterISOLanguageName { get; set; }
public bool? IsForced { get; set; }
}
}

View File

@@ -2,43 +2,28 @@
namespace Jellyfin.MeiamSub.Thunder.Model
{
public class SublistItem
{
/// <summary>
///
/// </summary>
public string scid { get; set; }
/// <summary>
///
/// </summary>
public string sname { get; set; }
/// <summary>
/// 未知语言
/// </summary>
public string language { get; set; }
/// <summary>
///
/// </summary>
public string rate { get; set; }
/// <summary>
///
/// </summary>
public string surl { get; set; }
/// <summary>
///
/// </summary>
public int svote { get; set; }
/// <summary>
///
/// </summary>
public int roffset { get; set; }
}
public class SubtitleResponseRoot
{
/// <summary>
///
/// </summary>
public List<SublistItem> sublist { get; set; }
public int Code { get; set; }
public List<SublistItem> Data { get; set; }
public string Result { get; set; }
}
public class SublistItem
{
public string Gcid { get; set; }
public string Cid { get; set; }
public string Url { get; set; }
public string Ext { get; set; }
public string Name { get; set; }
public int Duration { get; set; }
public string[] Languages { get; set; }
public string Langs => Languages != null ? string.Join(",", Languages) : string.Empty;
public int Source { get; set; }
public int Score { get; set; }
public int FingerprintfScore { get; set; }
public string ExtraName { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Controller;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Jellyfin.MeiamSub.Thunder
{
public class PluginServiceRegistrator : IPluginServiceRegistrator
{
public void RegisterServices(IServiceCollection serviceCollection, IServerApplicationHost applicationHos)
{
serviceCollection.AddSingleton<ISubtitleProvider, ThunderProvider>();
}
}
}

View File

@@ -2,7 +2,6 @@
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
@@ -10,8 +9,10 @@ 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;
@@ -20,7 +21,7 @@ namespace Jellyfin.MeiamSub.Thunder
/// <summary>
/// 迅雷字幕组件
/// </summary>
public class ThunderProvider : ISubtitleProvider
public class ThunderProvider : ISubtitleProvider, IHasOrder
{
#region
public const string ASS = "ass";
@@ -28,10 +29,13 @@ namespace Jellyfin.MeiamSub.Thunder
public const string SRT = "srt";
private readonly ILogger<ThunderProvider> _logger;
private readonly IJsonSerializer _jsonSerializer;
public int Order => 0;
private static readonly HttpClient _httpClient = new HttpClient();
private static readonly JsonSerializerOptions _deserializeOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
};
public int Order => 1;
public string Name => "MeiamSub.Thunder";
/// <summary>
@@ -41,10 +45,11 @@ namespace Jellyfin.MeiamSub.Thunder
#endregion
#region
public ThunderProvider(ILogger<ThunderProvider> logger, IJsonSerializer jsonSerializer)
public ThunderProvider(ILogger<ThunderProvider> logger)
{
_logger = logger;
_jsonSerializer = jsonSerializer;
_httpClient.Timeout = TimeSpan.FromSeconds(30);
_logger.LogInformation($"{Name} Init");
}
#endregion
@@ -58,7 +63,7 @@ namespace Jellyfin.MeiamSub.Thunder
/// <returns></returns>
public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
{
_logger.LogDebug($"MeiamSub.Thunder Search | Request -> { _jsonSerializer.SerializeToString(request) }");
_logger.LogInformation($"{Name} Search | SubtitleSearchRequest -> { JsonSerializer.Serialize(request) }");
var subtitles = await SearchSubtitlesAsync(request);
@@ -79,49 +84,65 @@ namespace Jellyfin.MeiamSub.Thunder
var cid = GetCidByFile(request.MediaPath);
_logger.LogInformation($"{Name} Search | FileHash -> { cid }");
using (var _httpClient = new HttpClient())
using var options = new HttpRequestMessage
{
var response = await _httpClient.GetAsync($"http://sub.xmp.sandai.net:8000/subxl/{cid}.json");
_logger.LogDebug($"MeiamSub.Thunder Search | Response -> { _jsonSerializer.SerializeToString(response) }");
if (response.StatusCode == HttpStatusCode.OK)
{
var subtitleResponse = _jsonSerializer.DeserializeFromStream<SubtitleResponseRoot>(await response.Content.ReadAsStreamAsync());
if (subtitleResponse != null)
Method = HttpMethod.Get,
RequestUri = new Uri($"https://api-shoulei-ssl.xunlei.com/oracle/subtitle?name={Path.GetFileName(request.MediaPath)}"),
Headers =
{
_logger.LogDebug($"MeiamSub.Thunder Search | Response -> { _jsonSerializer.SerializeToString(subtitleResponse) }");
UserAgent = { new ProductInfoHeaderValue(new ProductHeaderValue($"{Name}")) },
Accept = { new MediaTypeWithQualityHeaderValue("*/*") },
}
};
var subtitles = subtitleResponse.sublist.Where(m => !string.IsNullOrEmpty(m.sname));
var response = await _httpClient.SendAsync(options);
if (subtitles.Count() > 0)
_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 remoteSubtitleInfos = new List<RemoteSubtitleInfo>();
if (subtitles.Count() > 0)
{
foreach (var item in subtitles)
{
_logger.LogDebug($"MeiamSub.Thunder Search | Summary -> Get { subtitles.Count() } Subtitles");
return subtitles.Select(m => new RemoteSubtitleInfo()
remoteSubtitleInfos.Add(new RemoteSubtitleInfo()
{
Id = Base64Encode(_jsonSerializer.SerializeToString(new DownloadSubInfo
Id = Base64Encode(JsonSerializer.Serialize(new DownloadSubInfo
{
Url = m.surl,
Format = ExtractFormat(m.sname),
Url = item.Url,
Format = item.Ext,
Language = request.Language,
TwoLetterISOLanguageName = request.TwoLetterISOLanguageName,
})),
Name = $"[MEIAMSUB] { Path.GetFileName(request.MediaPath) } | {request.TwoLetterISOLanguageName} | 迅雷",
Name = $"[MEIAMSUB] {item.Name} | {(item.Langs == string.Empty ? "" : item.Langs)} | 迅雷",
Author = "Meiam ",
CommunityRating = Convert.ToSingle(m.rate),
ProviderName = "MeiamSub.Thunder",
Format = ExtractFormat(m.sname),
Comment = $"Format : { ExtractFormat(m.sname)} - Rate : { m.rate }"
}).OrderByDescending(m => m.CommunityRating);
ProviderName = $"{Name}",
Format = item.Ext,
Comment = $"Format : {item.Ext}",
IsHashMatch = cid == item.Cid,
});
}
}
}
_logger.LogInformation($"{Name} Search | Summary -> Get {subtitles.Count()} Subtitles");
return remoteSubtitleInfos;
}
}
_logger.LogDebug($"MeiamSub.Thunder Search | Summary -> Get 0 Subtitles");
_logger.LogInformation($"{Name} Search | Summary -> Get 0 Subtitles");
return Array.Empty<RemoteSubtitleInfo>();
}
@@ -136,10 +157,7 @@ namespace Jellyfin.MeiamSub.Thunder
/// <returns></returns>
public async Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
{
await Task.Run(() =>
{
_logger.LogDebug($"MeiamSub.Thunder DownloadSub | Request -> {id}");
});
_logger.LogInformation($"{Name} DownloadSub | Request -> {id}");
return await DownloadSubAsync(id);
}
@@ -151,29 +169,43 @@ namespace Jellyfin.MeiamSub.Thunder
/// <returns></returns>
private async Task<SubtitleResponse> DownloadSubAsync(string info)
{
var downloadSub = _jsonSerializer.DeserializeFromString<DownloadSubInfo>(Base64Decode(info));
var downloadSub = JsonSerializer.Deserialize<DownloadSubInfo>(Base64Decode(info));
_logger.LogDebug($"MeiamSub.Thunder DownloadSub | Url -> { downloadSub.Url } | Format -> { downloadSub.Format } | Language -> { downloadSub.Language } ");
using (var _httpClient = new HttpClient())
if (downloadSub == null)
{
var response = await _httpClient.GetAsync(downloadSub.Url);
_logger.LogDebug($"MeiamSub.Thunder DownloadSub | Response -> { response.StatusCode }");
if (response.StatusCode == HttpStatusCode.OK)
{
return new SubtitleResponse()
{
Language = downloadSub.Language,
IsForced = false,
Format = downloadSub.Format,
Stream = await response.Content.ReadAsStreamAsync(),
};
}
return new SubtitleResponse();
}
_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),
Headers =
{
UserAgent = { new ProductInfoHeaderValue(new ProductHeaderValue($"{Name}")) },
Accept = { new MediaTypeWithQualityHeaderValue("*/*") }
}
};
var response = await _httpClient.SendAsync(options);
_logger.LogInformation($"{Name} DownloadSub | Response -> { response.StatusCode }");
if (response.StatusCode == HttpStatusCode.OK)
{
var stream = await response.Content.ReadAsStreamAsync();
return new SubtitleResponse()
{
Language = downloadSub.Language,
IsForced = false,
Format = downloadSub.Format,
Stream = stream,
};
}
return new SubtitleResponse();
}
@@ -233,12 +265,12 @@ namespace Jellyfin.MeiamSub.Thunder
var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var reader = new BinaryReader(stream);
var fileSize = new FileInfo(filePath).Length;
var SHA1 = new SHA1CryptoServiceProvider();
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);
buffer = sha1.ComputeHash(buffer, 0, (int)fileSize);
}
else
{
@@ -248,7 +280,7 @@ namespace Jellyfin.MeiamSub.Thunder
stream.Seek(fileSize - 0x5000, SeekOrigin.Begin);
reader.Read(buffer, 0xa000, 0x5000);
buffer = SHA1.ComputeHash(buffer, 0, 0xf000);
buffer = sha1.ComputeHash(buffer, 0, 0xf000);
}
var result = "";
foreach (var i in buffer)

View File

@@ -1,17 +1,17 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31424.327
# Visual Studio Version 17
VisualStudioVersion = 17.10.34916.146
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.MeiamSub.Thunder", "Emby.MeiamSub.Thunder\Emby.MeiamSub.Thunder.csproj", "{96F3F427-0EC3-4610-81C3-2C92D773EDC8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.MeiamSub.DevTool", "Emby.MeiamSub.DevTool\Emby.MeiamSub.DevTool.csproj", "{6B0C23EA-EC24-4FB0-948E-094E84AEBF21}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.MeiamSub.Shooter", "Emby.MeiamSub.Shooter\Emby.MeiamSub.Shooter.csproj", "{0F502AEB-0FF4-44FA-8391-13AD61FC5490}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.MeiamSub.Thunder", "Jellyfin.MeiamSub.Thunder\Jellyfin.MeiamSub.Thunder.csproj", "{4676AA1B-CC6C-42DC-BD69-6A293BAE8823}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.MeiamSub.Shooter", "Jellyfin.MeiamSub.Shooter\Jellyfin.MeiamSub.Shooter.csproj", "{8F77E155-9A91-4882-82E8-E8D69FECD246}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.MeiamSub.Shooter", "Jellyfin.MeiamSub.Shooter\Jellyfin.MeiamSub.Shooter.csproj", "{8F77E155-9A91-4882-82E8-E8D69FECD246}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.MeiamSub.Shooter", "Emby.MeiamSub.Shooter\Emby.MeiamSub.Shooter.csproj", "{F2636BCB-111D-4F22-AA06-8852E96D05C4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.MeiamSub.Thunder", "Emby.MeiamSub.Thunder\Emby.MeiamSub.Thunder.csproj", "{96F4C65C-11B1-46F4-B343-115168688C2D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -19,18 +19,10 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{96F3F427-0EC3-4610-81C3-2C92D773EDC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96F3F427-0EC3-4610-81C3-2C92D773EDC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96F3F427-0EC3-4610-81C3-2C92D773EDC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96F3F427-0EC3-4610-81C3-2C92D773EDC8}.Release|Any CPU.Build.0 = Release|Any CPU
{6B0C23EA-EC24-4FB0-948E-094E84AEBF21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B0C23EA-EC24-4FB0-948E-094E84AEBF21}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B0C23EA-EC24-4FB0-948E-094E84AEBF21}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B0C23EA-EC24-4FB0-948E-094E84AEBF21}.Release|Any CPU.Build.0 = Release|Any CPU
{0F502AEB-0FF4-44FA-8391-13AD61FC5490}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0F502AEB-0FF4-44FA-8391-13AD61FC5490}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F502AEB-0FF4-44FA-8391-13AD61FC5490}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F502AEB-0FF4-44FA-8391-13AD61FC5490}.Release|Any CPU.Build.0 = Release|Any CPU
{4676AA1B-CC6C-42DC-BD69-6A293BAE8823}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4676AA1B-CC6C-42DC-BD69-6A293BAE8823}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4676AA1B-CC6C-42DC-BD69-6A293BAE8823}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -39,6 +31,14 @@ Global
{8F77E155-9A91-4882-82E8-E8D69FECD246}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F77E155-9A91-4882-82E8-E8D69FECD246}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8F77E155-9A91-4882-82E8-E8D69FECD246}.Release|Any CPU.Build.0 = Release|Any CPU
{F2636BCB-111D-4F22-AA06-8852E96D05C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2636BCB-111D-4F22-AA06-8852E96D05C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2636BCB-111D-4F22-AA06-8852E96D05C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2636BCB-111D-4F22-AA06-8852E96D05C4}.Release|Any CPU.Build.0 = Release|Any CPU
{96F4C65C-11B1-46F4-B343-115168688C2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96F4C65C-11B1-46F4-B343-115168688C2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96F4C65C-11B1-46F4-B343-115168688C2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96F4C65C-11B1-46F4-B343-115168688C2D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -1,4 +1,4 @@
# Emby.MeiamSub
# MeiamSubtitles
Emby Jellyfin 中文字幕插件 ,支持 迅雷影音、射手网、 精准匹配,自动下载
@@ -14,8 +14,20 @@ Emby Jellyfin 中文字幕插件 ,支持 迅雷影音、射手网、 精准匹
&nbsp;
## 给个星星! ⭐️
如果你喜欢这个项目或者它帮助你, 请给 Star~(辛苦咯)
如果你能赞助稳定 Google Drive 团队盘用于媒体库插件测试, 请于我联系 91270#QQ.COM
&nbsp;
## 广告时间 📣
搬瓦工 $99 年付, 建站神器重出江湖THE PLAN V1 传家宝套餐18机房随意切换
循环优惠码BWHCCNCXVV6.77%
[直达通道(传家宝套餐)](https://bwh88.net/aff.php?aff=117&pid=147)
&nbsp;
@@ -33,14 +45,16 @@ Emby Jellyfin 中文字幕插件 ,支持 迅雷影音、射手网、 精准匹
| 1 | 开发程序 | Emby.MeiamSub.DevTool | 项目开发测试调试使用
| 2 | 字幕插件 | Emby.MeiamSub.Thunder | 迅雷看看字幕插件 - Emby
| 3 | 字幕插件 | Emby.MeiamSub.Shooter | 射手影音字幕插件 - Emby
| 3 | 字幕插件 | Jellyfin.MeiamSub.Shooter | 迅雷看看字幕插件 - Jellyfin
| 3 | 字幕插件 | Jellyfin.MeiamSub.Thunder | 射手影音字幕插件 - Jellyfin
| 4 | 字幕插件 | Jellyfin.MeiamSub.Shooter | 迅雷看看字幕插件 - Jellyfin
| 5 | 字幕插件 | Jellyfin.MeiamSub.Thunder | 射手影音字幕插件 - Jellyfin
## 使用插件
首先下载已编译好的插件 [LINK](https://github.com/91270/Emby.MeiamSub/releases)
首先下载已编译好的插件 [LINK](https://github.com/91270/Emby.MeiamSub/releases) ,由于 Jellyfin 自身 [BUG](https://github.com/jellyfin/jellyfin/issues/12434) , 会重复下载字幕 。
建议:媒体库不勾选本插件, 自动扫描缺失字幕时不使用该插件,但不影响手动查找字幕
### WINDOWS
```bash
@@ -60,11 +74,26 @@ Emby Jellyfin 中文字幕插件 ,支持 迅雷影音、射手网、 精准匹
### 群晖
```bash
复制插件文件到 /var/packages/EmbyServer/target/var/plugins
复制插件文件到 /var/packages/EmbyServer/var/plugins
复制插件文件到 /var/packages/EmbyServer/target/system/plugins
重启服务
```
### 威联通
```bash
# 其中`CACHEDEV{num}_DATA`的名称取决于你的qpkg安装位置
复制插件文件到 /share/CACHEDEV1_DATA/.qpkg/EmbyServer/programdata/plugins
复制插件文件到 /share/CACHEDEV1_DATA/.qpkg/EmbyServer/system/plugins
重启服务
```
### Jellyfin 可通过存储库安装、更新插件
```bash
# 通过 控制台 -> 插件 -> 存储库 添加存储库 URL , 即可通过插件目录查看并安装插件
https://github.com/91270/MeiamSubtitles.Release/raw/main/Plugin/manifest-stable.json
```
&nbsp;
## 贡献