Files
jellyfin-plugin-danmu/Jellyfin.Plugin.Danmu/DanmuSubtitleProvider.cs
2025-12-20 14:02:22 +08:00

163 lines
5.8 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Plugin.Danmu.Core;
using Jellyfin.Plugin.Danmu.Core.Extensions;
using Jellyfin.Plugin.Danmu.Model;
using Jellyfin.Plugin.Danmu.Scrapers;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Providers;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Plugin.Danmu;
public class DanmuSubtitleProvider : ISubtitleProvider
{
public string Name => "Danmu";
private readonly ILibraryManager _libraryManager;
private readonly ILogger<LibraryManagerEventsHelper> _logger;
private readonly LibraryManagerEventsHelper _libraryManagerEventsHelper;
private readonly ScraperManager _scraperManager;
public IEnumerable<VideoContentType> SupportedMediaTypes => new List<VideoContentType>() { VideoContentType.Movie, VideoContentType.Episode };
public DanmuSubtitleProvider(ILibraryManager libraryManager, ILoggerFactory loggerFactory, ScraperManager scraperManager, LibraryManagerEventsHelper libraryManagerEventsHelper)
{
_libraryManager = libraryManager;
_logger = loggerFactory.CreateLogger<LibraryManagerEventsHelper>();
_scraperManager = scraperManager;
_libraryManagerEventsHelper = libraryManagerEventsHelper;
}
public async Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
{
var base64EncodedBytes = System.Convert.FromBase64String(id);
id = System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
var info = id.FromJson<SubtitleId>();
if (info == null)
{
throw new ArgumentException();
}
var item = _libraryManager.GetItemById(info.ItemId);
if (item == null)
{
throw new ArgumentException();
}
var scraper = _scraperManager.All().FirstOrDefault(x => x.ProviderId == info.ProviderId);
if (scraper != null)
{
// 注意item这里要使用临时对象假如直接修改原始item的ProviderIds会导致直接修改原始item数据
if (item is Movie)
{
item = new Movie() { Id = item.Id, Name = item.Name, ProviderIds = new Dictionary<string, string>() { { scraper.ProviderId, info.Id } } };
}
if (item is Episode)
{
item = new Episode() { Id = item.Id, Name = item.Name, ProviderIds = new Dictionary<string, string>() { { scraper.ProviderId, info.Id } } };
}
_libraryManagerEventsHelper.QueueItem(item, EventType.Force);
}
throw new CanIgnoreException($"弹幕下载已由{Plugin.Instance?.Name}插件接管.");
}
public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
{
var list = new List<RemoteSubtitleInfo>();
if (request.IsAutomated || string.IsNullOrEmpty(request.MediaPath))
{
return list;
}
var item = _libraryManager.GetItemList(new InternalItemsQuery
{
Path = request.MediaPath,
}).FirstOrDefault();
if (item == null)
{
return list;
}
// 媒体库未启用就不处理
if (_libraryManagerEventsHelper.IsIgnoreItem(item))
{
return list;
}
// 剧集使用series名称进行搜索
if (item is Episode)
{
item.Name = request.SeriesName;
}
// 规范化名称,删除一些多余信息
item.Name = Utils.NormalizeSearchName(item.Name);
// 并行执行所有scraper的搜索
var searchTasks = _scraperManager.All().Select(async scraper =>
{
try
{
var result = await scraper.Search(item);
var subtitles = new List<RemoteSubtitleInfo>();
foreach (var searchInfo in result)
{
var title = searchInfo.Name;
if (!string.IsNullOrEmpty(searchInfo.Category))
{
title = $"[{searchInfo.Category}] {searchInfo.Name}";
}
if (searchInfo.Year != null && searchInfo.Year > 0)
{
title += $" ({searchInfo.Year})";
}
if (item is Episode && searchInfo.EpisodeSize > 0)
{
title += $"【共{searchInfo.EpisodeSize}集】";
}
var idInfo = new SubtitleId() { ItemId = item.Id.ToString(), Id = searchInfo.Id.ToString(), ProviderId = scraper.ProviderId };
subtitles.Add(new RemoteSubtitleInfo()
{
Id = idInfo.ToJson().ToBase64(), // Id不允许特殊字幕做base64编码处理
Name = title,
ProviderName = $"{Name}",
Format = "xml",
Comment = $"来源:{scraper.Name}",
});
}
return subtitles;
}
catch (Exception ex)
{
_logger.LogError(ex, "[{0}]Exception handled processing queued movie events", scraper.Name);
return new List<RemoteSubtitleInfo>();
}
});
var results = await Task.WhenAll(searchTasks);
// 合并所有结果
foreach (var subtitles in results)
{
list.AddRange(subtitles);
}
return list;
}
}