Animarr/src/Animarr/Selector.php

283 lines
8 KiB
PHP
Executable file

<?php
namespace Animarr;
use Animarr\Release\Release;
use Animarr\Torrent\Torrent;
class Selector{
private $priorities = [];
private $pedanticPriorities = [];
private $pedanticPreferPublic;
private $greylist = [];
private $goldlist = [];
public function __construct(){
foreach (Database::getConfigKey("priority.list", [[]]) as $entry){
if($entry{0} === "{"){
$entry = json_decode($entry);
$p = [];
if(isset($entry->source)){
$p["source"] = constant(Release::class . "::SOURCE_" . $entry->source);
}
if(isset($entry->quality)){
$p["quality"] = constant(Release::class . "::QUALITY_" . $entry->quality);
}
if(isset($entry->best)){
$p["best"] = $entry->best;
}
if(isset($entry->trusted)){
$p["trusted"] = $entry->trusted;
}
$this->priorities[] = $p;
}
}
foreach (Database::getConfigKey("priority.pedantic.list", [[]]) as $entry){
if($entry{0} === "{"){
$entry = json_decode($entry);
$p = [];
if(isset($entry->videoCodec)){
$p["videoCodec"] = constant(Release::class . "::VIDEO_CODEC_" . $entry->videoCodec);
}
if(isset($entry->audioCodec)){
$p["audioCodec"] = constant(Release::class . "::AUDIO_CODEC_" . $entry->audioCodec);
}
if(isset($entry->crc)){
$p["crc"] = $entry->crc;
}
$this->pedanticPriorities[] = $p;
}
}
$goldlist = Database::getConfigKey("filter.groups.goldlist", []);
foreach ($goldlist as $k => $entry){
$this->goldlist[strtolower($entry)] = count($goldlist) - $k;
}
$greylist = Database::getConfigKey("filter.groups.greylist", []);
foreach ($greylist as $entry){
$this->greylist[strtolower($entry)] = $entry;
}
$this->pedanticPreferPublic = Database::getConfigKey("priority.pedantic.preferPublic", true);
}
public function calculatePriority(Release $release){
$bestMatch = PHP_INT_MAX;
foreach($this->priorities as $k => $match){
if(isset($match["source"]) and $match["source"] !== $release->getSource()){
continue;
}
if(isset($match["quality"]) and $match["quality"] !== $release->getQuality()){
continue;
}
if(isset($match["trusted"]) and $match["trusted"] !== $release->isTrusted()){
continue;
}
if(isset($match["best"]) and $match["best"] !== $release->isBest()){
continue;
}
if($bestMatch > $k){
$bestMatch = $k;
}
}
return $bestMatch;
}
public function calculatePedanticPriority(Release $release){
$bestMatch = PHP_INT_MAX;
foreach($this->pedanticPriorities as $k => $match){
if(isset($match["videoCodec"]) and $match["videoCodec"] !== $release->getVideoCodec()){
continue;
}
if(isset($match["audioCodec"]) and $match["audioCodec"] !== $release->getAudioCodec()){
continue;
}
if(isset($match["crc"]) and $match["crc"] !== ($release->getCRC() !== null)){
continue;
}
if($bestMatch > $k){
$bestMatch = $k;
}
}
return $bestMatch;
}
/**
* @param Release[] $listing
* @param array $preferGroups
* @return Release
*/
public function findBestRelease(array $listing, array $preferGroups = []){
$best = null;
foreach ($listing as $entry){
if($best === null){
$best = $entry;
continue;
}
$old = $best;
$best = $this->selectBest($best, $entry, $preferGroups);
Downloader::log("\"".$best->getOriginalTitle()."\" is better than \"".($old === $best ? $entry->getOriginalTitle() : $old->getOriginalTitle())."\"", "SELECTOR");
}
return $best;
}
private function isInList(Release $release, array $list){
$c = isset($list[strtolower($release->getGroup())]) ? 1 : 0;
foreach(explode("-", strtolower($release->getGroup())) as $i => $k){
if($k != "" and isset($list[$k])){
++$c;
}
}
return $c;
}
private function isInPriorityList(Release $release, array $list){
$c = isset($list[strtolower($release->getGroup())]) ? $list[strtolower($release->getGroup())] : 0;
foreach(explode("-", strtolower($release->getGroup())) as $i => $k){
if($k != "" and isset($list[$k])){
if($list[$k] > $c){
$c = $list[$k];
}
}
}
return $c;
}
public function selectBest(Release $e1, Release $e2, array $preferGroups = []){
$groups = [];
foreach ($preferGroups as $k){
$groups[strtolower($k)] = $k;
}
$priority1 = $this->calculatePriority($e1);
$priority2 = $this->calculatePriority($e2);
if(in_array(pathinfo(trim(strtolower($e1->getOriginalTitle())), PATHINFO_EXTENSION), Database::getConfigKey("filter.extension.greylist", []))){
$priority1 += 10000;
}
if(in_array(pathinfo(trim(strtolower($e2->getOriginalTitle())), PATHINFO_EXTENSION), Database::getConfigKey("filter.extension.greylist", []))){
$priority2 += 10000;
}
if($this->isInList($e1, $this->greylist)){
$priority1 += 5000;
}
if($this->isInList($e2, $this->greylist)){
$priority2 += 5000;
}
if($this->isInList($e1, $groups)){
$priority1 -= 10000;
}
if($this->isInList($e2, $groups)){
$priority2 -= 10000;
}
if($e1->getSource() === $e2->getSource()){
if($d = $this->isInPriorityList($e1, $this->goldlist)){
$priority1 -= 1000;
}
if($d = $this->isInPriorityList($e2, $this->goldlist)){
$priority2 -= 1000;
}
}
if($priority1 > $priority2){
return $e2;
}elseif($priority1 < $priority2){
return $e1;
}
if($d = $this->isInPriorityList($e1, $this->goldlist)){
$priority1 -= 1000 * $d;
}
if($d = $this->isInPriorityList($e2, $this->goldlist)){
$priority2 -= 1000 * $d;
}
if($priority1 > $priority2){
return $e2;
}elseif($priority1 < $priority2){
return $e1;
}
//AAAAHAHHA they are the same!
//Now starts the fun part!
$ppriority1 = $this->calculatePedanticPriority($e1);
$ppriority2 = $this->calculatePedanticPriority($e2);
if($ppriority1 > $ppriority2){
return $e2;
}elseif($ppriority1 < $ppriority2){
return $e1;
}
if($this->pedanticPreferPublic){
$e1IsPrivate = Torrent::isPrivateTorrent($e1->getDownloadLink());
$e2IsPrivate = Torrent::isPrivateTorrent($e2->getDownloadLink());
if($e1IsPrivate and !$e2IsPrivate){
return $e2;
}else if(!$e1IsPrivate and $e2IsPrivate){
return $e1;
}
}
//This handles v2s... mostly?
if($e1->getGroup() === $e2->getGroup() and $e1->getNumber() === $e2->getNumber() and $e1->getQuality() === $e2->getQuality() and $e1->getSource() === $e2->getSource() and $e1->getTitle() === $e2->getTitle() and $e1->getType() === $e2->getType()){
if($e1->getVersion() > $e2->getVersion()){
return $e1;
}else if($e1->getVersion() < $e2->getVersion()){
return $e2;
}
}
if($e1->getSeeds() > $e2->getSeeds()){
return $e1;
}else if($e1->getSeeds() < $e2->getSeeds()){
return $e2;
}
if($e1->getUploadDate() < $e2->getUploadDate()){
return $e1;
}else if($e1->getUploadDate() > $e2->getUploadDate()){
return $e2;
}
return $e1;
}
}