refactor: merge metadata provider id to one

This commit is contained in:
cxfksword
2026-05-07 14:53:53 +08:00
parent 59061518e3
commit 07c1d4e0d9
35 changed files with 476 additions and 675 deletions

View File

@@ -0,0 +1,105 @@
using System;
using Jellyfin.Plugin.Danmu.Core;
using Jellyfin.Plugin.Danmu.Scrapers;
using Jellyfin.Plugin.Danmu.Scrapers.Tencent;
using MediaBrowser.Controller.Entities.Movies;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Plugin.Danmu.Test;
[TestClass]
public class DanmuProviderIdTest
{
private static readonly ILoggerFactory TestLoggerFactory = LoggerFactory.Create(builder => { });
[DataTestMethod]
[DataRow("BilibiliID", "bilibili")]
[DataRow("DandanID", "dandan")]
[DataRow("DanmuApiID", "danmuapi")]
[DataRow("IqiyiID", "iqiyi")]
[DataRow("MgtvID", "mgtv")]
[DataRow("TencentID", "tencent")]
[DataRow("YoukuID", "youku")]
public void Encode_UsesMappedLowercasePrefix(string scraperProviderId, string expectedPrefix)
{
var encodedValue = DanmuProviderId.Encode(scraperProviderId, "provider-value");
Assert.AreEqual($"{expectedPrefix}:provider-value", encodedValue);
}
[DataTestMethod]
[DataRow("TencentID:g41000zu2yv", "TencentID", "g41000zu2yv")]
[DataRow("tencent:g41000zu2yv", "TencentID", "g41000zu2yv")]
public void TryDecode_SupportsLegacyAndMappedPrefix(string rawValue, string expectedScraperProviderId, string expectedProviderValue)
{
var success = DanmuProviderId.TryDecode(rawValue, out var scraperProviderId, out var providerValue);
Assert.IsTrue(success);
Assert.AreEqual(expectedScraperProviderId, scraperProviderId);
Assert.AreEqual(expectedProviderValue, providerValue);
}
[TestMethod]
public void Set_WritesMappedUnifiedProviderId()
{
var item = new Movie();
DanmuProviderId.Set(item, Array.Empty<AbstractScraper>(), Tencent.ScraperProviderId, "g41000zu2yv");
Assert.AreEqual("tencent:g41000zu2yv", item.ProviderIds[DanmuProviderId.UnifiedProviderId]);
}
[TestMethod]
public void TryGet_ReadsMappedUnifiedProviderIdWithLegacyScraperProviderId()
{
var item = new Movie();
item.ProviderIds[DanmuProviderId.UnifiedProviderId] = "tencent:g41000zu2yv";
var success = DanmuProviderId.TryGet(item, Tencent.ScraperProviderId, out var providerValue);
Assert.IsTrue(success);
Assert.AreEqual("g41000zu2yv", providerValue);
}
[TestMethod]
public void TryMigrateToUnified_ConvertsLegacyScraperProviderIdToUnifiedProviderId()
{
var item = new Movie();
item.ProviderIds[Tencent.ScraperProviderId] = "g41000zu2yv";
var migrated = DanmuProviderId.TryMigrateToUnified(item, CreateScrapers(), Tencent.ScraperProviderId, "g41000zu2yv");
Assert.IsTrue(migrated);
Assert.IsFalse(item.ProviderIds.ContainsKey(Tencent.ScraperProviderId));
Assert.AreEqual("tencent:g41000zu2yv", item.ProviderIds[DanmuProviderId.UnifiedProviderId]);
}
[TestMethod]
public void TryMigrateToUnified_RewritesLegacyUnifiedValueToCanonicalValue()
{
var item = new Movie();
item.ProviderIds[DanmuProviderId.UnifiedProviderId] = "TencentID:g41000zu2yv";
var migrated = DanmuProviderId.TryMigrateToUnified(item, CreateScrapers(), Tencent.ScraperProviderId, "g41000zu2yv");
Assert.IsTrue(migrated);
Assert.AreEqual("tencent:g41000zu2yv", item.ProviderIds[DanmuProviderId.UnifiedProviderId]);
}
[TestMethod]
public void TryMigrateToUnified_SkipsCanonicalUnifiedValue()
{
var item = new Movie();
item.ProviderIds[DanmuProviderId.UnifiedProviderId] = "tencent:g41000zu2yv";
var migrated = DanmuProviderId.TryMigrateToUnified(item, CreateScrapers(), Tencent.ScraperProviderId, "g41000zu2yv");
Assert.IsFalse(migrated);
Assert.AreEqual("tencent:g41000zu2yv", item.ProviderIds[DanmuProviderId.UnifiedProviderId]);
}
private static AbstractScraper[] CreateScrapers()
{
return new AbstractScraper[] { new Tencent(TestLoggerFactory) };
}
}

View File

@@ -2,12 +2,15 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Jellyfin.Plugin.Danmu.Core;
using Jellyfin.Plugin.Danmu.Model;
using Jellyfin.Plugin.Danmu.Scrapers;
using Jellyfin.Plugin.Danmu.Scrapers.Bilibili;
using Jellyfin.Plugin.Danmu.Scrapers.Dandan;
using Jellyfin.Plugin.Danmu.Scrapers.Tencent;
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Net;
@@ -289,6 +292,41 @@ namespace Jellyfin.Plugin.Danmu.Test
}
[TestMethod]
public void ProcessQueuedUpdateMeta_ShouldKeepUnifiedProviderId_WhenQueueItemAndItemAreSameInstance()
{
var scraperManager = new ScraperManager(loggerFactory);
scraperManager.Register(new Tencent(loggerFactory));
var fileSystemStub = new Mock<Jellyfin.Plugin.Danmu.Core.IFileSystem>();
var itemRepositoryStub = new Mock<IItemRepository>();
var libraryManagerStub = new Mock<ILibraryManager>();
var currentItem = new Movie
{
Name = "test",
ProviderIds = new Dictionary<string, string>
{
[DanmuProviderId.UnifiedProviderId] = "tencent:p4101tg0b9n",
},
};
libraryManagerStub
.Setup(x => x.GetItemById(It.IsAny<Guid>()))
.Returns(currentItem);
libraryManagerStub
.Setup(x => x.RunMetadataSavers(It.IsAny<BaseItem>(), It.IsAny<ItemUpdateType>()))
.Returns(Task.CompletedTask);
var libraryManagerEventsHelper = new LibraryManagerEventsHelper(itemRepositoryStub.Object, libraryManagerStub.Object, loggerFactory, fileSystemStub.Object, scraperManager);
var queue = new List<BaseItem> { currentItem };
var processQueuedUpdateMeta = typeof(LibraryManagerEventsHelper).GetMethod("ProcessQueuedUpdateMeta", BindingFlags.NonPublic | BindingFlags.Instance);
var task = (Task)processQueuedUpdateMeta!.Invoke(libraryManagerEventsHelper, new object[] { queue })!;
task.GetAwaiter().GetResult();
Assert.AreEqual("tencent:p4101tg0b9n", currentItem.ProviderIds[DanmuProviderId.UnifiedProviderId]);
}
[TestMethod]
public void TestDownloadDanmu()
{

View File

@@ -0,0 +1,199 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Jellyfin.Plugin.Danmu.Scrapers;
using Jellyfin.Plugin.Danmu.Scrapers.Bilibili;
using Jellyfin.Plugin.Danmu.Scrapers.Dandan;
using Jellyfin.Plugin.Danmu.Scrapers.DanmuApi;
using Jellyfin.Plugin.Danmu.Scrapers.Iqiyi;
using Jellyfin.Plugin.Danmu.Scrapers.Mgtv;
using Jellyfin.Plugin.Danmu.Scrapers.Tencent;
using Jellyfin.Plugin.Danmu.Scrapers.Youku;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
namespace Jellyfin.Plugin.Danmu.Core;
public static class DanmuProviderId
{
public const string UnifiedProviderId = "DanmuID";
public const string UnifiedProviderName = "Danmu";
private const char Separator = ':';
private static readonly IReadOnlyDictionary<string, string> ScraperProviderIdToPrefixMap = new Dictionary<string, string>(StringComparer.Ordinal)
{
[Bilibili.ScraperProviderId] = "bilibili",
[Dandan.ScraperProviderId] = "dandan",
[DanmuApi.ScraperProviderId] = "danmuapi",
[Iqiyi.ScraperProviderId] = "iqiyi",
[Mgtv.ScraperProviderId] = "mgtv",
[Tencent.ScraperProviderId] = "tencent",
[Youku.ScraperProviderId] = "youku",
};
private static readonly IReadOnlyDictionary<string, string> PrefixToScraperProviderIdMap = ScraperProviderIdToPrefixMap
.ToDictionary(pair => pair.Value, pair => pair.Key, StringComparer.OrdinalIgnoreCase);
public static string Encode(string scraperProviderId, string providerValue)
{
return $"{ToPrefix(scraperProviderId)}{Separator}{providerValue}";
}
public static bool TryDecode(string? value, out string scraperProviderId, out string providerValue)
{
if (string.IsNullOrWhiteSpace(value))
{
scraperProviderId = string.Empty;
providerValue = string.Empty;
return false;
}
var separatorIndex = value.IndexOf(Separator);
if (separatorIndex <= 0 || separatorIndex >= value.Length - 1)
{
scraperProviderId = string.Empty;
providerValue = string.Empty;
return false;
}
scraperProviderId = ToScraperProviderId(value[..separatorIndex]);
providerValue = value[(separatorIndex + 1)..];
return true;
}
public static string Get(IHasProviderIds item, string scraperProviderId)
{
return TryGet(item, scraperProviderId, out var providerValue) ? providerValue : string.Empty;
}
public static bool TryGet(IHasProviderIds item, string scraperProviderId, out string providerValue)
{
if (item.ProviderIds.ContainsKey(UnifiedProviderId))
{
if (TryGetUnified(item, out var matchedProviderId, out var unifiedProviderValue)
&& string.Equals(matchedProviderId, scraperProviderId, StringComparison.Ordinal))
{
providerValue = unifiedProviderValue;
return true;
}
providerValue = string.Empty;
return false;
}
if (item.ProviderIds.TryGetValue(scraperProviderId, out var legacyProviderValue)
&& !string.IsNullOrEmpty(legacyProviderValue))
{
providerValue = legacyProviderValue;
return true;
}
providerValue = string.Empty;
return false;
}
public static bool TryGetFirst(IHasProviderIds item, IEnumerable<AbstractScraper> scrapers, out AbstractScraper? scraper, out string providerValue)
{
if (item.ProviderIds.ContainsKey(UnifiedProviderId))
{
if (TryGetUnified(item, out var unifiedScraperProviderId, out var unifiedProviderValue))
{
scraper = scrapers.FirstOrDefault(current => string.Equals(current.ProviderId, unifiedScraperProviderId, StringComparison.Ordinal));
if (scraper != null)
{
providerValue = unifiedProviderValue;
return true;
}
}
scraper = null;
providerValue = string.Empty;
return false;
}
foreach (var currentScraper in scrapers)
{
if (item.ProviderIds.TryGetValue(currentScraper.ProviderId, out var legacyProviderValue)
&& !string.IsNullOrEmpty(legacyProviderValue))
{
scraper = currentScraper;
providerValue = legacyProviderValue;
return true;
}
}
scraper = null;
providerValue = string.Empty;
return false;
}
public static bool HasAny(IHasProviderIds item, IEnumerable<AbstractScraper> scrapers)
{
return TryGetFirst(item, scrapers, out _, out _);
}
public static bool TryGetUnified(IHasProviderIds item, out string scraperProviderId, out string providerValue)
{
if (item.ProviderIds.TryGetValue(UnifiedProviderId, out var rawProviderValue)
&& TryDecode(rawProviderValue, out scraperProviderId, out providerValue))
{
return true;
}
scraperProviderId = string.Empty;
providerValue = string.Empty;
return false;
}
public static void Clear(BaseItem item, IEnumerable<AbstractScraper> scrapers)
{
item.ProviderIds.Remove(UnifiedProviderId);
foreach (var scraper in scrapers)
{
item.ProviderIds.Remove(scraper.ProviderId);
}
}
public static void Set(BaseItem item, IEnumerable<AbstractScraper> scrapers, string scraperProviderId, string providerValue)
{
Clear(item, scrapers);
item.SetProviderId(UnifiedProviderId, Encode(scraperProviderId, providerValue));
}
public static bool TryMigrateToUnified(BaseItem item, IEnumerable<AbstractScraper> scrapers, string scraperProviderId, string providerValue)
{
if (string.IsNullOrEmpty(providerValue))
{
return false;
}
var scraperList = scrapers as IReadOnlyCollection<AbstractScraper> ?? scrapers.ToArray();
var encodedProviderValue = Encode(scraperProviderId, providerValue);
var hasCanonicalUnifiedProviderId = item.ProviderIds.TryGetValue(UnifiedProviderId, out var rawProviderValue)
&& string.Equals(rawProviderValue, encodedProviderValue, StringComparison.Ordinal);
var hasLegacyScraperProviderId = scraperList.Any(scraper => item.ProviderIds.ContainsKey(scraper.ProviderId));
if (hasCanonicalUnifiedProviderId && !hasLegacyScraperProviderId)
{
return false;
}
Set(item, scraperList, scraperProviderId, providerValue);
return true;
}
private static string ToPrefix(string scraperProviderId)
{
return ScraperProviderIdToPrefixMap.TryGetValue(scraperProviderId, out var prefix)
? prefix
: scraperProviderId;
}
private static string ToScraperProviderId(string prefix)
{
return PrefixToScraperProviderIdMap.TryGetValue(prefix, out var scraperProviderId)
? scraperProviderId
: prefix;
}
}

View File

@@ -0,0 +1,42 @@
using Jellyfin.Plugin.Danmu.Core;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.ExternalId;
public abstract class BaseExternalId : IExternalId
{
public string ProviderName => DanmuProviderId.UnifiedProviderName;
public string Key => DanmuProviderId.UnifiedProviderId;
public string UrlFormatString => string.Empty;
public abstract ExternalIdMediaType? Type { get; }
public abstract bool Supports(IHasProviderIds item);
}
public class MovieExternalId : BaseExternalId
{
public override ExternalIdMediaType? Type => ExternalIdMediaType.Movie;
public override bool Supports(IHasProviderIds item) => item is Movie;
}
public class EpisodeExternalId : BaseExternalId
{
public override ExternalIdMediaType? Type => ExternalIdMediaType.Episode;
public override bool Supports(IHasProviderIds item) => item is Episode;
}
public class SeasonExternalId : BaseExternalId
{
public override ExternalIdMediaType? Type => ExternalIdMediaType.Season;
public override bool Supports(IHasProviderIds item) => item is Season;
}

View File

@@ -305,7 +305,7 @@ public class LibraryManagerEventsHelper : IDisposable
_logger.LogInformation("[{0}]匹配成功name={1} ProviderId: {2}", scraper.Name, item.Name, providerVal);
// 更新epid元数据
item.SetProviderId(scraper.ProviderId, providerVal);
DanmuProviderId.Set(item, _scraperManager.All(), scraper.ProviderId, providerVal);
queueUpdateMeta.Add(item);
// 下载弹幕
@@ -331,15 +331,21 @@ public class LibraryManagerEventsHelper : IDisposable
// 更新
if (eventType == EventType.Update)
{
var queueUpdateMeta = new List<BaseItem>();
foreach (var item in movies)
{
foreach (var scraper in _scraperManager.All())
{
try
{
var providerVal = item.GetProviderId(scraper.ProviderId);
var providerVal = DanmuProviderId.Get(item, scraper.ProviderId);
if (!string.IsNullOrEmpty(providerVal))
{
if (DanmuProviderId.TryMigrateToUnified(item, _scraperManager.All(), scraper.ProviderId, providerVal))
{
queueUpdateMeta.Add(item);
}
var episode = await scraper.GetMediaEpisode(item, providerVal);
if (episode != null)
{
@@ -361,6 +367,8 @@ public class LibraryManagerEventsHelper : IDisposable
}
}
}
await ProcessQueuedUpdateMeta(queueUpdateMeta).ConfigureAwait(false);
}
// 强制刷新指定来源弹幕
@@ -369,15 +377,7 @@ public class LibraryManagerEventsHelper : IDisposable
foreach (var queueItem in movies)
{
// 找到选择的scraper
var scraper = _scraperManager.All().FirstOrDefault(x => queueItem.ProviderIds.ContainsKey(x.ProviderId));
if (scraper == null)
{
continue;
}
// 获取选择的弹幕Id
var mediaId = queueItem.GetProviderId(scraper.ProviderId);
if (string.IsNullOrEmpty(mediaId))
if (!DanmuProviderId.TryGetFirst(queueItem, _scraperManager.All(), out var scraper, out var mediaId) || scraper == null)
{
continue;
}
@@ -525,7 +525,7 @@ public class LibraryManagerEventsHelper : IDisposable
// 更新seasonId元数据
season.SetProviderId(scraper.ProviderId, mediaId);
DanmuProviderId.Set(season, _scraperManager.All(), scraper.ProviderId, mediaId);
queueUpdateMeta.Add(season);
_logger.LogInformation("[{0}]匹配成功:{1}-{2} season_number:{3} ProviderId: {4}", scraper.Name, series.Name, season.Name, season.IndexNumber, mediaId);
@@ -569,12 +569,17 @@ public class LibraryManagerEventsHelper : IDisposable
{
try
{
var providerVal = season.GetProviderId(scraper.ProviderId);
var providerVal = DanmuProviderId.Get(season, scraper.ProviderId);
if (string.IsNullOrEmpty(providerVal))
{
continue;
}
if (DanmuProviderId.TryMigrateToUnified(season, _scraperManager.All(), scraper.ProviderId, providerVal))
{
queueUpdateMeta.Add(season);
}
var media = await scraper.GetMedia(season, providerVal);
if (media == null)
{
@@ -609,10 +614,10 @@ public class LibraryManagerEventsHelper : IDisposable
_logger.LogInformation("[{0}]成功匹配. {1}.{2} -> epId: {3} cid: {4}", scraper.Name, indexNumber, episode.Name, epId, commentId);
// 更新eposide元数据
var episodeProviderVal = episode.GetProviderId(scraper.ProviderId);
var episodeProviderVal = DanmuProviderId.Get(episode, scraper.ProviderId);
if (!string.IsNullOrEmpty(epId) && episodeProviderVal != epId)
{
episode.SetProviderId(scraper.ProviderId, epId);
DanmuProviderId.Set(episode, _scraperManager.All(), scraper.ProviderId, epId);
queueUpdateMeta.Add(episode);
}
@@ -670,20 +675,24 @@ public class LibraryManagerEventsHelper : IDisposable
// 如果 Episode 没有弹幕元数据,表示该集是刮削完成后再新增的,需要重新匹配获取
var scrapers = this._scraperManager.All();
var season = item.Season;
var allDanmuProviderIds = scrapers.Select(x => x.ProviderId).ToList();
var episodeFirstProviderId = allDanmuProviderIds.FirstOrDefault(x => !string.IsNullOrEmpty(item.GetProviderId(x)));
var seasonFirstProviderId = allDanmuProviderIds.FirstOrDefault(x => !string.IsNullOrEmpty(season.GetProviderId(x)));
if (string.IsNullOrEmpty(episodeFirstProviderId) && !string.IsNullOrEmpty(seasonFirstProviderId) && item.IndexNumber.HasValue)
var hasEpisodeProvider = DanmuProviderId.TryGetFirst(item, scrapers, out _, out _);
var hasSeasonProvider = DanmuProviderId.TryGetFirst(season, scrapers, out var seasonScraper, out var seasonProviderVal);
if (!hasEpisodeProvider && hasSeasonProvider && seasonScraper != null && item.IndexNumber.HasValue)
{
var scraper = scrapers.First(x => x.ProviderId == seasonFirstProviderId);
var providerVal = season.GetProviderId(seasonFirstProviderId);
var scraper = seasonScraper;
var providerVal = seasonProviderVal;
if (scraper == null)
{
_logger.LogInformation("找不到对应的弹幕来源. ProviderId: {0}", seasonFirstProviderId);
_logger.LogInformation("找不到对应的弹幕来源. ProviderId: {0}", string.Empty);
continue;
}
if (DanmuProviderId.TryMigrateToUnified(season, _scraperManager.All(), scraper.ProviderId, providerVal))
{
queueUpdateMeta.Add(season);
}
var media = await scraper.GetMedia(season, providerVal);
if (media != null)
{
@@ -714,10 +723,10 @@ public class LibraryManagerEventsHelper : IDisposable
this._logger.LogInformation("[{0}]成功匹配. {1}.{2} -> epId: {3} cid: {4}", scraper.Name, item.IndexNumber, item.Name, epId, commentId);
// 更新 eposide 元数据
var episodeProviderVal = item.GetProviderId(scraper.ProviderId);
var episodeProviderVal = DanmuProviderId.Get(item, scraper.ProviderId);
if (!string.IsNullOrEmpty(epId) && episodeProviderVal != epId)
{
item.SetProviderId(scraper.ProviderId, epId);
DanmuProviderId.Set(item, _scraperManager.All(), scraper.ProviderId, epId);
queueUpdateMeta.Add(item);
}
@@ -733,12 +742,17 @@ public class LibraryManagerEventsHelper : IDisposable
{
try
{
var providerVal = item.GetProviderId(scraper.ProviderId);
var providerVal = DanmuProviderId.Get(item, scraper.ProviderId);
if (string.IsNullOrEmpty(providerVal))
{
continue;
}
if (DanmuProviderId.TryMigrateToUnified(item, _scraperManager.All(), scraper.ProviderId, providerVal))
{
queueUpdateMeta.Add(item);
}
var episode = await scraper.GetMediaEpisode(item, providerVal);
if (episode != null)
{
@@ -769,15 +783,7 @@ public class LibraryManagerEventsHelper : IDisposable
foreach (var queueItem in items)
{
// 找到选择的scraper
var scraper = _scraperManager.All().FirstOrDefault(x => queueItem.ProviderIds.ContainsKey(x.ProviderId));
if (scraper == null)
{
continue;
}
// 获取选择的弹幕Id
var mediaId = queueItem.GetProviderId(scraper.ProviderId);
if (string.IsNullOrEmpty(mediaId))
if (!DanmuProviderId.TryGetFirst(queueItem, _scraperManager.All(), out var scraper, out var mediaId) || scraper == null)
{
continue;
}
@@ -869,14 +875,18 @@ public class LibraryManagerEventsHelper : IDisposable
var item = _libraryManager.GetItemById(queueItem.Id);
if (item != null)
{
// 合并新添加的provider id
foreach (var pair in queueItem.ProviderIds)
{
if (string.IsNullOrEmpty(pair.Value))
{
continue;
}
var providerIdSnapshot = queueItem.ProviderIds
.Where(pair => !string.IsNullOrEmpty(pair.Value))
.ToDictionary(pair => pair.Key, pair => pair.Value);
if (providerIdSnapshot.ContainsKey(DanmuProviderId.UnifiedProviderId))
{
DanmuProviderId.Clear(item, _scraperManager.All());
}
// 合并新添加的provider id
foreach (var pair in providerIdSnapshot)
{
item.ProviderIds[pair.Key] = pair.Value;
}
@@ -993,13 +1003,7 @@ public class LibraryManagerEventsHelper : IDisposable
private async Task ForceSaveProviderId(BaseItem item, string providerId, string providerVal)
{
// 先清空旧弹幕的所有元数据
foreach (var s in _scraperManager.All())
{
item.ProviderIds.Remove(s.ProviderId);
}
// 保存指定弹幕元数据
item.ProviderIds[providerId] = providerVal;
DanmuProviderId.Set(item, _scraperManager.All(), providerId, providerVal);
await this.UpdateItemsAsync(item, CancellationToken.None).ConfigureAwait(false);
}

View File

@@ -7,6 +7,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using Jellyfin.Plugin.Danmu.Core;
using Jellyfin.Plugin.Danmu.Core.Extensions;
using Jellyfin.Plugin.Danmu.Model;
using Jellyfin.Plugin.Danmu.Scrapers;
@@ -128,24 +129,19 @@ namespace Jellyfin.Plugin.Danmu.ScheduledTasks
private bool HasAnyScraperProviderId(ReadOnlyCollection<AbstractScraper> scrapers, BaseItem item)
{
foreach (var scraper in scrapers)
{
var providerVal = item.GetProviderId(scraper.ProviderId);
if (!string.IsNullOrEmpty(providerVal))
{
return true;
}
}
return false;
return DanmuProviderId.HasAny(item, scrapers);
}
private Dictionary<string, string> GetScraperFilter(ReadOnlyCollection<AbstractScraper> scrapers)
{
var filter = new Dictionary<string, string>();
var filter = new Dictionary<string, string>
{
{ DanmuProviderId.UnifiedProviderId, string.Empty }
};
foreach (var scraper in scrapers)
{
filter.Add(scraper.ProviderId, string.Empty);
filter[scraper.ProviderId] = string.Empty;
}
return filter;

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Bilibili.ExternalId
{
/// <inheritdoc />
public class EpisodeExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Bilibili.ScraperProviderName;
/// <inheritdoc />
public string Key => Bilibili.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Episode;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Episode;
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Jellyfin.Plugin.Danmu.Core;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -22,7 +23,7 @@ public class ExternalUrlProvider : IExternalUrlProvider
switch (item)
{
case Season season:
if (item.TryGetProviderId(Bilibili.ScraperProviderId, out var externalId))
if (DanmuProviderId.TryGet(item, Bilibili.ScraperProviderId, out var externalId))
{
if (externalId.StartsWith("bv", StringComparison.OrdinalIgnoreCase) || externalId.StartsWith("av", StringComparison.OrdinalIgnoreCase))
{
@@ -36,14 +37,14 @@ public class ExternalUrlProvider : IExternalUrlProvider
break;
case Episode episode:
if (item.TryGetProviderId(Bilibili.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Bilibili.ScraperProviderId, out externalId))
{
yield return $"https://www.bilibili.com/bangumi/play/ep{externalId}";
}
break;
case Movie:
if (item.TryGetProviderId(Bilibili.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Bilibili.ScraperProviderId, out externalId))
{
yield return $"https://www.bilibili.com/bangumi/play/ep{externalId}";
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Bilibili.ExternalId
{
/// <inheritdoc />
public class MovieExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Bilibili.ScraperProviderName;
/// <inheritdoc />
public string Key => Bilibili.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Movie;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Movie;
}
}

View File

@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Bilibili.ExternalId
{
/// <inheritdoc />
public class SeasonExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Bilibili.ScraperProviderName;
/// <inheritdoc />
public string Key => Bilibili.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Season;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Season;
}
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Dandan.ExternalId
{
/// <inheritdoc />
public class EpisodeExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Dandan.ScraperProviderName;
/// <inheritdoc />
public string Key => Dandan.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Episode;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Episode;
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Jellyfin.Plugin.Danmu.Core;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -22,21 +23,21 @@ public class ExternalUrlProvider : IExternalUrlProvider
switch (item)
{
case Season season:
if (item.TryGetProviderId(Dandan.ScraperProviderId, out var externalId))
if (DanmuProviderId.TryGet(item, Dandan.ScraperProviderId, out var externalId))
{
yield return $"https://api.dandanplay.net/api/v2/bangumi/{externalId}";
}
break;
case Episode episode:
if (item.TryGetProviderId(Dandan.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Dandan.ScraperProviderId, out externalId))
{
yield return "#";
}
break;
case Movie:
if (item.TryGetProviderId(Dandan.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Dandan.ScraperProviderId, out externalId))
{
yield return $"https://api.dandanplay.net/api/v2/bangumi/{externalId}";
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Dandan.ExternalId
{
/// <inheritdoc />
public class MovieExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Dandan.ScraperProviderName;
/// <inheritdoc />
public string Key => Dandan.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Movie;
}
}

View File

@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Dandan.ExternalId
{
/// <inheritdoc />
public class SeasonExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Dandan.ScraperProviderName;
/// <inheritdoc />
public string Key => Dandan.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Season;
}
}

View File

@@ -1,23 +0,0 @@
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.DanmuApi.ExternalId
{
/// <inheritdoc />
public class EpisodeExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => DanmuApi.ScraperProviderName;
/// <inheritdoc />
public string Key => DanmuApi.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Episode;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Episode;
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Jellyfin.Plugin.Danmu.Core;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -22,7 +23,7 @@ public class ExternalUrlProvider : IExternalUrlProvider
switch (item)
{
case Season season:
if (item.TryGetProviderId(DanmuApi.ScraperProviderId, out var externalId))
if (DanmuProviderId.TryGet(item, DanmuApi.ScraperProviderId, out var externalId))
{
var serverUrl = GetServerUrl();
if (!string.IsNullOrEmpty(serverUrl))
@@ -37,7 +38,7 @@ public class ExternalUrlProvider : IExternalUrlProvider
break;
case Episode episode:
if (item.TryGetProviderId(DanmuApi.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, DanmuApi.ScraperProviderId, out externalId))
{
var serverUrl = GetServerUrl();
if (!string.IsNullOrEmpty(serverUrl))
@@ -52,7 +53,7 @@ public class ExternalUrlProvider : IExternalUrlProvider
break;
case Movie:
if (item.TryGetProviderId(DanmuApi.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, DanmuApi.ScraperProviderId, out externalId))
{
var serverUrl = GetServerUrl();
if (!string.IsNullOrEmpty(serverUrl))

View File

@@ -1,23 +0,0 @@
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.DanmuApi.ExternalId
{
/// <inheritdoc />
public class MovieExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => DanmuApi.ScraperProviderName;
/// <inheritdoc />
public string Key => DanmuApi.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Movie;
}
}

View File

@@ -1,23 +0,0 @@
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.DanmuApi.ExternalId
{
/// <inheritdoc />
public class SeasonExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => DanmuApi.ScraperProviderName;
/// <inheritdoc />
public string Key => DanmuApi.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Season;
}
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Iqiyi.ExternalId
{
/// <inheritdoc />
public class EpisodeExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Iqiyi.ScraperProviderName;
/// <inheritdoc />
public string Key => Iqiyi.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Episode;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Episode;
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Jellyfin.Plugin.Danmu.Core;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -22,21 +23,21 @@ public class ExternalUrlProvider : IExternalUrlProvider
switch (item)
{
case Season season:
if (item.TryGetProviderId(Iqiyi.ScraperProviderId, out var externalId))
if (DanmuProviderId.TryGet(item, Iqiyi.ScraperProviderId, out var externalId))
{
yield return $"https://www.iqiyi.com/v_{externalId}.html";
}
break;
case Episode episode:
if (item.TryGetProviderId(Iqiyi.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Iqiyi.ScraperProviderId, out externalId))
{
yield return $"https://www.iqiyi.com/v_{externalId}.html";
}
break;
case Movie:
if (item.TryGetProviderId(Iqiyi.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Iqiyi.ScraperProviderId, out externalId))
{
yield return $"https://www.iqiyi.com/v_{externalId}.html";
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Iqiyi.ExternalId
{
/// <inheritdoc />
public class MovieExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Iqiyi.ScraperProviderName;
/// <inheritdoc />
public string Key => Iqiyi.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Movie;
}
}

View File

@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Iqiyi.ExternalId
{
/// <inheritdoc />
public class SeasonExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Iqiyi.ScraperProviderName;
/// <inheritdoc />
public string Key => Iqiyi.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Season;
}
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Mgtv.ExternalId
{
/// <inheritdoc />
public class EpisodeExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Mgtv.ScraperProviderName;
/// <inheritdoc />
public string Key => Mgtv.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Episode;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Episode;
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Jellyfin.Plugin.Danmu.Core;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -22,16 +23,16 @@ public class ExternalUrlProvider : IExternalUrlProvider
switch (item)
{
case Season season:
if (item.TryGetProviderId(Mgtv.ScraperProviderId, out var externalId))
if (DanmuProviderId.TryGet(item, Mgtv.ScraperProviderId, out var externalId))
{
yield return $"https://www.mgtv.com/h/{externalId}.html";
}
break;
case Episode episode:
if (item.TryGetProviderId(Mgtv.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Mgtv.ScraperProviderId, out externalId))
{
if (episode.Season?.TryGetProviderId(Mgtv.ScraperProviderId, out var seasonExternalId) == true)
if (episode.Season != null && DanmuProviderId.TryGet(episode.Season, Mgtv.ScraperProviderId, out var seasonExternalId))
{
yield return $"https://www.mgtv.com/b/{seasonExternalId}/{externalId}.html";
}
@@ -43,7 +44,7 @@ public class ExternalUrlProvider : IExternalUrlProvider
break;
case Movie:
if (item.TryGetProviderId(Mgtv.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Mgtv.ScraperProviderId, out externalId))
{
yield return $"https://www.mgtv.com/h/{externalId}.html";
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Mgtv.ExternalId
{
/// <inheritdoc />
public class MovieExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Mgtv.ScraperProviderName;
/// <inheritdoc />
public string Key => Mgtv.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Movie;
}
}

View File

@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Mgtv.ExternalId
{
/// <inheritdoc />
public class SeasonExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Mgtv.ScraperProviderName;
/// <inheritdoc />
public string Key => Mgtv.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Season;
}
}

View File

@@ -1,6 +1,7 @@
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Plugin.Danmu.Core;
using MediaBrowser.Controller.Entities;
using Microsoft.Extensions.Logging;
using Jellyfin.Plugin.Danmu.Scrapers.Entity;
@@ -176,7 +177,7 @@ public class Mgtv : AbstractScraper
// 从季信息元数据中获取cid值
// 不能通过GetParent获取Season因为没有SXX季文件夹时GetParent是Series
var season = ((MediaBrowser.Controller.Entities.TV.Episode)item).Season;
season.ProviderIds.TryGetValue(ScraperProviderId, out var cid);
DanmuProviderId.TryGet(season, ScraperProviderId, out var cid);
return new ScraperEpisode() { Id = id, CommentId = $"{cid},{id}" };
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Tencent.ExternalId
{
/// <inheritdoc />
public class EpisodeExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Tencent.ScraperProviderName;
/// <inheritdoc />
public string Key => Tencent.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Episode;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Episode;
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Jellyfin.Plugin.Danmu.Core;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -22,16 +23,16 @@ public class ExternalUrlProvider : IExternalUrlProvider
switch (item)
{
case Season season:
if (item.TryGetProviderId(Tencent.ScraperProviderId, out var externalId))
if (DanmuProviderId.TryGet(item, Tencent.ScraperProviderId, out var externalId))
{
yield return $"https://v.qq.com/x/cover/{externalId}.html";
}
break;
case Episode episode:
if (item.TryGetProviderId(Tencent.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Tencent.ScraperProviderId, out externalId))
{
if (episode.Season?.TryGetProviderId(Tencent.ScraperProviderId, out var seasonExternalId) == true)
if (episode.Season != null && DanmuProviderId.TryGet(episode.Season, Tencent.ScraperProviderId, out var seasonExternalId))
{
yield return $"https://v.qq.com/x/cover/{seasonExternalId}/{externalId}.html";
}
@@ -43,7 +44,7 @@ public class ExternalUrlProvider : IExternalUrlProvider
break;
case Movie:
if (item.TryGetProviderId(Tencent.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Tencent.ScraperProviderId, out externalId))
{
yield return $"https://v.qq.com/x/cover/{externalId}.html";
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Tencent.ExternalId
{
/// <inheritdoc />
public class MovieExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Tencent.ScraperProviderName;
/// <inheritdoc />
public string Key => Tencent.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Movie;
}
}

View File

@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Tencent.ExternalId
{
/// <inheritdoc />
public class SeasonExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Tencent.ScraperProviderName;
/// <inheritdoc />
public string Key => Tencent.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Season;
}
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Youku.ExternalId
{
/// <inheritdoc />
public class EpisodeExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Youku.ScraperProviderName;
/// <inheritdoc />
public string Key => Youku.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => ExternalIdMediaType.Episode;
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Episode;
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Web;
using System.Collections.Generic;
using Jellyfin.Plugin.Danmu.Core;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -23,14 +24,14 @@ public class ExternalUrlProvider : IExternalUrlProvider
switch (item)
{
case Season season:
if (item.TryGetProviderId(Youku.ScraperProviderId, out var externalId))
if (DanmuProviderId.TryGet(item, Youku.ScraperProviderId, out var externalId))
{
yield return $"https://v.youku.com/v_nextstage/id_{externalId}.html";
}
break;
case Episode episode:
if (item.TryGetProviderId(Youku.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Youku.ScraperProviderId, out externalId))
{
var decodeExternalId = HttpUtility.UrlDecode(externalId).Replace("||", "==");
yield return $"https://v.youku.com/v_show/id_{decodeExternalId}.html";
@@ -38,7 +39,7 @@ public class ExternalUrlProvider : IExternalUrlProvider
break;
case Movie:
if (item.TryGetProviderId(Youku.ScraperProviderId, out externalId))
if (DanmuProviderId.TryGet(item, Youku.ScraperProviderId, out externalId))
{
yield return $"https://v.youku.com/v_nextstage/id_{externalId}.html";
}

View File

@@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Youku.ExternalId
{
/// <inheritdoc />
public class MovieExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Youku.ScraperProviderName;
/// <inheritdoc />
public string Key => Youku.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public string UrlFormatString => "https://v.youku.com/v_show/id_{0}.html";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Movie;
}
}

View File

@@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace Jellyfin.Plugin.Danmu.Scrapers.Youku.ExternalId
{
/// <inheritdoc />
public class SeasonExternalId : IExternalId
{
/// <inheritdoc />
public string ProviderName => Youku.ScraperProviderName;
/// <inheritdoc />
public string Key => Youku.ScraperProviderId;
/// <inheritdoc />
public ExternalIdMediaType? Type => null;
/// <inheritdoc />
public string UrlFormatString => "https://v.youku.com/v_nextstage/id_{0}.html";
/// <inheritdoc />
public bool Supports(IHasProviderIds item) => item is Season;
}
}