mirror of
https://github.com/Prowlarr/Prowlarr
synced 2026-05-08 12:43:19 +02:00
Fix BjShare torrent parsing
This commit is contained in:
parent
bde4ac29cb
commit
719d281ad7
2 changed files with 302 additions and 11 deletions
|
|
@ -0,0 +1,218 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerTests.BjShareTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class BjShareFixture
|
||||
{
|
||||
private static IndexerResponse CreateResponse(string content)
|
||||
{
|
||||
var httpRequest = new HttpRequest("https://bj-share.info/torrents.php?searchstr=test&action=basic&searchsubmit=1");
|
||||
var httpResponse = new HttpResponse(httpRequest, new HttpHeader(), new CookieCollection(), Encoding.UTF8.GetBytes(content));
|
||||
|
||||
return new IndexerResponse(new IndexerRequest(httpRequest), httpResponse);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_individual_torrent_row_from_search_results()
|
||||
{
|
||||
const string html = @"
|
||||
<table class=""torrent_table cats grouping"" id=""torrent_table"">
|
||||
<tr class=""torrent"">
|
||||
<td></td>
|
||||
<td class=""center cats_col""><a href='/torrents.php?filter_cat%5b2%5d=2'><img alt='Seriados' title='Seriados' /></a></td>
|
||||
<td class=""big_info"">
|
||||
<div class=""group_info clear"">
|
||||
<span style=""padding-left: 0px"">
|
||||
<span class=""add_bookmark float_right""><a href=""#"" class=""tooltip bookmarklink_torrent_111111"" title=""Adicionar aos Favoritos""><i class=""fad fa-bookmark""></i></a></span>
|
||||
<span class=""download_torrent float_right""><a href=""torrents.php?action=download&id=222222&source=browse"" class=""tooltip"" title=""Baixar""><i class=""fad fa-download""></i></a> </span>
|
||||
</span>
|
||||
<a href=""series.php?id=3333"">Cidade Invisivel [Invisible City]</a> - <a href=""torrents.php?id=111111&torrentid=222222"" class=""tooltip"" title=""View torrent group"" dir=""ltr""></a> [2021]
|
||||
<div class=""torrent_info"" data-imdbid="""" data-audiotype=""Legendado"" data-videocodec=""x264"" data-audiocodec=""AC3"" data-language=""Portugues"" data-format=""MKV"" data-resolution=""HD"" data-name=""Cidade Invisivel [Invisible City] - [2021]"" data-localizedname="""" data-year=""2021"">[MKV / x264 / HDTV / HD / Legendado / <strong class=""torrent_label bjtooltip free"" title=""Free"">Free</strong>]</div>
|
||||
<div class=""tags""></div>
|
||||
</div>
|
||||
</td>
|
||||
<td><a href=""/user.php?username=""></a></td>
|
||||
<td class=""number_column nobr""><span class=""time bjtooltip"" title=""May 02 2021, 20:22"">5 anos atras</span></td>
|
||||
<td class=""number_column nobr"">92.05 GiB</td>
|
||||
<td class=""number_column"">121</td>
|
||||
<td class=""number_column"">6</td>
|
||||
<td class=""number_column"">2</td>
|
||||
</tr>
|
||||
</table>";
|
||||
|
||||
var parser = new BjShareParser(new IndexerCapabilitiesCategories());
|
||||
|
||||
var release = parser.ParseResponse(CreateResponse(html)).Single() as TorrentInfo;
|
||||
|
||||
release.Title.Should().Be("Invisible City 2021 MKV / x264 / HDTV / 720p / Legendado");
|
||||
release.DownloadUrl.Should().Be("https://bj-share.info/torrents.php?action=download&id=222222&source=browse");
|
||||
release.InfoUrl.Should().Be("https://bj-share.info/torrents.php?id=111111&torrentid=222222");
|
||||
release.PublishDate.Should().Be(DateTime.Parse("May 02 2021, 20:22", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal));
|
||||
release.Size.Should().Be(98837934899);
|
||||
release.Grabs.Should().Be(121);
|
||||
release.Seeders.Should().Be(6);
|
||||
release.Peers.Should().Be(8);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_full_grouped_tv_search_results_table()
|
||||
{
|
||||
const string html = @"
|
||||
<table class=""torrent_table cats grouping"" id=""torrent_table"">
|
||||
<tr class=""colhead"">
|
||||
<td class=""small""></td>
|
||||
<td class=""small cats_col""></td>
|
||||
<td onclick=""window.location='torrents.php?way=desc&order=name&searchstr=Journey+Beyond+S03E07&tags_type=0&action=basic&searchsubmit=1'"" style=""cursor: pointer"">Nome</td>
|
||||
<td>Uploader</td>
|
||||
<td onclick=""window.location='torrents.php?way=asc&order=time&searchstr=Journey+Beyond+S03E07&tags_type=0&action=basic&searchsubmit=1'"" style=""cursor: pointer"">Lancado ha</td>
|
||||
<td onclick=""window.location='torrents.php?way=desc&order=size&searchstr=Journey+Beyond+S03E07&tags_type=0&action=basic&searchsubmit=1'"" style=""cursor: pointer"">Tamanho</td>
|
||||
<td class=""center""><i class=""fas fa-redo""></i></td>
|
||||
<td class=""center""><i class=""fas fa-arrow-up""></i></td>
|
||||
<td class=""center""><i class=""fas fa-arrow-down""></i></td>
|
||||
</tr>
|
||||
<tr class=""group"">
|
||||
<td class=""center"">
|
||||
<div id=""showimg_765432"" class=""hide_torrents"">
|
||||
<a href=""#"" class=""tooltip show_torrents_link"" onclick=""toggle_group(765432, this, event)"" title=""Collapse this group.""></a>
|
||||
</div>
|
||||
</td>
|
||||
<td class=""center cats_col""><a href='/torrents.php?filter_cat%5b2%5d=2'><img width='50' height='50' src='static/common/newcaticons3/seriadob4.svg' alt='Seriados' title='Seriados' class='brackets tooltip' /></a></td>
|
||||
<td class=""big_info"">
|
||||
<div class=""group_info clear"">
|
||||
<a href=""series.php?id=4444"">Viagem Alem do Tempo [Journey Beyond]</a> - <a href=""torrents.php?id=765432"" class=""tooltip"" title=""View torrent group"" dir=""ltr"">S03E07</a> [2027]
|
||||
<span class=""add_bookmark float_right""><a href=""#"" class=""tooltip bookmarklink_torrent_765432"" title=""Adicionar aos Favoritos""><i class=""fad fa-bookmark""></i></a></span>
|
||||
<br/>
|
||||
<div class=""tags""></div>
|
||||
</div>
|
||||
</td>
|
||||
<td> </td>
|
||||
<td class=""number_column nobr upload_time""><span class=""time bjtooltip"" title=""Mar 26 2027, 22:06"">1 semana atras</span></td>
|
||||
<td class=""number_column nobr"">10.45 GiB (Max)</td>
|
||||
<td class=""number_column"">394</td>
|
||||
<td class=""number_column"">91</td>
|
||||
<td class=""number_column"">0</td>
|
||||
</tr>
|
||||
<tr class=""group_torrent groupid_765432 edition_0"">
|
||||
<td colspan=""3"">
|
||||
<span><a href=""torrents.php?action=download&id=888001&source=browse"" class=""tooltip"" title=""Baixar""><i class=""fad fa-download""></i></a></span>
|
||||
-> <a href=""torrents.php?id=765432&torrentid=888001"">[MKV / H.264 / WEB-DL / Full HD / Dolby Atmos / Dual Audio / <strong class=""torrentinfo_release"">StreamBox</strong> / <strong style=""color:red"">WANDER</strong> / <strong class=""torrent_label bjtooltip free"" title=""Free"">Free</strong>]</a>
|
||||
</td>
|
||||
<td><a href=""/user.php?username=""></a><br /><br /><span style=""color:red;font-weight:bold;float:none""><a href=""torrents.php?action=team&TeamID=55"" style=""color:red;font-weight:bold;float:none""><span style=""color:red;font-weight:bold;float:none"">WANDER</span></a></span></td>
|
||||
<td class=""nobr""><span class=""time bjtooltip"" title=""Mar 26 2027, 22:02"">1 semana atras</span></td>
|
||||
<td class=""number_column nobr"">4.58 GiB</td>
|
||||
<td class=""number_column"">286</td>
|
||||
<td class=""number_column"">74</td>
|
||||
<td class=""number_column"">5</td>
|
||||
</tr>
|
||||
<tr class=""group_torrent groupid_765432 edition_0"">
|
||||
<td colspan=""3"">
|
||||
<span><a href=""torrents.php?action=download&id=888002&source=browse"" class=""tooltip"" title=""Baixar""><i class=""fad fa-download""></i></a></span>
|
||||
-> <a href=""torrents.php?id=765432&torrentid=888002"">[MKV / H.265 / WEB-DL / 4K / Dolby Atmos / 10-bit / Dolby Vision / HDR10+ / Dual Audio / <strong class=""torrentinfo_release"">StreamBox</strong> / <strong class=""torrent_label bjtooltip free"" title=""Free"">Free</strong>]</a>
|
||||
</td>
|
||||
<td><a href=""/user.php?username=""></a></td>
|
||||
<td class=""nobr""><span class=""time bjtooltip"" title=""Mar 26 2027, 22:06"">1 semana atras</span></td>
|
||||
<td class=""number_column nobr"">10.45 GiB</td>
|
||||
<td class=""number_column"">108</td>
|
||||
<td class=""number_column"">17</td>
|
||||
<td class=""number_column"">0</td>
|
||||
</tr>
|
||||
</table>";
|
||||
|
||||
var parser = new BjShareParser(new IndexerCapabilitiesCategories());
|
||||
|
||||
var releases = parser.ParseResponse(CreateResponse(html)).Cast<TorrentInfo>().ToList();
|
||||
|
||||
releases.Should().HaveCount(2);
|
||||
releases[0].Title.Should().Be("Journey Beyond 2027 S03E07 MKV / H.264 / WEB-DL / 1080p / Dolby Atmos / Dual Audio / StreamBox / WANDER");
|
||||
releases[0].DownloadUrl.Should().Be("https://bj-share.info/torrents.php?action=download&id=888001&source=browse");
|
||||
releases[0].InfoUrl.Should().Be("https://bj-share.info/torrents.php?id=765432&torrentid=888001");
|
||||
releases[0].PublishDate.Should().Be(DateTime.Parse("Mar 26 2027, 22:02", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal));
|
||||
releases[0].Size.Should().Be(4917737553);
|
||||
releases[0].Seeders.Should().Be(74);
|
||||
releases[0].Peers.Should().Be(79);
|
||||
|
||||
releases[1].Title.Should().Be("Journey Beyond 2027 S03E07 MKV / H.265 / WEB-DL / 2160p / Dolby Atmos / 10-bit / Dolby Vision / HDR10+ / Dual Audio / StreamBox");
|
||||
releases[1].DownloadUrl.Should().Be("https://bj-share.info/torrents.php?action=download&id=888002&source=browse");
|
||||
releases[1].Size.Should().Be(11220602060);
|
||||
releases[1].Seeders.Should().Be(17);
|
||||
releases[1].Peers.Should().Be(17);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_full_grouped_movie_search_results_table_with_year_outside_anchor()
|
||||
{
|
||||
const string html = @"
|
||||
<table class=""torrent_table cats grouping"" id=""torrent_table"">
|
||||
<tr class=""colhead"">
|
||||
<td class=""small""></td>
|
||||
<td class=""small cats_col""></td>
|
||||
<td>Nome</td>
|
||||
<td>Uploader</td>
|
||||
<td>Lancado ha</td>
|
||||
<td>Tamanho</td>
|
||||
<td class=""center""><i class=""fas fa-redo""></i></td>
|
||||
<td class=""center""><i class=""fas fa-arrow-up""></i></td>
|
||||
<td class=""center""><i class=""fas fa-arrow-down""></i></td>
|
||||
</tr>
|
||||
<tr class=""group"">
|
||||
<td class=""center"">
|
||||
<div id=""showimg_654321"" class=""hide_torrents"">
|
||||
<a href=""#"" class=""tooltip show_torrents_link"" onclick=""toggle_group(654321, this, event)"" title=""Collapse this group.""></a>
|
||||
</div>
|
||||
</td>
|
||||
<td class=""center cats_col""><a href='/torrents.php?filter_cat%5b1%5d=1'><img width='50' height='50' src='static/common/newcaticons3/filmes4.svg' alt='Filmes' title='Filmes' class='brackets tooltip' /></a></td>
|
||||
<td class=""big_info"">
|
||||
<div class=""group_info clear"">
|
||||
<a href=""torrents.php?id=654321"" class=""tooltip"" title=""View torrent group"" dir=""ltr"">A Lua de Papel [Paper Moonlight]</a> [1989]
|
||||
<span class=""add_bookmark float_right""><a href=""#"" class=""tooltip bookmarklink_torrent_654321"" title=""Adicionar aos Favoritos""><i class=""fad fa-bookmark""></i></a></span>
|
||||
<br/>
|
||||
<div class=""tags""></div>
|
||||
</div>
|
||||
</td>
|
||||
<td> </td>
|
||||
<td class=""number_column nobr upload_time""><span class=""time bjtooltip"" title=""Dec 07 2019, 15:46"">6 anos atras</span></td>
|
||||
<td class=""number_column nobr"">12.90 GiB (Max)</td>
|
||||
<td class=""number_column"">40</td>
|
||||
<td class=""number_column"">0</td>
|
||||
<td class=""number_column"">1</td>
|
||||
</tr>
|
||||
<tr class=""group_torrent groupid_654321 edition_0"">
|
||||
<td colspan=""3"">
|
||||
<span><a href=""torrents.php?action=download&id=240001&source=browse"" class=""tooltip"" title=""Baixar""><i class=""fad fa-download""></i></a></span>
|
||||
-> <a href=""torrents.php?id=654321&torrentid=240001"">[MKV / H.264 / Blu-ray / Full HD / Legendado / <strong class=""torrent_label bjtooltip free"" title=""Free"">Free</strong>]</a>
|
||||
</td>
|
||||
<td><a href=""/user.php?username=""></a></td>
|
||||
<td class=""nobr""><span class=""time bjtooltip"" title=""Dec 07 2019, 15:46"">6 anos atras</span></td>
|
||||
<td class=""number_column nobr"">12.90 GiB</td>
|
||||
<td class=""number_column"">40</td>
|
||||
<td class=""number_column"">0</td>
|
||||
<td class=""number_column"">1</td>
|
||||
</tr>
|
||||
</table>";
|
||||
|
||||
var parser = new BjShareParser(new IndexerCapabilitiesCategories());
|
||||
|
||||
var release = parser.ParseResponse(CreateResponse(html)).Single() as TorrentInfo;
|
||||
|
||||
release.Title.Should().Be("Paper Moonlight 1989 MKV / H.264 / Blu-ray / 1080p / Legendado");
|
||||
release.DownloadUrl.Should().Be("https://bj-share.info/torrents.php?action=download&id=240001&source=browse");
|
||||
release.InfoUrl.Should().Be("https://bj-share.info/torrents.php?id=654321&torrentid=240001");
|
||||
release.PublishDate.Should().Be(DateTime.Parse("Dec 07 2019, 15:46", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal));
|
||||
release.Size.Should().Be(13851269529);
|
||||
release.Grabs.Should().Be(40);
|
||||
release.Seeders.Should().Be(0);
|
||||
release.Peers.Should().Be(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -77,20 +77,24 @@ private static IndexerCapabilities SetCapabilities()
|
|||
caps.Categories.AddCategoryMapping(3, NewznabStandardCategory.PC, "Aplicativos");
|
||||
caps.Categories.AddCategoryMapping(4, NewznabStandardCategory.PCGames, "Jogos");
|
||||
caps.Categories.AddCategoryMapping(5, NewznabStandardCategory.BooksComics, "Mangás");
|
||||
caps.Categories.AddCategoryMapping(6, NewznabStandardCategory.TV, "Vídeos de TV");
|
||||
caps.Categories.AddCategoryMapping(7, NewznabStandardCategory.Other, "Outros");
|
||||
caps.Categories.AddCategoryMapping(8, NewznabStandardCategory.TVSport, "Esportes");
|
||||
caps.Categories.AddCategoryMapping(9, NewznabStandardCategory.BooksMags, "Revistas");
|
||||
caps.Categories.AddCategoryMapping(10, NewznabStandardCategory.Books, "E-Books");
|
||||
caps.Categories.AddCategoryMapping(11, NewznabStandardCategory.AudioAudiobook, "Audiobook");
|
||||
caps.Categories.AddCategoryMapping(12, NewznabStandardCategory.BooksComics, "HQ");
|
||||
caps.Categories.AddCategoryMapping(12, NewznabStandardCategory.BooksComics, "Histórias em Quadrinhos");
|
||||
caps.Categories.AddCategoryMapping(13, NewznabStandardCategory.TV, "Stand Up Comedy");
|
||||
caps.Categories.AddCategoryMapping(14, NewznabStandardCategory.TVAnime, "Anime");
|
||||
caps.Categories.AddCategoryMapping(15, NewznabStandardCategory.XXXImageSet, "Fotos Adultas");
|
||||
caps.Categories.AddCategoryMapping(16, NewznabStandardCategory.TVOther, "Desenho Animado");
|
||||
caps.Categories.AddCategoryMapping(17, NewznabStandardCategory.TVDocumentary, "Documentários");
|
||||
caps.Categories.AddCategoryMapping(18, NewznabStandardCategory.Other, "Cursos");
|
||||
caps.Categories.AddCategoryMapping(19, NewznabStandardCategory.XXX, "Filmes Adultos");
|
||||
caps.Categories.AddCategoryMapping(20, NewznabStandardCategory.XXXOther, "Jogos Adultos");
|
||||
caps.Categories.AddCategoryMapping(21, NewznabStandardCategory.XXXOther, "Mangás Adultos");
|
||||
caps.Categories.AddCategoryMapping(22, NewznabStandardCategory.XXXOther, "Animes Adultos");
|
||||
caps.Categories.AddCategoryMapping(23, NewznabStandardCategory.XXXOther, "HQ Adultas");
|
||||
caps.Categories.AddCategoryMapping(23, NewznabStandardCategory.XXXOther, "HQ Adultos");
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
|
@ -267,7 +271,15 @@ private GroupContext ParseGroup(IElement row, string baseUrl)
|
|||
var groupDetailsHref = row.QuerySelector("div.group_info a[href^=\"torrents.php?id=\"]")?.GetAttribute("href");
|
||||
var seriesHref = row.QuerySelector("div.group_info a[href^=\"series.php?id=\"]")?.GetAttribute("href");
|
||||
|
||||
var title = ExtractEnglishOrFallbackTitle(rawTitle);
|
||||
var groupDetailsText = row.QuerySelector("div.group_info a[href^=\"torrents.php?id=\"][title=\"View torrent group\"]")?.TextContent?.Trim();
|
||||
var titleSource = row.QuerySelector("div.group_info a[href^=\"series.php?id=\"]")?.TextContent?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(titleSource))
|
||||
{
|
||||
titleSource = RemoveGroupDetailsText(rawTitle, groupDetailsText);
|
||||
}
|
||||
|
||||
var seasonInformation = ExtractSeasonEpisode(groupDetailsText);
|
||||
var title = ExtractEnglishOrFallbackTitle(string.IsNullOrWhiteSpace(titleSource) ? rawTitle : titleSource);
|
||||
var year = ExtractYear(rawTitle);
|
||||
var categoryId = ExtractCategoryId(categoryHref);
|
||||
|
||||
|
|
@ -275,6 +287,7 @@ private GroupContext ParseGroup(IElement row, string baseUrl)
|
|||
{
|
||||
Title = title,
|
||||
Year = year,
|
||||
SeasonEpisode = seasonInformation,
|
||||
CategoryId = categoryId,
|
||||
GroupDetailsUrl = ToAbsolute(baseUrl, groupDetailsHref),
|
||||
SeriesUrl = ToAbsolute(baseUrl, seriesHref)
|
||||
|
|
@ -291,17 +304,18 @@ private ReleaseInfo ParseGroupedTorrent(IElement row, GroupContext group, string
|
|||
|
||||
var detailsHref = row.QuerySelector("a[href*=\"torrentid=\"]")?.GetAttribute("href");
|
||||
var infoText = row.QuerySelector("td[colspan=\"3\"] a[href*=\"torrentid=\"]")?.TextContent?.Trim() ?? string.Empty;
|
||||
var peerStats = ParsePeerStats(row);
|
||||
|
||||
var release = new TorrentInfo
|
||||
{
|
||||
Guid = ToAbsolute(baseUrl, downloadHref),
|
||||
DownloadUrl = ToAbsolute(baseUrl, downloadHref),
|
||||
InfoUrl = ToAbsolute(baseUrl, detailsHref),
|
||||
Title = BuildReleaseTitle(group.Title, group.Year, infoText),
|
||||
Title = BuildReleaseTitle(group.Title, group.Year, group.SeasonEpisode, infoText),
|
||||
Categories = _categories.MapTrackerCatToNewznab(group.CategoryId.ToString()),
|
||||
Size = ParseSize(row.QuerySelector("td:nth-last-child(4)")?.TextContent),
|
||||
Seeders = ParseInt(row.QuerySelector("td:nth-last-child(2)")?.TextContent),
|
||||
Peers = ParseInt(row.QuerySelector("td:nth-last-child(1)")?.TextContent),
|
||||
Seeders = peerStats.Seeders,
|
||||
Peers = peerStats.Peers,
|
||||
Grabs = ParseInt(row.QuerySelector("td:nth-last-child(3)")?.TextContent),
|
||||
PublishDate = ParseBjDate(row.QuerySelector("td.nobr .time")?.GetAttribute("title")),
|
||||
DownloadVolumeFactor = row.QuerySelector("strong[title*=\"Free\"]") != null ? 0 : 1,
|
||||
|
|
@ -330,18 +344,21 @@ private ReleaseInfo ParseStandaloneTorrent(IElement row, string baseUrl)
|
|||
|
||||
var title = ExtractEnglishOrFallbackTitle(rawTitle);
|
||||
var year = ExtractYear(groupInfoText);
|
||||
var seasonLink = row.QuerySelector("div.group_info a.tooltip[href^=\"torrents.php\"]");
|
||||
var seasonEpisode = seasonLink?.TextContent?.Trim() ?? string.Empty;
|
||||
var categoryId = ExtractCategoryId(categoryHref);
|
||||
var peerStats = ParsePeerStats(row);
|
||||
|
||||
return new TorrentInfo
|
||||
{
|
||||
Guid = ToAbsolute(baseUrl, downloadHref),
|
||||
DownloadUrl = ToAbsolute(baseUrl, downloadHref),
|
||||
InfoUrl = ToAbsolute(baseUrl, detailsHref),
|
||||
Title = BuildReleaseTitle(title, year, infoText),
|
||||
Title = BuildReleaseTitle(title, year, seasonEpisode, infoText),
|
||||
Categories = _categories.MapTrackerCatToNewznab(categoryId.ToString()),
|
||||
Size = ParseSize(row.QuerySelector("td:nth-last-child(4)")?.TextContent),
|
||||
Seeders = ParseInt(row.QuerySelector("td:nth-last-child(2)")?.TextContent),
|
||||
Peers = ParseInt(row.QuerySelector("td:nth-last-child(1)")?.TextContent),
|
||||
Seeders = peerStats.Seeders,
|
||||
Peers = peerStats.Peers,
|
||||
Grabs = ParseInt(row.QuerySelector("td:nth-last-child(3)")?.TextContent),
|
||||
PublishDate = ParseBjDate(row.QuerySelector("td.nobr .time")?.GetAttribute("title")),
|
||||
DownloadVolumeFactor = row.QuerySelector("strong[title*=\"Free\"]") != null ? 0 : 1,
|
||||
|
|
@ -389,16 +406,71 @@ private static int ExtractCategoryId(string href)
|
|||
return int.TryParse(value, out var id) ? id : 0;
|
||||
}
|
||||
|
||||
private static string BuildReleaseTitle(string title, int? year, string infoText)
|
||||
private static string RemoveGroupDetailsText(string rawTitle, string groupDetailsText)
|
||||
{
|
||||
var title = rawTitle ?? string.Empty;
|
||||
if (!string.IsNullOrWhiteSpace(groupDetailsText))
|
||||
{
|
||||
title = Regex.Replace(title, $@"\s*-\s*{Regex.Escape(groupDetailsText)}(?=\s*\[|$)", string.Empty);
|
||||
}
|
||||
|
||||
title = Regex.Replace(title, @"\s*-\s*(?=\[(?:19|20)\d{2}\])", " ");
|
||||
|
||||
return title.Trim();
|
||||
}
|
||||
|
||||
private static string ExtractSeasonEpisode(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var match = Regex.Match(value, @"\b[ST](\d{1,2})(?:\s*E(\d{1,3}))?\b", RegexOptions.IgnoreCase);
|
||||
if (!match.Success)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var season = int.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
|
||||
if (!match.Groups[2].Success)
|
||||
{
|
||||
return $"S{season:00}";
|
||||
}
|
||||
|
||||
var episode = int.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture);
|
||||
return $"S{season:00}E{episode:00}";
|
||||
}
|
||||
|
||||
private static string BuildReleaseTitle(string title, int? year, string seasonEpisode, string infoText)
|
||||
{
|
||||
var cleanInfo = Regex.Replace(infoText ?? string.Empty, @"[\[\]]", "");
|
||||
cleanInfo = cleanInfo.Replace("Full HD", "1080p");
|
||||
cleanInfo = cleanInfo.Replace("4K", "2160p");
|
||||
cleanInfo = cleanInfo.Replace("SD", "480p");
|
||||
cleanInfo = Regex.Replace(cleanInfo, @"(^|/\s*)HD(?=\s*/|$)", "$1720p", RegexOptions.IgnoreCase);
|
||||
cleanInfo = cleanInfo.Replace(" / Free", "");
|
||||
cleanInfo = Regex.Replace(cleanInfo, @"\s+", " ").Trim();
|
||||
|
||||
return $"{title} {(year.HasValue ? year.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)} {cleanInfo}".Trim();
|
||||
if (!string.IsNullOrWhiteSpace(seasonEpisode) && Regex.IsMatch(cleanInfo, $@"\b{Regex.Escape(seasonEpisode)}\b", RegexOptions.IgnoreCase))
|
||||
{
|
||||
seasonEpisode = string.Empty;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(seasonEpisode) && Regex.IsMatch(title ?? string.Empty, $@"\b{Regex.Escape(seasonEpisode)}\b", RegexOptions.IgnoreCase))
|
||||
{
|
||||
seasonEpisode = string.Empty;
|
||||
}
|
||||
|
||||
return $"{title} {(year.HasValue ? year.Value.ToString(CultureInfo.InvariantCulture) : string.Empty)} {seasonEpisode} {cleanInfo}".Trim();
|
||||
}
|
||||
|
||||
private static (int Seeders, int Peers) ParsePeerStats(IElement row)
|
||||
{
|
||||
var seeders = ParseInt(row.QuerySelector("td:nth-last-child(2)")?.TextContent);
|
||||
var leechers = ParseInt(row.QuerySelector("td:nth-last-child(1)")?.TextContent);
|
||||
|
||||
return (seeders, seeders + leechers);
|
||||
}
|
||||
|
||||
private static DateTime PublishDateFallback() => DateTime.UtcNow;
|
||||
|
|
@ -447,6 +519,7 @@ private sealed class GroupContext
|
|||
{
|
||||
public string Title { get; set; }
|
||||
public int? Year { get; set; }
|
||||
public string SeasonEpisode { get; set; }
|
||||
public int CategoryId { get; set; }
|
||||
public string GroupDetailsUrl { get; set; }
|
||||
public string SeriesUrl { get; set; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue