mirror of
https://github.com/lampame/lampac-ukraine.git
synced 2026-04-16 09:22:21 +00:00
feat(jacktor): add result deduplication and improve release identification
Add CollapseNearDuplicates method to filter near-duplicate torrent results based on quality, size, seeders, peers, season, voice, and title. Improve BuildRid to use guid/details as stable identifiers when infohash is unavailable. Add season labels to release display in Controller. Add Guid property to JackettResult model.
This commit is contained in:
parent
459e9e5dda
commit
910b2588db
@ -118,11 +118,15 @@ namespace JackTor.Controllers
|
|||||||
var similarTpl = new SimilarTpl();
|
var similarTpl = new SimilarTpl();
|
||||||
foreach (var torrent in releases)
|
foreach (var torrent in releases)
|
||||||
{
|
{
|
||||||
string releaseName = string.IsNullOrWhiteSpace(torrent.Voice)
|
string seasonLabel = (torrent.Seasons != null && torrent.Seasons.Length > 0)
|
||||||
? (torrent.Tracker ?? "Без назви")
|
? $"S{string.Join(",", torrent.Seasons.OrderBy(i => i))}"
|
||||||
: torrent.Voice;
|
: $"S{targetSeason}";
|
||||||
|
|
||||||
string qualityInfo = $"{torrent.QualityLabel} / {torrent.MediaInfo} / ↑{torrent.Seeders}";
|
string releaseName = string.IsNullOrWhiteSpace(torrent.Voice)
|
||||||
|
? $"{seasonLabel} • {(torrent.Tracker ?? "Без назви")}"
|
||||||
|
: $"{seasonLabel} • {torrent.Voice}";
|
||||||
|
|
||||||
|
string qualityInfo = $"{torrent.Tracker} / {torrent.QualityLabel} / {torrent.MediaInfo} / ↑{torrent.Seeders}";
|
||||||
string releaseLink = accsArgs($"{host}/jacktor/serial/{torrent.Rid}?rjson={rjson}&title={enTitle}&original_title={enOriginal}&s={targetSeason}");
|
string releaseLink = accsArgs($"{host}/jacktor/serial/{torrent.Rid}?rjson={rjson}&title={enTitle}&original_title={enOriginal}&s={targetSeason}");
|
||||||
|
|
||||||
similarTpl.Append(releaseName, null, qualityInfo, releaseLink);
|
similarTpl.Append(releaseName, null, qualityInfo, releaseLink);
|
||||||
|
|||||||
@ -365,7 +365,7 @@ namespace JackTor
|
|||||||
if (!string.IsNullOrWhiteSpace(_init.filter_ignore) && IsRegexMatch(regexSource, _init.filter_ignore))
|
if (!string.IsNullOrWhiteSpace(_init.filter_ignore) && IsRegexMatch(regexSource, _init.filter_ignore))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
string rid = BuildRid(raw.InfoHash, source);
|
string rid = BuildRid(raw.InfoHash, raw.Guid, raw.Details, source);
|
||||||
|
|
||||||
var parsed = new JackTorParsedResult()
|
var parsed = new JackTorParsedResult()
|
||||||
{
|
{
|
||||||
@ -403,7 +403,7 @@ namespace JackTor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = byRid.Values;
|
var result = CollapseNearDuplicates(byRid.Values);
|
||||||
|
|
||||||
IOrderedEnumerable<JackTorParsedResult> ordered = result
|
IOrderedEnumerable<JackTorParsedResult> ordered = result
|
||||||
.OrderByDescending(i => i.AudioRank)
|
.OrderByDescending(i => i.AudioRank)
|
||||||
@ -637,6 +637,54 @@ namespace JackTor
|
|||||||
return $"{mb:0.##} MB";
|
return $"{mb:0.##} MB";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<JackTorParsedResult> CollapseNearDuplicates(IEnumerable<JackTorParsedResult> items)
|
||||||
|
{
|
||||||
|
var dedup = new Dictionary<string, JackTorParsedResult>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
string seasonKey = (item.Seasons == null || item.Seasons.Length == 0)
|
||||||
|
? "-"
|
||||||
|
: string.Join(",", item.Seasons.OrderBy(i => i));
|
||||||
|
|
||||||
|
string key = $"{item.Quality}|{item.Size}|{item.Seeders}|{item.Peers}|{seasonKey}|{NormalizeVoice(item.Voice)}|{NormalizeTitle(item.Title)}";
|
||||||
|
if (dedup.TryGetValue(key, out JackTorParsedResult exists))
|
||||||
|
{
|
||||||
|
if (Score(item) > Score(exists))
|
||||||
|
dedup[key] = item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dedup[key] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dedup.Values;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string NormalizeVoice(string voice)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(voice))
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
return string.Join(",",
|
||||||
|
voice.ToLowerInvariant()
|
||||||
|
.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(i => i.Trim())
|
||||||
|
.Distinct()
|
||||||
|
.OrderBy(i => i));
|
||||||
|
}
|
||||||
|
|
||||||
|
private string NormalizeTitle(string title)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(title))
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
string lower = title.ToLowerInvariant();
|
||||||
|
lower = Regex.Replace(lower, "\\s+", " ").Trim();
|
||||||
|
return lower;
|
||||||
|
}
|
||||||
|
|
||||||
private int Score(JackTorParsedResult item)
|
private int Score(JackTorParsedResult item)
|
||||||
{
|
{
|
||||||
int qualityScore = item.Quality * 100;
|
int qualityScore = item.Quality * 100;
|
||||||
@ -648,13 +696,19 @@ namespace JackTor
|
|||||||
return qualityScore + seedScore + audioScore + gainScore + dateScore;
|
return qualityScore + seedScore + audioScore + gainScore + dateScore;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string BuildRid(string infoHash, string source)
|
private string BuildRid(string infoHash, string guid, string details, string source)
|
||||||
{
|
{
|
||||||
string hash = (infoHash ?? string.Empty).Trim().ToLowerInvariant();
|
string hash = (infoHash ?? string.Empty).Trim().ToLowerInvariant();
|
||||||
if (!string.IsNullOrWhiteSpace(hash))
|
if (!string.IsNullOrWhiteSpace(hash))
|
||||||
return hash;
|
return hash;
|
||||||
|
|
||||||
byte[] sourceBytes = Encoding.UTF8.GetBytes(source ?? string.Empty);
|
string stableId = !string.IsNullOrWhiteSpace(guid)
|
||||||
|
? guid.Trim()
|
||||||
|
: !string.IsNullOrWhiteSpace(details)
|
||||||
|
? details.Trim()
|
||||||
|
: source ?? string.Empty;
|
||||||
|
|
||||||
|
byte[] sourceBytes = Encoding.UTF8.GetBytes(stableId);
|
||||||
byte[] digest = SHA1.HashData(sourceBytes);
|
byte[] digest = SHA1.HashData(sourceBytes);
|
||||||
return Convert.ToHexString(digest).ToLowerInvariant();
|
return Convert.ToHexString(digest).ToLowerInvariant();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,6 +88,8 @@ namespace JackTor.Models
|
|||||||
|
|
||||||
public class JackettResult
|
public class JackettResult
|
||||||
{
|
{
|
||||||
|
public string Guid { get; set; }
|
||||||
|
|
||||||
public string Tracker { get; set; }
|
public string Tracker { get; set; }
|
||||||
|
|
||||||
public string TrackerId { get; set; }
|
public string TrackerId { get; set; }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user