mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-29 01:08:56 +00:00
3042 lines
96 KiB
PHP
3042 lines
96 KiB
PHP
<?php
|
|
|
|
use newznab\db\Settings;
|
|
use newznab\utility\Utility;
|
|
use newznab\processing\PProcess;
|
|
|
|
/**
|
|
* This class handles storage and retrieval of releases rows and the main processing functions
|
|
* for turning binaries into releases.
|
|
*/
|
|
class Releases
|
|
{
|
|
// RAR/ZIP Passworded indicator.
|
|
const PASSWD_NONE = 0; // No password.
|
|
const PASSWD_POTENTIAL = 1; // Might have a password.
|
|
const BAD_FILE = 2; // Possibly broken RAR/ZIP.
|
|
const PASSWD_RAR = 10; // Definitely passworded.
|
|
|
|
/**
|
|
* @access public
|
|
* @var initial binary state after being added from usenet
|
|
*/
|
|
const PROCSTAT_NEW = 0;
|
|
|
|
/**
|
|
* @access public
|
|
* @var after a binary has matched a releaseregex
|
|
*/
|
|
const PROCSTAT_TITLEMATCHED = 5;
|
|
|
|
/**
|
|
* @access public
|
|
* @var after a binary has been confirmed as having the right number of parts
|
|
*/
|
|
const PROCSTAT_READYTORELEASE = 1;
|
|
|
|
/**
|
|
* @access public
|
|
* @var binary has not matched a releaseregex
|
|
*/
|
|
const PROCSTAT_TITLENOTMATCHED = 3;
|
|
|
|
/**
|
|
* @access public
|
|
* @var binary that has finished and successfully made it into a release
|
|
*/
|
|
const PROCSTAT_RELEASED = 4;
|
|
|
|
/**
|
|
* @access public
|
|
* @var after a series of attempts to lookup the allfilled style reqid to get a name, its given up
|
|
*/
|
|
const PROCSTAT_NOREQIDNAMELOOKUPFOUND = 7;
|
|
|
|
/**
|
|
* @var SphinxSearch
|
|
*/
|
|
public $sphinxSearch;
|
|
|
|
/**
|
|
* @var newznab\db\Settings
|
|
*/
|
|
public $pdo;
|
|
|
|
/**
|
|
* @var Groups
|
|
*/
|
|
public $groups;
|
|
|
|
/**
|
|
* @var bool
|
|
*/
|
|
public $updategrabs;
|
|
|
|
/**
|
|
* @var ReleaseSearch
|
|
*/
|
|
public $releaseSearch;
|
|
|
|
/**
|
|
* @var bool
|
|
*/
|
|
public $tablePerGroup;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
public $crossPostTime;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
public $releaseCreationLimit;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
public $completion;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
public $processRequestIDs;
|
|
|
|
/**
|
|
* @var bool
|
|
*/
|
|
public $echoCLI;
|
|
|
|
/**
|
|
* @var \ConsoleTools
|
|
*/
|
|
public $consoleTools;
|
|
|
|
/**
|
|
* @var \NZB
|
|
*/
|
|
public $nzb;
|
|
|
|
/**
|
|
* @var \ReleaseCleaning
|
|
*/
|
|
public $releaseCleaning;
|
|
|
|
/**
|
|
* @var \ReleaseImage
|
|
*/
|
|
public $releaseImage;
|
|
|
|
/**
|
|
* @param array $options Class instances / Echo to cli ?
|
|
*/
|
|
public function __construct(array $options = [])
|
|
{
|
|
$defaults = [
|
|
'Echo' => true,
|
|
'ConsoleTools' => null,
|
|
'Groups' => null,
|
|
'NZB' => null,
|
|
'ReleaseCleaning' => null,
|
|
'ReleaseImage' => null,
|
|
'Releases' => null,
|
|
'Settings' => null,
|
|
];
|
|
$options += $defaults;
|
|
|
|
$this->echoCLI = ($options['Echo'] && NN_ECHOCLI);
|
|
|
|
$this->pdo = ($options['Settings'] instanceof Settings ? $options['Settings'] : new Settings());
|
|
$this->consoleTools = ($options['ConsoleTools'] instanceof \ConsoleTools ? $options['ConsoleTools'] : new \ConsoleTools(['ColorCLI' => $this->pdo->log]));
|
|
$this->groups = ($options['Groups'] instanceof \Groups ? $options['Groups'] : new \Groups(['Settings' => $this->pdo]));
|
|
$this->nzb = ($options['NZB'] instanceof \NZB ? $options['NZB'] : new \NZB());
|
|
$this->releaseCleaning = ($options['ReleaseCleaning'] instanceof \ReleaseCleaning ? $options['ReleaseCleaning'] : new \ReleaseCleaning($this->pdo));
|
|
$this->releaseImage = ($options['ReleaseImage'] instanceof \ReleaseImage ? $options['ReleaseImage'] : new \ReleaseImage($this->pdo));
|
|
$this->updategrabs = ($this->pdo->getSetting('grabstatus') == '0' ? false : true);
|
|
$this->passwordStatus = ($this->pdo->getSetting('checkpasswordedrar') == 1 ? -1 : 0);
|
|
$this->sphinxSearch = new \SphinxSearch();
|
|
$this->releaseSearch = new \ReleaseSearch($this->pdo, $this->sphinxSearch);
|
|
$this->releaseRegex = new \ReleaseRegex();
|
|
|
|
$this->tablePerGroup = ($this->pdo->getSetting('tablepergroup') == 0 ? false : true);
|
|
$this->crossPostTime = ($this->pdo->getSetting('crossposttime') != '' ? (int)$this->pdo->getSetting('crossposttime') : 2);
|
|
$this->releaseCreationLimit = ($this->pdo->getSetting('maxnzbsprocessed') != '' ? (int)$this->pdo->getSetting('maxnzbsprocessed') : 1000);
|
|
$this->completion = ($this->pdo->getSetting('completionpercent') != '' ? (int)$this->pdo->getSetting('completionpercent') : 0);
|
|
$this->processRequestIDs = (int)$this->pdo->getSetting('lookup_reqids');
|
|
if ($this->completion > 100) {
|
|
$this->completion = 100;
|
|
echo $this->pdo->log->error(PHP_EOL . 'You have an invalid setting for completion. It must be lower than 100.');
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Get a list of releases by an array of names
|
|
*/
|
|
public function getByNames($names)
|
|
{
|
|
|
|
$nsql = "1=2";
|
|
if (count($names) > 0) {
|
|
$n = array();
|
|
foreach ($names as $nm)
|
|
$n[] = " searchname = " . $this->pdo->escapeString($nm);
|
|
|
|
$nsql = "( " . implode(' or ', $n) . " )";
|
|
}
|
|
|
|
$sql = sprintf(" SELECT releases.*, CONCAT(cp.title, ' > ', c.title) AS category_name,
|
|
m.id AS movie_id, m.title, m.rating, m.cover, m.plot, m.year, m.genre, m.director, m.actors, m.tagline,
|
|
mu.id AS music_id, mu.title AS mu_title, mu.cover AS mu_cover, mu.year AS mu_year, mu.artist AS mu_artist, mu.tracks AS mu_tracks, mu.review AS mu_review,
|
|
ep.id AS ep_id, ep.showtitle AS ep_showtitle, ep.airdate AS ep_airdate, ep.fullep AS ep_fullep, ep.overview AS ep_overview,
|
|
tvrage.imgdata AS rage_imgdata, tvrage.id AS rg_ID
|
|
FROM releases
|
|
LEFT OUTER JOIN category c ON c.id = releases.categoryid
|
|
LEFT OUTER JOIN category cp ON cp.id = c.parentid
|
|
LEFT OUTER JOIN movieinfo m ON m.imdbid = releases.imdbid
|
|
LEFT OUTER JOIN musicinfo mu ON mu.id = releases.musicinfoid
|
|
LEFT OUTER JOIN episodeinfo ep ON ep.id = releases.episodeinfoid
|
|
LEFT OUTER JOIN tvrage ON tvrage.rageid = releases.rageid
|
|
WHERE %s", $nsql
|
|
);
|
|
|
|
return $this->pdo->queryDirect($sql);
|
|
}
|
|
|
|
/**
|
|
* Get a count of releases for pager. used in admin manage list
|
|
*/
|
|
public function getCount()
|
|
{
|
|
|
|
$res = $this->pdo->queryOneRow("SELECT count(id) AS num FROM releases");
|
|
|
|
return $res["num"];
|
|
}
|
|
|
|
/**
|
|
* Get a range of releases. used in admin manage list
|
|
*/
|
|
public function getRange($start, $num)
|
|
{
|
|
|
|
|
|
if ($start === false)
|
|
$limit = "";
|
|
else
|
|
$limit = " LIMIT " . $start . "," . $num;
|
|
|
|
return $this->pdo->query(" SELECT releases.*, concat(cp.title, ' > ', c.title) AS category_name FROM releases LEFT OUTER JOIN category c ON c.id = releases.categoryid LEFT OUTER JOIN category cp ON cp.id = c.parentid ORDER BY postdate DESC" . $limit);
|
|
}
|
|
|
|
/**
|
|
* Get a count of previews for pager. used in admin manage list
|
|
*/
|
|
public function getPreviewCount($previewtype, $cat)
|
|
{
|
|
|
|
|
|
$catsrch = "";
|
|
if (count($cat) > 0 && $cat[0] != -1) {
|
|
$catsrch = " and (";
|
|
foreach ($cat as $category) {
|
|
if ($category != -1) {
|
|
$categ = new Categorize();
|
|
if ($categ->isParent($category)) {
|
|
$children = $categ->getChildren($category);
|
|
$chlist = "-99";
|
|
foreach ($children as $child)
|
|
$chlist .= ", " . $child["id"];
|
|
|
|
if ($chlist != "-99")
|
|
$catsrch .= " releases.categoryid in (" . $chlist . ") or ";
|
|
} else {
|
|
$catsrch .= sprintf(" releases.categoryid = %d or ", $category);
|
|
}
|
|
}
|
|
}
|
|
$catsrch .= "1=2 )";
|
|
}
|
|
|
|
$sql = sprintf("SELECT count(id) AS num FROM releases WHERE haspreview = %d %s ", $previewtype, $catsrch);
|
|
$res = $this->pdo->queryOneRow($sql);
|
|
|
|
return $res["num"];
|
|
}
|
|
|
|
/**
|
|
* Get a range of releases. used in admin manage list
|
|
*/
|
|
public function getPreviewRange($previewtype, $cat, $start, $num)
|
|
{
|
|
|
|
|
|
$catsrch = "";
|
|
if (count($cat) > 0 && $cat[0] != -1) {
|
|
$catsrch = " and (";
|
|
foreach ($cat as $category) {
|
|
if ($category != -1) {
|
|
$categ = new Categorize();
|
|
if ($categ->isParent($category)) {
|
|
$children = $categ->getChildren($category);
|
|
$chlist = "-99";
|
|
foreach ($children as $child)
|
|
$chlist .= ", " . $child["id"];
|
|
|
|
if ($chlist != "-99")
|
|
$catsrch .= " releases.categoryid in (" . $chlist . ") or ";
|
|
} else {
|
|
$catsrch .= sprintf(" releases.categoryid = %d or ", $category);
|
|
}
|
|
}
|
|
}
|
|
$catsrch .= "1=2 )";
|
|
}
|
|
|
|
if ($start === false)
|
|
$limit = "";
|
|
else
|
|
$limit = " LIMIT " . $start . "," . $num;
|
|
|
|
$sql = sprintf(" SELECT releases.*, concat(cp.title, ' > ', c.title) AS category_name FROM releases LEFT OUTER JOIN category c ON c.id = releases.categoryid LEFT OUTER JOIN category cp ON cp.id = c.parentid WHERE haspreview = %d %s ORDER BY postdate DESC %s", $previewtype, $catsrch, $limit);
|
|
|
|
return $this->pdo->query($sql);
|
|
}
|
|
|
|
|
|
/**
|
|
* Used for pager on browse page.
|
|
*
|
|
* @param array $cat
|
|
* @param int $maxAge
|
|
* @param array $excludedCats
|
|
* @param string $groupName
|
|
*
|
|
* @return int
|
|
*/
|
|
public function getBrowseCount($cat, $maxAge = -1, $excludedCats = [], $groupName = '')
|
|
{
|
|
return $this->getPagerCount(
|
|
sprintf(
|
|
'SELECT r.id
|
|
FROM releases r
|
|
%s
|
|
WHERE r.nzbstatus = %d
|
|
AND r.passwordstatus %s
|
|
%s %s %s %s',
|
|
($groupName != '' ? 'INNER JOIN groups g ON g.id = r.groupid' : ''),
|
|
Enzebe::NZB_ADDED,
|
|
$this->showPasswords(),
|
|
($groupName != '' ? sprintf(' AND g.name = %s', $this->pdo->escapeString($groupName)) : ''),
|
|
$this->categorySQL($cat),
|
|
($maxAge > 0 ? (' AND r.postdate > NOW() - INTERVAL ' . $maxAge . ' DAY ') : ''),
|
|
(count($excludedCats) ? (' AND r.categoryid NOT IN (' . implode(',', $excludedCats) . ')') : '')
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Used for browse results.
|
|
*
|
|
* @param array $cat
|
|
* @param $start
|
|
* @param $num
|
|
* @param string $orderBy
|
|
* @param int $maxAge
|
|
* @param array $excludedCats
|
|
* @param string $groupName
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getBrowseRange($cat, $start, $num, $orderBy, $maxAge = -1, $excludedCats = [], $groupName = '')
|
|
{
|
|
$orderBy = $this->getBrowseOrder($orderBy);
|
|
return $this->pdo->query(
|
|
sprintf(
|
|
"SELECT r.*,
|
|
CONCAT(cp.title, ' > ', c.title) AS category_name,
|
|
CONCAT(cp.id, ',', c.id) AS category_ids,
|
|
g.name AS group_name,
|
|
rn.id AS nfoid,
|
|
re.releaseid AS reid
|
|
FROM releases r
|
|
STRAIGHT_JOIN groups g ON g.id = r.groupid
|
|
STRAIGHT_JOIN category c ON c.id = r.categoryid
|
|
INNER JOIN category cp ON cp.id = c.parentid
|
|
LEFT OUTER JOIN releasevideo re ON re.releaseid = r.id
|
|
LEFT OUTER JOIN releasenfo rn ON rn.releaseid = r.id
|
|
AND rn.nfo IS NOT NULL
|
|
WHERE r.nzbstatus = %d
|
|
AND r.passwordstatus %s
|
|
%s %s %s %s
|
|
ORDER BY %s %s %s",
|
|
Enzebe::NZB_ADDED,
|
|
$this->showPasswords(),
|
|
$this->categorySQL($cat),
|
|
($maxAge > 0 ? (" AND postdate > NOW() - INTERVAL " . $maxAge . ' DAY ') : ''),
|
|
(count($excludedCats) ? (' AND r.categoryid NOT IN (' . implode(',', $excludedCats) . ')') : ''),
|
|
($groupName != '' ? sprintf(' AND g.name = %s ', $this->pdo->escapeString($groupName)) : ''),
|
|
$orderBy[0],
|
|
$orderBy[1],
|
|
($start === false ? '' : ' LIMIT ' . $num . ' OFFSET ' . $start)
|
|
),
|
|
true, NN_CACHE_EXPIRY_MEDIUM
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get a column names browse list to be ordered by
|
|
*/
|
|
public function getBrowseOrder($orderby)
|
|
{
|
|
$order = ($orderby == '') ? 'posted_desc' : $orderby;
|
|
$orderArr = explode("_", $order);
|
|
switch ($orderArr[0]) {
|
|
case 'cat':
|
|
$orderfield = 'categoryid';
|
|
break;
|
|
case 'name':
|
|
$orderfield = 'searchname';
|
|
break;
|
|
case 'size':
|
|
$orderfield = 'size';
|
|
break;
|
|
case 'files':
|
|
$orderfield = 'totalpart';
|
|
break;
|
|
case 'stats':
|
|
$orderfield = 'grabs';
|
|
break;
|
|
case 'posted':
|
|
default:
|
|
$orderfield = 'postdate';
|
|
break;
|
|
}
|
|
$ordersort = (isset($orderArr[1]) && preg_match('/^asc|desc$/i', $orderArr[1])) ? $orderArr[1] : 'desc';
|
|
|
|
return array($orderfield, $ordersort);
|
|
}
|
|
|
|
/**
|
|
* Return ordering types usable on site.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getBrowseOrdering()
|
|
{
|
|
return [
|
|
'name_asc',
|
|
'name_desc',
|
|
'cat_asc',
|
|
'cat_desc',
|
|
'posted_asc',
|
|
'posted_desc',
|
|
'size_asc',
|
|
'size_desc',
|
|
'files_asc',
|
|
'files_desc',
|
|
'stats_asc',
|
|
'stats_desc'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Get list of releases available for export.
|
|
*
|
|
* @param string $postFrom (optional) Date in this format : 01/01/2014
|
|
* @param string $postTo (optional) Date in this format : 01/01/2014
|
|
* @param string $groupID (optional) Group ID.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getForExport($postFrom = '', $postTo = '', $groupID = '')
|
|
{
|
|
return $this->pdo->query(
|
|
sprintf(
|
|
"SELECT searchname, guid, groups.name AS gname, CONCAT(cp.title,'_',category.title) AS catName
|
|
FROM releases r
|
|
INNER JOIN category ON r.categoryid = category.id
|
|
INNER JOIN groups ON r.groupid = groups.id
|
|
INNER JOIN category cp ON cp.id = category.parentid
|
|
WHERE r.nzbstatus = %d
|
|
%s %s %s",
|
|
Enzebe::NZB_ADDED,
|
|
$this->exportDateString($postFrom),
|
|
$this->exportDateString($postTo, false),
|
|
(($groupID != '' && $groupID != '-1') ? sprintf(' AND group_id = %d ', $groupID) : '')
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create a date query string for exporting.
|
|
*
|
|
* @param string $date
|
|
* @param bool $from
|
|
*
|
|
* @return string
|
|
*/
|
|
private function exportDateString($date, $from = true)
|
|
{
|
|
if ($date != '') {
|
|
$dateParts = explode('/', $date);
|
|
if (count($dateParts) === 3) {
|
|
$date = sprintf(
|
|
' AND postdate %s %s ',
|
|
($from ? '>' : '<'),
|
|
$this->pdo->escapeString(
|
|
$dateParts[2] . '-' . $dateParts[1] . '-' . $dateParts[0] .
|
|
($from ? ' 00:00:00' : ' 23:59:59')
|
|
)
|
|
);
|
|
} else {
|
|
$date = '';
|
|
}
|
|
}
|
|
return $date;
|
|
}
|
|
|
|
/**
|
|
* Get the earliest release
|
|
*/
|
|
public function getEarliestUsenetPostDate()
|
|
{
|
|
|
|
$row = $this->pdo->queryOneRow("SELECT DATE_FORMAT(min(postdate), '%d/%m/%Y') AS postdate FROM releases");
|
|
|
|
return $row["postdate"];
|
|
}
|
|
|
|
/**
|
|
* Get the most recent release
|
|
*/
|
|
public function getLatestUsenetPostDate()
|
|
{
|
|
|
|
$row = $this->pdo->queryOneRow("SELECT DATE_FORMAT(max(postdate), '%d/%m/%Y') AS postdate FROM releases");
|
|
|
|
return $row["postdate"];
|
|
}
|
|
|
|
/**
|
|
* Get all groups for which there is a release for a html select
|
|
*/
|
|
public function getReleasedGroupsForSelect($blnIncludeAll = true)
|
|
{
|
|
|
|
$groups = $this->pdo->query("SELECT DISTINCT groups.id, groups.name FROM releases INNER JOIN groups ON groups.id = releases.groupid");
|
|
$temp_array = array();
|
|
|
|
if ($blnIncludeAll)
|
|
$temp_array[-1] = "--All Groups--";
|
|
|
|
foreach ($groups as $group)
|
|
$temp_array[$group["id"]] = $group["name"];
|
|
|
|
return $temp_array;
|
|
}
|
|
|
|
/**
|
|
* Get releases for all types of rss feeds
|
|
*/
|
|
public function getRss($cat, $num, $uid = 0, $rageid, $anidbid, $airdate = -1)
|
|
{
|
|
|
|
|
|
$limit = " LIMIT 0," . ($num > 100 ? 100 : $num);
|
|
|
|
$cartsrch = "";
|
|
$catsrch = "";
|
|
|
|
if (count($cat) > 0) {
|
|
if ($cat[0] == -2) {
|
|
$cartsrch = sprintf(" inner join usercart on usercart.userid = %d and usercart.releaseid = releases.id ", $uid);
|
|
} elseif ($cat[0] == -1) {
|
|
} else {
|
|
$catsrch = " and (";
|
|
foreach ($cat as $category) {
|
|
if ($category != -1) {
|
|
$categ = new Categorize();
|
|
if ($categ->isParent($category)) {
|
|
$children = $categ->getChildren($category);
|
|
$chlist = "-99";
|
|
foreach ($children as $child)
|
|
$chlist .= ", " . $child["id"];
|
|
|
|
if ($chlist != "-99")
|
|
$catsrch .= " releases.categoryid in (" . $chlist . ") or ";
|
|
} else {
|
|
$catsrch .= sprintf(" releases.categoryid = %d or ", $category);
|
|
}
|
|
}
|
|
}
|
|
$catsrch .= "1=2 )";
|
|
}
|
|
}
|
|
|
|
$rage = ($rageid > -1) ? sprintf(" and releases.rageid = %d ", $rageid) : '';
|
|
$anidb = ($anidbid > -1) ? sprintf(" and releases.anidbid = %d ", $anidbid) : '';
|
|
$airdate = ($airdate > -1) ? sprintf(" and releases.tvairdate >= DATE_SUB(CURDATE(), INTERVAL %d DAY) ", $airdate) : '';
|
|
|
|
$sql = sprintf(" SELECT releases.*, rn.id AS nfoid, m.title AS imdbtitle, m.cover, m.imdbid, m.rating, m.plot, m.year, m.genre, m.director, m.actors, g.name AS group_name, concat(cp.title, ' > ', c.title) AS category_name, concat(cp.id, ',', c.id) AS category_ids, coalesce(cp.id,0) AS parentCategoryID, mu.title AS mu_title, mu.url AS mu_url, mu.artist AS mu_artist, mu.publisher AS mu_publisher, mu.releasedate AS mu_releasedate, mu.review AS mu_review, mu.tracks AS mu_tracks, mu.cover AS mu_cover, mug.title AS mu_genre, co.title AS co_title, co.url AS co_url, co.publisher AS co_publisher, co.releasedate AS co_releasedate, co.review AS co_review, co.cover AS co_cover, cog.title AS co_genre, bo.title AS bo_title, bo.url AS bo_url, bo.publisher AS bo_publisher, bo.author AS bo_author, bo.publishdate AS bo_publishdate, bo.review AS bo_review, bo.cover AS bo_cover FROM releases LEFT OUTER JOIN category c ON c.id = releases.categoryid LEFT OUTER JOIN category cp ON cp.id = c.parentid LEFT OUTER JOIN groups g ON g.id = releases.groupid LEFT OUTER JOIN releasenfo rn ON rn.releaseid = releases.id AND rn.nfo IS NOT NULL LEFT OUTER JOIN movieinfo m ON m.imdbid = releases.imdbid AND m.title != '' LEFT OUTER JOIN musicinfo mu ON mu.id = releases.musicinfoid LEFT OUTER JOIN genres mug ON mug.id = mu.genreID LEFT OUTER JOIN bookinfo bo ON bo.id = releases.bookinfoid LEFT OUTER JOIN consoleinfo co ON co.id = releases.consoleinfoid LEFT OUTER JOIN genres cog ON cog.id = co.genreID %s WHERE releases.passwordstatus <= (SELECT value FROM settings WHERE setting='showpasswordedrelease') %s %s %s %s ORDER BY postdate DESC %s", $cartsrch, $catsrch, $rage, $anidb, $airdate, $limit);
|
|
|
|
return $this->pdo->query($sql, true);
|
|
}
|
|
|
|
/**
|
|
* Get releases in users 'my tv show' rss feed
|
|
*/
|
|
public function getShowsRss($num, $uid = 0, $excludedcats = array(), $airdate = -1)
|
|
{
|
|
|
|
|
|
$exccatlist = "";
|
|
if (count($excludedcats) > 0)
|
|
$exccatlist = " and releases.categoryid not in (" . implode(",", $excludedcats) . ")";
|
|
|
|
$usershows = $this->pdo->query(sprintf("SELECT rageid, categoryid FROM userseries WHERE userid = %d", $uid), true);
|
|
$usql = '(1=2 ';
|
|
foreach ($usershows as $ushow) {
|
|
$usql .= sprintf('or (releases.rageid = %d', $ushow['rageid']);
|
|
if ($ushow['categoryid'] != '') {
|
|
$catsArr = explode('|', $ushow['categoryid']);
|
|
if (count($catsArr) > 1)
|
|
$usql .= sprintf(' and releases.categoryid in (%s)', implode(',', $catsArr));
|
|
else
|
|
$usql .= sprintf(' and releases.categoryid = %d', $catsArr[0]);
|
|
}
|
|
$usql .= ') ';
|
|
}
|
|
$usql .= ') ';
|
|
|
|
$airdate = ($airdate > -1) ? sprintf(" and releases.tvairdate >= DATE_SUB(CURDATE(), INTERVAL %d DAY) ", $airdate) : '';
|
|
|
|
$limit = " LIMIT 0," . ($num > 100 ? 100 : $num);
|
|
|
|
$sql = sprintf(" SELECT releases.*, tvr.rageid, tvr.releasetitle, epinfo.overview, epinfo.director, epinfo.gueststars, epinfo.writer, epinfo.rating, epinfo.fullep, epinfo.showtitle, epinfo.tvdbid AS ep_tvdbID, g.name AS group_name, concat(cp.title, '-', c.title) AS category_name, concat(cp.id, ',', c.id) AS category_ids, coalesce(cp.id,0) AS parentCategoryID
|
|
FROM releases FORCE INDEX (ix_releases_rageID)
|
|
LEFT OUTER JOIN category c ON c.id = releases.categoryid
|
|
LEFT OUTER JOIN category cp ON cp.id = c.parentid
|
|
LEFT OUTER JOIN groups g ON g.id = releases.groupid
|
|
LEFT OUTER JOIN (SELECT id, releasetitle, rageid FROM tvrage GROUP BY rageid) tvr ON tvr.rageid = releases.rageid
|
|
LEFT OUTER JOIN episodeinfo epinfo ON epinfo.id = releases.episodeinfoid
|
|
INNER JOIN
|
|
( SELECT id FROM
|
|
( SELECT id, rageid, categoryid, season, episode FROM releases WHERE %s ORDER BY season DESC, episode DESC, postdate ASC ) releases
|
|
GROUP BY rageid, season, episode, categoryid
|
|
) z ON z.id = releases.id
|
|
WHERE %s %s %s
|
|
AND releases.passwordstatus <= (SELECT VALUE FROM settings WHERE setting='showpasswordedrelease')
|
|
ORDER BY postdate DESC %s", $usql, $usql, $exccatlist, $airdate, $limit
|
|
);
|
|
|
|
return $this->pdo->query($sql);
|
|
}
|
|
|
|
/**
|
|
* Get releases in users 'my movies' rss feed
|
|
*/
|
|
public function getMyMoviesRss($num, $uid = 0, $excludedcats = array())
|
|
{
|
|
|
|
|
|
$exccatlist = "";
|
|
if (count($excludedcats) > 0)
|
|
$exccatlist = " and releases.categoryid not in (" . implode(",", $excludedcats) . ")";
|
|
|
|
$usermovies = $this->pdo->query(sprintf("SELECT imdbid, categoryid FROM usermovies WHERE userid = %d", $uid), true);
|
|
$usql = '(1=2 ';
|
|
foreach ($usermovies as $umov) {
|
|
$usql .= sprintf('or (releases.imdbid = %d', $umov['imdbid']);
|
|
if ($umov['categoryid'] != '') {
|
|
$catsArr = explode('|', $umov['categoryid']);
|
|
if (count($catsArr) > 1)
|
|
$usql .= sprintf(' and releases.categoryid in (%s)', implode(',', $catsArr));
|
|
else
|
|
$usql .= sprintf(' and releases.categoryid = %d', $catsArr[0]);
|
|
}
|
|
$usql .= ') ';
|
|
}
|
|
$usql .= ') ';
|
|
|
|
$limit = " LIMIT 0," . ($num > 100 ? 100 : $num);
|
|
|
|
$sql = sprintf(" SELECT releases.*, mi.title AS releasetitle, g.name AS group_name, concat(cp.title, '-', c.title) AS category_name, concat(cp.id, ',', c.id) AS category_ids, coalesce(cp.id,0) AS parentCategoryID
|
|
FROM releases
|
|
LEFT OUTER JOIN category c ON c.id = releases.categoryid
|
|
LEFT OUTER JOIN category cp ON cp.id = c.parentid
|
|
LEFT OUTER JOIN groups g ON g.id = releases.groupid
|
|
LEFT OUTER JOIN movieinfo mi ON mi.imdbid = releases.imdbid
|
|
WHERE %s %s
|
|
AND releases.passwordstatus <= (SELECT VALUE FROM settings WHERE setting='showpasswordedrelease')
|
|
ORDER BY postdate DESC %s", $usql, $exccatlist, $limit
|
|
);
|
|
|
|
return $this->pdo->query($sql);
|
|
}
|
|
|
|
/**
|
|
* Get range of releases in users 'my tvshows'
|
|
*/
|
|
public function getShowsRange($usershows, $start, $num, $orderby, $maxage = -1, $excludedcats = array())
|
|
{
|
|
|
|
|
|
if ($start === false)
|
|
$limit = "";
|
|
else
|
|
$limit = " LIMIT " . $start . "," . $num;
|
|
|
|
$exccatlist = "";
|
|
if (count($excludedcats) > 0)
|
|
$exccatlist = " and releases.categoryid not in (" . implode(",", $excludedcats) . ")";
|
|
|
|
$usql = '(1=2 ';
|
|
foreach ($usershows as $ushow) {
|
|
$usql .= sprintf('or (releases.rageid = %d', $ushow['rageid']);
|
|
if ($ushow['categoryid'] != '') {
|
|
$catsArr = explode('|', $ushow['categoryid']);
|
|
if (count($catsArr) > 1)
|
|
$usql .= sprintf(' and releases.categoryid in (%s)', implode(',', $catsArr));
|
|
else
|
|
$usql .= sprintf(' and releases.categoryid = %d', $catsArr[0]);
|
|
}
|
|
$usql .= ') ';
|
|
}
|
|
$usql .= ') ';
|
|
|
|
$maxagesql = "";
|
|
if ($maxage > 0)
|
|
$maxagesql = sprintf(" and releases.postdate > now() - interval %d day ", $maxage);
|
|
|
|
$order = $this->getBrowseOrder($orderby);
|
|
$sql = sprintf(" SELECT releases.*, concat(cp.title, '-', c.title) AS category_name, concat(cp.id, ',', c.id) AS category_ids, groups.name AS group_name, pre.ctime, pre.nuketype, rn.id AS nfoid, re.releaseid AS reID FROM releases LEFT OUTER JOIN releasevideo re ON re.releaseid = releases.id LEFT OUTER JOIN groups ON groups.id = releases.groupid LEFT OUTER JOIN releasenfo rn ON rn.releaseid = releases.id AND rn.nfo IS NOT NULL LEFT OUTER JOIN category c ON c.id = releases.categoryid LEFT OUTER JOIN predb pre ON pre.id = releases.preid LEFT OUTER JOIN category cp ON cp.id = c.parentid WHERE %s %s AND releases.passwordstatus <= (SELECT VALUE FROM settings WHERE setting='showpasswordedrelease') %s ORDER BY %s %s" . $limit, $usql, $exccatlist, $maxagesql, $order[0], $order[1]);
|
|
|
|
return $this->pdo->query($sql, true);
|
|
}
|
|
|
|
/**
|
|
* Get count of releases in users 'my tvshows' for pager
|
|
*
|
|
* @param $usershows
|
|
* @param int $maxage
|
|
* @param array $excludedcats
|
|
*
|
|
* @return
|
|
*/
|
|
public function getShowsCount($usershows, $maxage = -1, $excludedcats = array())
|
|
{
|
|
|
|
|
|
$exccatlist = "";
|
|
if (count($excludedcats) > 0)
|
|
$exccatlist = " and releases.categoryid not in (" . implode(",", $excludedcats) . ")";
|
|
|
|
$usql = '(1=2 ';
|
|
foreach ($usershows as $ushow) {
|
|
$usql .= sprintf('or (releases.rageid = %d', $ushow['rageid']);
|
|
if ($ushow['categoryid'] != '') {
|
|
$catsArr = explode('|', $ushow['categoryid']);
|
|
if (count($catsArr) > 1)
|
|
$usql .= sprintf(' and releases.categoryid in (%s)', implode(',', $catsArr));
|
|
else
|
|
$usql .= sprintf(' and releases.categoryid = %d', $catsArr[0]);
|
|
}
|
|
$usql .= ') ';
|
|
}
|
|
$usql .= ') ';
|
|
|
|
$maxagesql = "";
|
|
if ($maxage > 0)
|
|
$maxagesql = sprintf(" and releases.postdate > now() - interval %d day ", $maxage);
|
|
|
|
$res = $this->pdo->queryOneRow(sprintf(" SELECT count(releases.id) AS num FROM releases WHERE %s %s AND releases.passwordstatus <= (SELECT VALUE FROM settings WHERE setting='showpasswordedrelease') %s", $usql, $exccatlist, $maxagesql), true);
|
|
|
|
return $res["num"];
|
|
}
|
|
|
|
/**
|
|
* Delete a preview associated with a release and update the release to indicate it doesnt have one.
|
|
*/
|
|
public function deletePreview($guid)
|
|
{
|
|
$this->updateHasPreview($guid, 0);
|
|
$ri = new ReleaseImage();
|
|
$ri->delete($guid);
|
|
}
|
|
|
|
/**
|
|
* Update whether a release has a preview.
|
|
*/
|
|
public function updateHasPreview($guid, $haspreview)
|
|
{
|
|
|
|
$this->pdo->queryExec(sprintf("UPDATE releases SET haspreview = %d WHERE guid = %s", $haspreview, $this->pdo->escapeString($guid)));
|
|
}
|
|
|
|
/**
|
|
* Update a release.
|
|
*/
|
|
public function update($id, $name, $searchname, $fromname, $category, $parts, $grabs, $size, $posteddate, $addeddate, $rageid, $seriesfull, $season, $episode, $imdbid, $anidbid, $tvdbid, $consoleinfoid)
|
|
{
|
|
|
|
|
|
$this->pdo->queryExec(sprintf("UPDATE releases SET name=%s, searchname=%s, fromname=%s, categoryid=%d, totalpart=%d, grabs=%d, size=%s, postdate=%s, adddate=%s, rageid=%d, seriesfull=%s, season=%s, episode=%s, imdbid=%d, anidbid=%d, tvdbid=%d,consoleinfoid=%d WHERE id = %d",
|
|
$this->pdo->escapeString($name), $this->pdo->escapeString($searchname), $this->pdo->escapeString($fromname), $category, $parts, $grabs, $this->pdo->escapeString($size), $this->pdo->escapeString($posteddate), $this->pdo->escapeString($addeddate), $rageid, $this->pdo->escapeString($seriesfull), $this->pdo->escapeString($season), $this->pdo->escapeString($episode), $imdbid, $anidbid, $tvdbid, $consoleinfoid, $id
|
|
)
|
|
);
|
|
$this->sphinxSearch->updateReleaseSearchName($id, $searchname);
|
|
}
|
|
|
|
/**
|
|
* Update multiple releases.
|
|
*/
|
|
public function updatemulti($guids, $category, $grabs, $rageid, $season, $imdbid)
|
|
{
|
|
if (!is_array($guids) || sizeof($guids) < 1)
|
|
return false;
|
|
|
|
$update = array(
|
|
'categoryid' => (($category == '-1') ? '' : $category),
|
|
'grabs' => $grabs,
|
|
'rageid' => $rageid,
|
|
'season' => $season,
|
|
'imdbid' => $imdbid
|
|
);
|
|
|
|
|
|
$updateSql = array();
|
|
foreach ($update as $updk => $updv) {
|
|
if ($updv != '')
|
|
$updateSql[] = sprintf($updk . '=%s', $this->pdo->escapeString($updv));
|
|
}
|
|
|
|
if (sizeof($updateSql) < 1) {
|
|
//echo 'no field set to be changed';
|
|
return -1;
|
|
}
|
|
|
|
$updateGuids = array();
|
|
foreach ($guids as $guid) {
|
|
$updateGuids[] = $this->pdo->escapeString($guid);
|
|
}
|
|
|
|
$sql = sprintf('UPDATE releases SET ' . implode(', ', $updateSql) . ' WHERE guid IN (%s)', implode(', ', $updateGuids));
|
|
|
|
return $this->pdo->queryExec($sql);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $rageId
|
|
* @param string $series
|
|
* @param string $episode
|
|
* @param int $offset
|
|
* @param int $limit
|
|
* @param string $name
|
|
* @param array $cat
|
|
* @param int $maxAge
|
|
*
|
|
* @return array
|
|
*/
|
|
public function searchbyRageId($rageId, $series = '', $episode = '', $offset = 0, $limit = 100, $name = '', $cat = [-1], $maxAge = -1)
|
|
{
|
|
$whereSql = sprintf(
|
|
"%s
|
|
WHERE r.categoryid BETWEEN 5000 AND 5999
|
|
AND r.nzbstatus = %d
|
|
AND r.passwordstatus %s %s %s %s %s %s %s",
|
|
($name !== '' ? $this->releaseSearch->getFullTextJoinString() : ''),
|
|
Enzebe::NZB_ADDED,
|
|
$this->showPasswords(),
|
|
($rageId != -1 ? sprintf(' AND rageid = %d ', $rageId) : ''),
|
|
($series != '' ? sprintf(' AND UPPER(r.season) = UPPER(%s)', $this->pdo->escapeString(((is_numeric($series) && strlen($series) != 4) ? sprintf('S%02d', $series) : $series))) : ''),
|
|
($episode != '' ? sprintf(' AND r.episode %s', $this->pdo->likeString((is_numeric($episode) ? sprintf('E%02d', $episode) : $episode))) : ''),
|
|
($name !== '' ? $this->releaseSearch->getSearchSQL(['searchname' => $name]) : ''),
|
|
$this->categorySQL($cat),
|
|
($maxAge > 0 ? sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge) : '')
|
|
);
|
|
|
|
$baseSql = sprintf(
|
|
"SELECT r.*,
|
|
concat(cp.title, ' > ', c.title) AS category_name,
|
|
CONCAT(cp.id, ',', c.id) AS category_ids,
|
|
groups.name AS group_name,
|
|
rn.id AS nfoid,
|
|
re.releaseid AS reid
|
|
FROM releases r
|
|
INNER JOIN category c ON c.id = r.categoryid
|
|
INNER JOIN groups ON groups.id = r.groupid
|
|
LEFT OUTER JOIN releasevideo re ON re.releaseid = r.id
|
|
LEFT OUTER JOIN releasenfo rn ON rn.releaseid = r.id AND rn.nfo IS NOT NULL
|
|
INNER JOIN category cp ON cp.id = c.parentid
|
|
%s",
|
|
$whereSql
|
|
);
|
|
|
|
$sql = sprintf(
|
|
"%s
|
|
ORDER BY postdate DESC
|
|
LIMIT %d OFFSET %d",
|
|
$baseSql,
|
|
$limit,
|
|
$offset
|
|
);
|
|
$releases = $this->pdo->query($sql);
|
|
if ($releases && count($releases)) {
|
|
$releases[0]['_totalrows'] = $this->getPagerCount($baseSql);
|
|
}
|
|
return $releases;
|
|
}
|
|
|
|
/**
|
|
* @param int $aniDbID
|
|
* @param string $episodeNumber
|
|
* @param int $offset
|
|
* @param int $limit
|
|
* @param string $name
|
|
* @param array $cat
|
|
* @param int $maxAge
|
|
*
|
|
* @return array
|
|
*/
|
|
public function searchbyAnidbId($aniDbID, $episodeNumber = '', $offset = 0, $limit = 100, $name = '', $cat = [-1], $maxAge = -1)
|
|
{
|
|
$whereSql = sprintf(
|
|
"%s
|
|
WHERE r.passwordstatus %s AND r.nzbstatus = %d %s %s %s %s %s",
|
|
($name !== '' ? $this->releaseSearch->getFullTextJoinString() : ''),
|
|
$this->showPasswords(),
|
|
Enzebe::NZB_ADDED,
|
|
($aniDbID > -1 ? sprintf(' AND anidbid = %d ', $aniDbID) : ''),
|
|
(is_numeric($episodeNumber) ? sprintf(" AND r.episode '%s' ", $this->pdo->likeString($episodeNumber)) : ''),
|
|
($name !== '' ? $this->releaseSearch->getSearchSQL(['searchname' => $name]) : ''),
|
|
$this->categorySQL($cat),
|
|
($maxAge > 0 ? sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge) : '')
|
|
);
|
|
|
|
$baseSql = sprintf(
|
|
"SELECT r.*,
|
|
CONCAT(cp.title, ' > ', c.title) AS category_name,
|
|
CONCAT(cp.id, ',', c.id) AS category_ids,
|
|
groups.name AS group_name,
|
|
rn.id AS nfoid
|
|
FROM releases r
|
|
INNER JOIN category c ON c.id = r.categoryid
|
|
INNER JOIN groups ON groups.id = r.groupid
|
|
LEFT OUTER JOIN releasenfo rn ON rn.releaseid = r.id AND rn.nfo IS NOT NULL
|
|
INNER JOIN category cp ON cp.id = c.parentid
|
|
%s",
|
|
$whereSql
|
|
);
|
|
|
|
$sql = sprintf(
|
|
"%s
|
|
ORDER BY postdate DESC
|
|
LIMIT %d OFFSET %d",
|
|
$baseSql,
|
|
$limit,
|
|
$offset
|
|
);
|
|
$releases = $this->pdo->query($sql);
|
|
if ($releases && count($releases)) {
|
|
$releases[0]['_totalrows'] = $this->getPagerCount($baseSql);
|
|
}
|
|
return $releases;
|
|
}
|
|
|
|
/**
|
|
* @param int $imDbId
|
|
* @param int $offset
|
|
* @param int $limit
|
|
* @param string $name
|
|
* @param array $cat
|
|
* @param int $maxAge
|
|
*
|
|
* @return array
|
|
*/
|
|
public function searchbyImdbId($imDbId, $offset = 0, $limit = 100, $name = '', $cat = [-1], $maxAge = -1)
|
|
{
|
|
$whereSql = sprintf(
|
|
"%s
|
|
WHERE r.categoryid BETWEEN 2000 AND 2999
|
|
AND r.nzbstatus = %d
|
|
AND r.passwordstatus %s
|
|
%s %s %s %s",
|
|
($name !== '' ? $this->releaseSearch->getFullTextJoinString() : ''),
|
|
Enzebe::NZB_ADDED,
|
|
$this->showPasswords(),
|
|
($name !== '' ? $this->releaseSearch->getSearchSQL(['searchname' => $name]) : ''),
|
|
(($imDbId != '-1' && is_numeric($imDbId)) ? sprintf(' AND imdbid = %d ', str_pad($imDbId, 7, '0', STR_PAD_LEFT)) : ''),
|
|
$this->categorySQL($cat),
|
|
($maxAge > 0 ? sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxAge) : '')
|
|
);
|
|
|
|
$baseSql = sprintf(
|
|
"SELECT r.*,
|
|
concat(cp.title, ' > ', c.title) AS category_name,
|
|
CONCAT(cp.id, ',', c.id) AS category_ids,
|
|
g.name AS group_name,
|
|
rn.id AS nfoid
|
|
FROM releases r
|
|
INNER JOIN groups g ON g.id = r.groupid
|
|
INNER JOIN category c ON c.id = r.categoryid
|
|
LEFT OUTER JOIN releasenfo rn ON rn.releaseid = r.id AND rn.nfo IS NOT NULL
|
|
INNER JOIN category cp ON cp.id = c.parentid
|
|
%s",
|
|
$whereSql
|
|
);
|
|
|
|
$sql = sprintf(
|
|
"%s
|
|
ORDER BY postdate DESC
|
|
LIMIT %d OFFSET %d",
|
|
$baseSql,
|
|
$limit,
|
|
$offset
|
|
);
|
|
$releases = $this->pdo->query($sql);
|
|
if ($releases && count($releases)) {
|
|
$releases[0]['_totalrows'] = $this->getPagerCount($baseSql);
|
|
}
|
|
return $releases;
|
|
}
|
|
|
|
/**
|
|
* Search for releases by album/artist/musicinfo. Used by API.
|
|
*/
|
|
public function searchAudio($artist, $album, $label, $track, $year, $genre = array(-1), $offset = 0, $limit = 100, $cat = array(-1), $maxage = -1)
|
|
{
|
|
$s = new Settings();
|
|
if ($s->getSetting('sphinxenabled')) {
|
|
$sphinx = new Sphinx();
|
|
$results = $sphinx->searchAudio($artist, $album, $label, $track, $year, $genre, $offset, $limit, $cat, $maxage, array(), true);
|
|
if (is_array($results))
|
|
return $results;
|
|
}
|
|
|
|
|
|
$searchsql = "";
|
|
|
|
if ($artist != "")
|
|
$searchsql .= sprintf(" and musicinfo.artist like %s ", $this->pdo->escapeString("%" . $artist . "%"));
|
|
if ($album != "")
|
|
$searchsql .= sprintf(" and musicinfo.title like %s ", $this->pdo->escapeString("%" . $album . "%"));
|
|
if ($label != "")
|
|
$searchsql .= sprintf(" and musicinfo.publisher like %s ", $this->pdo->escapeString("%" . $label . "%"));
|
|
if ($track != "")
|
|
$searchsql .= sprintf(" and musicinfo.tracks like %s ", $this->pdo->escapeString("%" . $track . "%"));
|
|
if ($year != "")
|
|
$searchsql .= sprintf(" and musicinfo.year = %d ", $year);
|
|
|
|
|
|
$catsrch = "";
|
|
$usecatindex = "";
|
|
if (count($cat) > 0 && $cat[0] != -1) {
|
|
$catsrch = " and (";
|
|
foreach ($cat as $category) {
|
|
if ($category != -1) {
|
|
$categ = new Categorize();
|
|
if ($categ->isParent($category)) {
|
|
$children = $categ->getChildren($category);
|
|
$chlist = "-99";
|
|
foreach ($children as $child)
|
|
$chlist .= ", " . $child["id"];
|
|
|
|
if ($chlist != "-99")
|
|
$catsrch .= " releases.categoryid in (" . $chlist . ") or ";
|
|
} else {
|
|
$catsrch .= sprintf(" releases.categoryid = %d or ", $category);
|
|
}
|
|
}
|
|
}
|
|
$catsrch .= "1=2 )";
|
|
$usecatindex = " use index (ix_releases_categoryID) ";
|
|
}
|
|
|
|
if ($maxage > 0)
|
|
$maxage = sprintf(" and postdate > now() - interval %d day ", $maxage);
|
|
else
|
|
$maxage = "";
|
|
|
|
$genresql = "";
|
|
if (count($genre) > 0 && $genre[0] != -1) {
|
|
$genresql = " and (";
|
|
foreach ($genre as $g) {
|
|
$genresql .= sprintf(" musicinfo.genreID = %d or ", $g);
|
|
}
|
|
$genresql .= "1=2 )";
|
|
}
|
|
|
|
$sql = sprintf("SELECT releases.*, musicinfo.cover AS mi_cover, musicinfo.review AS mi_review, musicinfo.tracks AS mi_tracks, musicinfo.publisher AS mi_publisher, musicinfo.title AS mi_title, musicinfo.artist AS mi_artist, genres.title AS music_genrename, concat(cp.title, ' > ', c.title) AS category_name, concat(cp.id, ',', c.id) AS category_ids, groups.name AS group_name, rn.id AS nfoid FROM releases %s LEFT OUTER JOIN musicinfo ON musicinfo.id = releases.musicinfoid LEFT JOIN genres ON genres.id = musicinfo.genreID LEFT OUTER JOIN groups ON groups.id = releases.groupid LEFT OUTER JOIN category c ON c.id = releases.categoryid LEFT OUTER JOIN releasenfo rn ON rn.releaseid = releases.id AND rn.nfo IS NOT NULL LEFT OUTER JOIN category cp ON cp.id = c.parentid WHERE releases.passwordstatus <= (SELECT VALUE FROM settings WHERE setting='showpasswordedrelease') %s %s %s %s ORDER BY postdate DESC LIMIT %d, %d ", $usecatindex, $searchsql, $catsrch, $maxage, $genresql, $offset, $limit);
|
|
$orderpos = strpos($sql, "order by");
|
|
$wherepos = strpos($sql, "where");
|
|
$sqlcount = "SELECT count(releases.id) AS num FROM releases INNER JOIN musicinfo ON musicinfo.id = releases.musicinfoid " . substr($sql, $wherepos, $orderpos - $wherepos);
|
|
|
|
$countres = $this->pdo->queryOneRow($sqlcount, true);
|
|
$res = $this->pdo->query($sql, true);
|
|
if (count($res) > 0)
|
|
$res[0]["_totalrows"] = $countres["num"];
|
|
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* Search for releases by author/bookinfo. Used by API.
|
|
*/
|
|
public function searchBook($author, $title, $offset = 0, $limit = 100, $maxage = -1)
|
|
{
|
|
$s = new Settings();
|
|
if ($s->getSetting('sphinxenabled')) {
|
|
$sphinx = new Sphinx();
|
|
$results = $sphinx->searchBook($author, $title, $offset, $limit, $maxage, array(), true);
|
|
if (is_array($results))
|
|
return $results;
|
|
}
|
|
|
|
|
|
$searchsql = "";
|
|
|
|
if ($author != "")
|
|
$searchsql .= sprintf(" and bookinfo.author like %s ", $this->pdo->escapeString("%" . $author . "%"));
|
|
if ($title != "")
|
|
$searchsql .= sprintf(" and bookinfo.title like %s ", $this->pdo->escapeString("%" . $title . "%"));
|
|
|
|
if ($maxage > 0)
|
|
$maxage = sprintf(" and postdate > now() - interval %d day ", $maxage);
|
|
else
|
|
$maxage = "";
|
|
|
|
$sql = sprintf("SELECT releases.*, bookinfo.cover AS bi_cover, bookinfo.review AS bi_review, bookinfo.publisher AS bi_publisher, bookinfo.pages AS bi_pages, bookinfo.publishdate AS bi_publishdate, bookinfo.title AS bi_title, bookinfo.author AS bi_author, genres.title AS book_genrename, concat(cp.title, ' > ', c.title) AS category_name, concat(cp.id, ',', c.id) AS category_ids, groups.name AS group_name, rn.id AS nfoid FROM releases LEFT OUTER JOIN bookinfo ON bookinfo.id = releases.bookinfoid LEFT JOIN genres ON genres.id = bookinfo.genreID LEFT OUTER JOIN groups ON groups.id = releases.groupid LEFT OUTER JOIN category c ON c.id = releases.categoryid LEFT OUTER JOIN releasenfo rn ON rn.releaseid = releases.id AND rn.nfo IS NOT NULL LEFT OUTER JOIN category cp ON cp.id = c.parentid WHERE releases.passwordstatus <= (SELECT value FROM settings WHERE setting='showpasswordedrelease') %s %s ORDER BY postdate DESC LIMIT %d, %d ", $searchsql, $maxage, $offset, $limit);
|
|
$orderpos = strpos($sql, "order by");
|
|
$wherepos = strpos($sql, "where");
|
|
$sqlcount = "SELECT count(releases.id) AS num FROM releases INNER JOIN bookinfo ON bookinfo.id = releases.bookinfoid " . substr($sql, $wherepos, $orderpos - $wherepos);
|
|
|
|
$countres = $this->pdo->queryOneRow($sqlcount, true);
|
|
$res = $this->pdo->query($sql, true);
|
|
if (count($res) > 0)
|
|
$res[0]["_totalrows"] = $countres["num"];
|
|
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* @param $currentID
|
|
* @param $name
|
|
* @param int $limit
|
|
* @param array $excludedCats
|
|
*
|
|
* @return array
|
|
*/
|
|
public function searchSimilar($currentID, $name, $limit = 6, $excludedCats = [])
|
|
{
|
|
// Get the category for the parent of this release.
|
|
$currRow = $this->getById($currentID);
|
|
$catRow = (new \Category(['Settings' => $this->pdo]))->getById($currRow['categoryid']);
|
|
$parentCat = $catRow['parentid'];
|
|
|
|
$results = $this->search(
|
|
$this->getSimilarName($name), -1, -1, -1, [$parentCat], -1, -1, 0, 0, -1, -1, 0, $limit, '', -1, $excludedCats
|
|
);
|
|
if (!$results) {
|
|
return $results;
|
|
}
|
|
|
|
$ret = [];
|
|
foreach ($results as $res) {
|
|
if ($res['id'] != $currentID && $res['categoryParentID'] == $parentCat) {
|
|
$ret[] = $res;
|
|
}
|
|
}
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* @param string $name
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getSimilarName($name)
|
|
{
|
|
return implode(' ', array_slice(str_word_count(str_replace(['.', '_'], ' ', $name), 2), 0, 2));
|
|
}
|
|
|
|
/**
|
|
* Function for searching on the site (by subject, searchname or advanced).
|
|
*
|
|
* @param string $searchName
|
|
* @param string $usenetName
|
|
* @param string $posterName
|
|
* @param string $groupName
|
|
* @param int $sizeFrom
|
|
* @param int $sizeTo
|
|
* @param int $hasNfo
|
|
* @param int $hasComments
|
|
* @param int $daysNew
|
|
* @param int $daysOld
|
|
* @param int $offset
|
|
* @param int $limit
|
|
* @param string $orderBy
|
|
* @param int $maxAge
|
|
* @param integer[] $excludedCats
|
|
* @param string $type
|
|
* @param array $cat
|
|
*
|
|
* @return array
|
|
*/
|
|
public function search(
|
|
$searchName,
|
|
$usenetName,
|
|
$posterName,
|
|
$groupName,
|
|
$sizeFrom,
|
|
$sizeTo,
|
|
$hasNfo,
|
|
$hasComments,
|
|
$daysNew,
|
|
$daysOld,
|
|
$offset = 0,
|
|
$limit = 1000,
|
|
$orderBy = '',
|
|
$maxAge = -1,
|
|
$excludedCats = [],
|
|
$type = 'basic',
|
|
$cat = [-1]
|
|
) {
|
|
$sizeRange = [
|
|
1 => 1,
|
|
2 => 2.5,
|
|
3 => 5,
|
|
4 => 10,
|
|
5 => 20,
|
|
6 => 30,
|
|
7 => 40,
|
|
8 => 80,
|
|
9 => 160,
|
|
10 => 320,
|
|
11 => 640,
|
|
];
|
|
|
|
if ($orderBy == '') {
|
|
$orderBy = [];
|
|
$orderBy[0] = 'postdate ';
|
|
$orderBy[1] = 'desc ';
|
|
} else {
|
|
$orderBy = $this->getBrowseOrder($orderBy);
|
|
}
|
|
|
|
$searchOptions = [];
|
|
if ($searchName != -1) {
|
|
$searchOptions['searchname'] = $searchName;
|
|
}
|
|
if ($usenetName != -1) {
|
|
$searchOptions['name'] = $usenetName;
|
|
}
|
|
if ($posterName != -1) {
|
|
$searchOptions['fromname'] = $posterName;
|
|
}
|
|
|
|
$whereSql = sprintf(
|
|
"%s
|
|
WHERE r.passwordstatus %s AND r.nzbstatus = %d %s %s %s %s %s %s %s %s %s %s %s",
|
|
$this->releaseSearch->getFullTextJoinString(),
|
|
$this->showPasswords(),
|
|
Enzebe::NZB_ADDED,
|
|
($maxAge > 0 ? sprintf(' AND r.postdate > (NOW() - INTERVAL %d DAY) ', $maxAge) : ''),
|
|
($groupName != -1 ? sprintf(' AND r.groupid = %d ', $this->groups->getIDByName($groupName)) : ''),
|
|
(array_key_exists($sizeFrom, $sizeRange) ? ' AND r.size > ' . (string)(104857600 * (int)$sizeRange[$sizeFrom]) . ' ' : ''),
|
|
(array_key_exists($sizeTo, $sizeRange) ? ' AND r.size < ' . (string)(104857600 * (int)$sizeRange[$sizeTo]) . ' ' : ''),
|
|
($hasNfo != 0 ? ' AND r.nfostatus = 1 ' : ''),
|
|
($hasComments != 0 ? ' AND r.comments > 0 ' : ''),
|
|
($type !== 'advanced' ? $this->categorySQL($cat) : ($cat[0] != '-1' ? sprintf(' AND (r.categoryid = %d) ', $cat[0]) : '')),
|
|
($daysNew != -1 ? sprintf(' AND r.postdate < (NOW() - INTERVAL %d DAY) ', $daysNew) : ''),
|
|
($daysOld != -1 ? sprintf(' AND r.postdate > (NOW() - INTERVAL %d DAY) ', $daysOld) : ''),
|
|
(count($excludedCats) > 0 ? ' AND r.categoryid NOT IN (' . implode(',', $excludedCats) . ')' : ''),
|
|
(count($searchOptions) > 0 ? $this->releaseSearch->getSearchSQL($searchOptions) : '')
|
|
);
|
|
|
|
$baseSql = sprintf(
|
|
"SELECT r.*,
|
|
CONCAT(cp.title, ' > ', c.title) AS category_name,
|
|
CONCAT(cp.id, ',', c.id) AS category_ids,
|
|
groups.name AS group_name,
|
|
rn.id AS nfoid,
|
|
re.releaseid AS reid,
|
|
cp.id AS categoryparentid
|
|
FROM releases r
|
|
LEFT OUTER JOIN releasevideo re ON re.releaseid = r.id
|
|
LEFT OUTER JOIN releasenfo rn ON rn.releaseid = r.id
|
|
INNER JOIN groups ON groups.id = r.groupid
|
|
INNER JOIN category c ON c.id = r.categoryid
|
|
INNER JOIN category cp ON cp.id = c.parentid
|
|
%s",
|
|
$whereSql
|
|
);
|
|
|
|
$sql = sprintf(
|
|
"SELECT * FROM (
|
|
%s
|
|
) r
|
|
ORDER BY r.%s %s
|
|
LIMIT %d OFFSET %d",
|
|
$baseSql,
|
|
$orderBy[0],
|
|
$orderBy[1],
|
|
$limit,
|
|
$offset
|
|
);
|
|
$releases = $this->pdo->query($sql);
|
|
if ($releases && count($releases)) {
|
|
$releases[0]['_totalrows'] = $this->getPagerCount($baseSql);
|
|
}
|
|
return $releases;
|
|
}
|
|
|
|
/**
|
|
* Get count of releases for pager.
|
|
*
|
|
* @param string $query The query to get the count from.
|
|
*
|
|
* @return int
|
|
*/
|
|
private function getPagerCount($query)
|
|
{
|
|
|
|
$count = $this->pdo->queryOneRow(
|
|
sprintf(
|
|
'SELECT COUNT(*) AS count FROM (%s LIMIT %s) z',
|
|
preg_replace('/SELECT.+?FROM\s+releases/is', 'SELECT r.id FROM releases', $query),
|
|
NN_MAX_PAGER_RESULTS
|
|
)
|
|
);
|
|
if (isset($count['count']) && is_numeric($count['count'])) {
|
|
return $count['count'];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Creates part of a query for searches requiring the categoryid's.
|
|
*
|
|
* @param array $categories
|
|
*
|
|
* @return string
|
|
*/
|
|
public function categorySQL($categories)
|
|
{
|
|
$sql = '';
|
|
if (count($categories) > 0 && $categories[0] != -1) {
|
|
$Category = new \Category(['Settings' => $this->pdo]);
|
|
$sql = ' AND (';
|
|
foreach ($categories as $category) {
|
|
if ($category != -1) {
|
|
if ($Category->isParent($category)) {
|
|
$children = $Category->getChildren($category);
|
|
$childList = '-99';
|
|
foreach ($children as $child) {
|
|
$childList .= ', ' . $child['id'];
|
|
}
|
|
|
|
if ($childList != '-99') {
|
|
$sql .= ' r.categoryid IN (' . $childList . ') OR ';
|
|
}
|
|
} else {
|
|
$sql .= sprintf(' r.categoryid = %d OR ', $category);
|
|
}
|
|
}
|
|
}
|
|
$sql .= '1=2 )';
|
|
}
|
|
|
|
return $sql;
|
|
}
|
|
|
|
/**
|
|
* @param int $id
|
|
*
|
|
* @return array|bool
|
|
*/
|
|
public function getById($id)
|
|
{
|
|
return $this->pdo->queryOneRow(
|
|
sprintf(
|
|
'SELECT r.*, g.name AS group_name
|
|
FROM releases r
|
|
INNER JOIN groups g ON g.id = r.groupid
|
|
WHERE r.id = %d',
|
|
$id
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Writes a zip file of an array of release guids directly to the stream
|
|
*/
|
|
public function getZipped($guids)
|
|
{
|
|
$s = new Settings();
|
|
$this->nzb = new NZB;
|
|
$zipfile = new zipfile();
|
|
|
|
foreach ($guids as $guid) {
|
|
$nzbpath = $this->nzb->getNZBPath($guid, $s->getSetting('nzbpath'));
|
|
|
|
if (file_exists($nzbpath)) {
|
|
ob_start();
|
|
@readgzfile($nzbpath);
|
|
$nzbfile = ob_get_contents();
|
|
ob_end_clean();
|
|
|
|
$filename = $guid;
|
|
$r = $this->getByGuid($guid);
|
|
if ($r)
|
|
$filename = $r["searchname"];
|
|
|
|
$zipfile->addFile($nzbfile, $filename . ".nzb");
|
|
}
|
|
}
|
|
|
|
return $zipfile->file();
|
|
}
|
|
|
|
/**
|
|
* Retrieve one or more releases by guid.
|
|
*/
|
|
public function getByGuid($guid)
|
|
{
|
|
|
|
if (is_array($guid)) {
|
|
$tmpguids = array();
|
|
foreach ($guid as $g)
|
|
$tmpguids[] = $this->pdo->escapeString($g);
|
|
$gsql = sprintf('guid in (%s)', implode(',', $tmpguids));
|
|
} else {
|
|
$gsql = sprintf('guid = %s', $this->pdo->escapeString($guid));
|
|
}
|
|
$sql = sprintf("SELECT releases.*, musicinfo.cover AS mi_cover, musicinfo.review AS mi_review, musicinfo.tracks AS mi_tracks, musicinfo.publisher AS mi_publisher, musicinfo.title AS mi_title, musicinfo.artist AS mi_artist, music_genre.title AS music_genrename, bookinfo.cover AS bi_cover, bookinfo.review AS bi_review, bookinfo.publisher AS bi_publisher, bookinfo.publishdate AS bi_publishdate, bookinfo.title AS bi_title, bookinfo.author AS bi_author, bookinfo.pages AS bi_pages, bookinfo.isbn AS bi_isbn, concat(cp.title, ' > ', c.title) AS category_name, concat(cp.id, ',', c.id) AS category_ids, groups.name AS group_name, movieinfo.title AS movietitle, movieinfo.year AS movieyear, (SELECT releasetitle FROM tvrage WHERE rageid = releases.rageid AND rageid > 0 LIMIT 1) AS tvreleasetitle FROM releases LEFT OUTER JOIN groups ON groups.id = releases.groupid LEFT OUTER JOIN category c ON c.id = releases.categoryid LEFT OUTER JOIN category cp ON cp.id = c.parentid LEFT OUTER JOIN musicinfo ON musicinfo.id = releases.musicinfoid LEFT OUTER JOIN bookinfo ON bookinfo.id = releases.bookinfoid LEFT OUTER JOIN movieinfo ON movieinfo.imdbid = releases.imdbid LEFT JOIN genres music_genre ON music_genre.id = musicinfo.genreID WHERE %s", $gsql);
|
|
|
|
return (is_array($guid)) ? $this->pdo->query($sql) : $this->pdo->queryOneRow($sql);
|
|
}
|
|
|
|
/**
|
|
* Removes an associated tvrage id from all releases using it.
|
|
*/
|
|
public function removeRageIdFromReleases($rageid)
|
|
{
|
|
|
|
$res = $this->pdo->queryOneRow(sprintf("SELECT count(id) AS num FROM releases WHERE rageid = %d", $rageid));
|
|
$ret = $res["num"];
|
|
$this->pdo->queryExec(sprintf("UPDATE releases SET rageid = -1, seriesfull = NULL, season = NULL, episode = NULL WHERE rageid = %d", $rageid));
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Removes an associated tvdb id from all releases using it.
|
|
*/
|
|
public function removeThetvdbIdFromReleases($tvdbID)
|
|
{
|
|
|
|
$res = $this->pdo->queryOneRow(sprintf("SELECT count(id) AS num FROM releases WHERE tvdbid = %d", $tvdbID));
|
|
$ret = $res["num"];
|
|
$res = $this->pdo->queryExec(sprintf("UPDATE releases SET tvdbid = -1 WHERE tvdbid = %d", $tvdbID));
|
|
|
|
return $ret;
|
|
}
|
|
|
|
public function removeAnidbIdFromReleases($anidbID)
|
|
{
|
|
|
|
$res = $this->pdo->queryOneRow(sprintf("SELECT count(id) AS num FROM releases WHERE anidbid = %d", $anidbID));
|
|
$ret = $res["num"];
|
|
$this->pdo->queryExec(sprintf("UPDATE releases SET anidbid = -1, episode = NULL, tvtitle = NULL, tvairdate = NULL WHERE anidbid = %d", $anidbID));
|
|
|
|
return $ret;
|
|
}
|
|
|
|
public function getReleaseNfo($id, $incnfo = true)
|
|
{
|
|
|
|
$selnfo = ($incnfo) ? ', uncompress(nfo) as nfo' : '';
|
|
|
|
return $this->pdo->queryOneRow(sprintf("SELECT id, releaseid" . $selnfo . " FROM releasenfo where releaseid = %d AND nfo IS NOT NULL", $id));
|
|
}
|
|
|
|
public function updateGrab($guid)
|
|
{
|
|
|
|
$this->pdo->queryExec(sprintf("UPDATE releases SET grabs = grabs + 1 WHERE guid = %s", $this->pdo->escapeString($guid)));
|
|
}
|
|
|
|
|
|
/**
|
|
* @param int $categorize
|
|
* @param int $postProcess
|
|
* @param string $groupName (optional)
|
|
* @param \NNTP $nntp
|
|
* @param bool $echooutput
|
|
*
|
|
* @return int
|
|
*/
|
|
public function processReleases($categorize, $postProcess, $groupName, &$nntp, $echooutput)
|
|
{
|
|
$this->echoCLI = ($echooutput && NN_ECHOCLI);
|
|
$page = new Page();
|
|
$groupID = '';
|
|
$s = new Sites();
|
|
echo $s->getLicense();
|
|
|
|
if (!empty($groupName)) {
|
|
$groupInfo = $this->groups->getByName($groupName);
|
|
$groupID = $groupInfo['id'];
|
|
}
|
|
|
|
$processReleases = microtime(true);
|
|
if ($this->echoCLI) {
|
|
$this->pdo->log->doEcho($this->pdo->log->header("Starting release update process (" . date('Y-m-d H:i:s') . ")"), true);
|
|
}
|
|
|
|
if (!file_exists($page->settings->getSetting('nzbpath'))) {
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Bad or missing nzb directory - ' . $page->settings->getSetting('nzbpath')), true);
|
|
|
|
return -1;
|
|
}
|
|
|
|
$this->checkRegexesUptoDate($page->settings->getSetting('latestregexurl'), $page->settings->getSetting('latestregexrevision'), $page->settings->getSetting('newznabID'));
|
|
|
|
$this->applyRegex($groupID);
|
|
$this->processIncompleteBinaries($groupID);
|
|
|
|
$DIR = NN_MISC;
|
|
$PYTHON = shell_exec('which python3 2>/dev/null');
|
|
$PYTHON = (empty($PYTHON) ? 'python -OOu' : 'python3 -OOu');
|
|
$processRequestIDs = (int)$page->settings->getSetting('lookup_reqids');
|
|
$consoleTools = new ConsoleTools(['ColorCLI' => $this->pdo->log]);
|
|
$totalReleasesAdded = 0;
|
|
do {
|
|
$releasesCount = $this->createReleases($groupID);
|
|
$totalReleasesAdded += $releasesCount['added'];
|
|
|
|
if ($processRequestIDs === 0) {
|
|
$this->processRequestIDs($groupID, 5000, true);
|
|
} else if ($processRequestIDs === 1) {
|
|
$this->processRequestIDs($groupID, 5000, true);
|
|
$this->processRequestIDs($groupID, 1000, false);
|
|
} else if ($processRequestIDs === 2) {
|
|
$requestIDTime = time();
|
|
if ($this->echoCLI) {
|
|
$this->pdo->log->doEcho($this->pdo->log->header("Process Releases -> Request id Threaded lookup."));
|
|
}
|
|
passthru("$PYTHON ${DIR}update_scripts/nix_scripts/tmux/python/requestid_threaded.py");
|
|
if ($this->echoCLI) {
|
|
$this->pdo->log->doEcho(
|
|
$this->pdo->log->primary(
|
|
"\nReleases updated in " .
|
|
$consoleTools->convertTime(time() - $requestIDTime)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
$this->categorizeReleases($categorize, $groupID);
|
|
$this->postProcessReleases($postProcess, $nntp);
|
|
$this->deleteBinaries($groupID);
|
|
// This loops as long as there were releases created or 3 loops, otherwise, you could loop indefinately
|
|
} while (($releasesCount['added'] + $releasesCount['dupes']) >= $this->releaseCreationLimit);
|
|
|
|
$this->deletedReleasesByGroup($groupID);
|
|
$this->deleteReleases();
|
|
|
|
//
|
|
// User/Request housekeeping, should ideally move this to its own section, but it needs to be done automatically.
|
|
//
|
|
$users = new Users;
|
|
$users->pruneRequestHistory($page->settings->getSetting('userdownloadpurgedays'));
|
|
|
|
//Print amount of added releases and time it took.
|
|
if ($this->echoCLI && $this->tablePerGroup === false) {
|
|
$countID = $this->pdo->queryOneRow('SELECT COUNT(id) AS count FROM binaries ' . (!empty($groupID) ? ' WHERE groupid = ' . $groupID : ''));
|
|
$this->pdo->log->doEcho(
|
|
$this->pdo->log->primary(
|
|
'Completed adding ' .
|
|
number_format($totalReleasesAdded) .
|
|
' releases in ' .
|
|
$this->consoleTools->convertTime(number_format(microtime(true) - $processReleases, 2)) .
|
|
'. ' .
|
|
number_format(($countID === false ? 0 : $countID['count'])) .
|
|
' binaries waiting to be converted (still incomplete or in queue for creation)'
|
|
), true
|
|
);
|
|
}
|
|
|
|
return $totalReleasesAdded;
|
|
|
|
}
|
|
/**
|
|
* Delete unwanted binaries based on size/file count using admin settings.
|
|
*
|
|
* @param int|string $groupID (optional)
|
|
*
|
|
* @void
|
|
* @access public
|
|
*/
|
|
public function deleteBinaries($groupID)
|
|
{
|
|
$group = $this->groups->getCBPTableNames($this->tablePerGroup, $groupID);
|
|
$page = new Page();
|
|
$currTime_ori = $this->pdo->queryOneRow("SELECT NOW() as now");
|
|
//
|
|
// aggregate the releasefiles upto the releases.
|
|
//
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Aggregating Files'));
|
|
$this->pdo->queryExec("UPDATE releases INNER JOIN (SELECT releaseid, COUNT(id) AS num FROM releasefiles GROUP BY releaseid) b ON b.releaseid = releases.id AND releases.rarinnerfilecount = 0 SET rarinnerfilecount = b.num");
|
|
|
|
// Remove the binaries and parts used to form releases, or that are duplicates.
|
|
//
|
|
if ($page->settings->getSetting('partsdeletechunks') > 0) {
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Chunk deleting unused binaries and parts'));
|
|
$query = sprintf("SELECT p.id AS partsID,b.id AS binariesID FROM %s p
|
|
LEFT JOIN %s b ON b.id = p.binaryid
|
|
WHERE b.dateadded < %s - INTERVAL %d HOUR LIMIT 0,%d",
|
|
$group['pname'],
|
|
$group['bname'],
|
|
$this->pdo->escapeString($currTime_ori["now"]),
|
|
ceil($page->settings->getSetting('rawretentiondays') * 24),
|
|
$page->settings->getSetting('partsdeletechunks')
|
|
);
|
|
|
|
$cc = 0;
|
|
$done = false;
|
|
while (!$done) {
|
|
$dd = $cc;
|
|
$result = $this->pdo->query($query);
|
|
if (count($result) > 0) {
|
|
$pID = array();
|
|
$bID = array();
|
|
foreach ($result as $row) {
|
|
$pID[] = $row['partsID'];
|
|
$bID[] = $row['binariesID'];
|
|
}
|
|
$pID = '(' . implode(',', $pID) . ')';
|
|
$bID = '(' . implode(',', $bID) . ')';
|
|
$fr = $this->pdo->queryExec("DELETE FROM %s WHERE id IN {$pID}", $group['pname']);
|
|
if ($fr > 0) {
|
|
$cc += $fr;
|
|
$cc += $this->pdo->queryExec("DELETE FROM %s WHERE id IN {$bID}", $group['bname']);
|
|
}
|
|
unset($pID);
|
|
unset($bID);
|
|
if ($cc == $dd) {
|
|
$done = true;
|
|
}
|
|
echo($cc % 10000 ? '.' : '');
|
|
} else {
|
|
$done = true;
|
|
}
|
|
}
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Complete - ' . $cc . ' rows affected'));
|
|
} else {
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Deleting unused binaries and parts'));
|
|
$this->pdo->queryDelete(sprintf("DELETE %s, %s FROM %s JOIN %s ON %s.id = %s.binaryid
|
|
WHERE %s.dateadded < %s - INTERVAL %d HOUR",
|
|
$group['pname'],
|
|
$group['bname'],
|
|
$group['pname'],
|
|
$group['bname'],
|
|
$group['bname'],
|
|
$group['pname'],
|
|
$group['bname'],
|
|
$this->pdo->escapeString($currTime_ori["now"]),
|
|
ceil($page->settings->getSetting('rawretentiondays') * 24)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param int $groupID
|
|
* @void
|
|
* @access public
|
|
*/
|
|
public function processIncompleteBinaries($groupID)
|
|
{
|
|
//
|
|
// Move all binaries from releases which have the correct number of files on to the next stage.
|
|
//
|
|
$retcount = 0;
|
|
$currTime_ori = $this->pdo->queryOneRow("SELECT NOW() as now");
|
|
$page = new Page();
|
|
$group = $this->groups->getCBPTableNames($this->tablePerGroup, $groupID);
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Marking binaries where all parts are available'));
|
|
$result = $this->pdo->queryDirect(sprintf("SELECT relname, date, SUM(reltotalpart) AS reltotalpart, groupid, reqid, fromname, SUM(num) AS num, coalesce(g.minfilestoformrelease, s.minfilestoformrelease) AS minfilestoformrelease FROM ( SELECT relname, reltotalpart, groupid, reqid, fromname, max(date) AS date, COUNT(id) AS num FROM %s WHERE procstat = %s GROUP BY relname, reltotalpart, groupid, reqid, fromname ORDER BY NULL ) x LEFT OUTER JOIN groups g ON g.id = x.groupid INNER JOIN ( SELECT value AS minfilestoformrelease FROM settings WHERE setting = 'minfilestoformrelease' ) s GROUP BY relname, groupid, reqid, fromname, minfilestoformrelease ORDER BY NULL", $group['bname'], Releases::PROCSTAT_TITLEMATCHED));
|
|
|
|
while ($row = $this->pdo->getAssocArray($result)) {
|
|
$retcount++;
|
|
|
|
//
|
|
// Less than the site permitted number of files in a release. Dont discard it, as it may
|
|
// be part of a set being uploaded.
|
|
//
|
|
if ($row["num"] < $row["minfilestoformrelease"]) {
|
|
//echo "Number of files in release ".$row["relname"]." less than site/group setting (".$row['num']."/".$row["minfilestoformrelease"].")\n";
|
|
}
|
|
|
|
//
|
|
// There are the same or more files in our release than the number of files specified
|
|
// in the message subject so go ahead and make a release
|
|
//
|
|
elseif ($row["num"] >= $row["reltotalpart"]) {
|
|
$incomplete = false;
|
|
|
|
if ($row['reltotalpart'] == 0 && strtotime($currTime_ori['now']) - strtotime($row['date']) < 14400) {
|
|
$incomplete = true;
|
|
} else {
|
|
// Check that the binary is complete
|
|
$binlist = $this->pdo->query(sprintf('SELECT %s.id, totalparts, date, COUNT(DISTINCT %s.messageid) AS num FROM %s,
|
|
%s WHERE %s.id=%s.binaryid AND %s.relname = %s
|
|
AND %s.procstat = %d AND %s.groupid = %d AND %s.fromname = %s
|
|
GROUP BY %s.id ORDER BY NULL',
|
|
$group['bname'],
|
|
$group['pname'],
|
|
$group['bname'],
|
|
$group['pname'],
|
|
$group['bname'],
|
|
$group['pname'],
|
|
$group['bname'],
|
|
$this->pdo->escapeString($row["relname"]),
|
|
$group['bname'],
|
|
Releases::PROCSTAT_TITLEMATCHED,
|
|
$group['bname'],
|
|
$row['groupid'],
|
|
$group['bname'],
|
|
$this->pdo->escapeString($row["fromname"]),
|
|
$group['bname']
|
|
)
|
|
);
|
|
|
|
foreach ($binlist as $rowbin) {
|
|
if ($rowbin['num'] < $rowbin['totalparts']) {
|
|
// Allow to binary to release if posted to usenet longer than four hours ago and we still don't have all the parts
|
|
if (!(strtotime($currTime_ori['now']) - strtotime($rowbin['date']) > 14400)) {
|
|
$incomplete = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$incomplete) {
|
|
//
|
|
// Right number of files, but see if the binary is a allfilled/reqid post, in which case it needs its name looked up
|
|
//
|
|
if ($row['reqid'] != '' && $page->settings->getSetting('reqidurl') != "") {
|
|
//
|
|
// Try and get the name using the group
|
|
//
|
|
$binGroup = $this->groups->getByNameById($groupID);
|
|
$newtitle = $this->getReleaseNameForReqId($page->settings->getSetting('reqidurl'), $page->settings->getSetting('newznabID'), $binGroup, $row["reqid"]);
|
|
|
|
//
|
|
// if the feed/group wasnt supported by the scraper, then just use the release name as the title.
|
|
//
|
|
if ($newtitle == "no feed") {
|
|
$newtitle = $row["relname"];
|
|
}
|
|
|
|
//
|
|
// Valid release with right number of files and title now, so move it on
|
|
//
|
|
if ($newtitle != "") {
|
|
$this->pdo->queryExec(sprintf("UPDATE %s SET relname = %s, procstat = %d WHERE %s relname = %s AND procstat = %d AND fromname = %s",
|
|
$group['bname'], $this->pdo->escapeString($newtitle), Releases::PROCSTAT_READYTORELEASE, (!empty($groupID) ? ' groupid = ' . $groupID . ' AND ' : ' '), $this->pdo->escapeString($row["relname"]), Releases::PROCSTAT_TITLEMATCHED, $this->pdo->escapeString($row["fromname"])
|
|
)
|
|
);
|
|
} else {
|
|
//
|
|
// Item not found, if the binary was added to the index yages ago, then give up.
|
|
//
|
|
$maxaddeddate = $this->pdo->queryOneRow(sprintf("SELECT NOW() AS now, MAX(dateadded) AS dateadded FROM %s WHERE relname = %s AND procstat = %d AND groupid = %d AND fromname=%s",
|
|
$group['bname'], $this->pdo->escapeString($row["relname"]), Releases::PROCSTAT_TITLEMATCHED, $groupID, $this->pdo->escapeString($row["fromname"])
|
|
)
|
|
);
|
|
|
|
//
|
|
// If added to the index over 48 hours ago, give up trying to determine the title
|
|
//
|
|
if (strtotime($maxaddeddate['now']) - strtotime($maxaddeddate['dateadded']) > (60 * 60 * 48)) {
|
|
$this->pdo->queryExec(sprintf("UPDATE %s SET procstat=%d WHERE relname = %s AND procstat = %d AND groupid = %d AND fromname=%s",
|
|
$group['bname'], Releases::PROCSTAT_NOREQIDNAMELOOKUPFOUND, $this->pdo->escapeString($row["relname"]), Releases::PROCSTAT_TITLEMATCHED, $groupID, $this->pdo->escapeString($row["fromname"])
|
|
)
|
|
);
|
|
}
|
|
}
|
|
} else {
|
|
$this->pdo->queryExec(sprintf("UPDATE %s SET procstat = %d WHERE relname = %s AND procstat = %d AND %s fromname=%s",
|
|
$group['bname'], Releases::PROCSTAT_READYTORELEASE, $this->pdo->escapeString($row["relname"]), Releases::PROCSTAT_TITLEMATCHED,(!empty($groupID) ? ' groupid = ' . $groupID . ' AND ' : ' '), $this->pdo->escapeString($row["fromname"])
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if ($retcount % 100 == 0)
|
|
echo ".";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create releases from complete binaries.
|
|
*
|
|
* @param int|string $groupID (optional)
|
|
*
|
|
* @return int
|
|
* @access public
|
|
*/
|
|
public function createReleases($groupID)
|
|
{
|
|
$startTime = time();
|
|
$group = $this->groups->getCBPTableNames($this->tablePerGroup, $groupID);
|
|
$page = new Page();
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Creating releases from complete binaries'));
|
|
|
|
$this->pdo->ping(true);
|
|
//
|
|
// Get out all distinct relname, group from binaries
|
|
//
|
|
$categorize = new \Categorize(['Settings' => $this->pdo]);
|
|
$returnCount = $duplicate = 0;
|
|
$result = $this->pdo->queryDirect(sprintf("SELECT %s.*, g.name AS group_name, count(%s.id) AS parts FROM %s INNER JOIN groups g ON g.id = %s.groupid WHERE %s procstat = %d AND relname IS NOT NULL GROUP BY relname, g.name, groupid, fromname ORDER BY COUNT(%s.id) DESC LIMIT %d", $group['bname'], $group['bname'], $group['bname'], $group['bname'], (!empty($groupID) ? ' groupid = ' . $groupID . ' AND ' : ' '), Releases::PROCSTAT_READYTORELEASE, $group['bname'], $this->releaseCreationLimit));
|
|
while ($row = $this->pdo->getAssocArray($result)) {
|
|
$relguid = $this->createGUID();
|
|
// Clean release name
|
|
$releaseCleaning = new ReleaseCleaning();
|
|
$cleanRelName = $this->cleanReleaseName($row['relname']);
|
|
$cleanedName = $releaseCleaning->releaseCleaner(
|
|
$row['relname'], $row['fromname'], $row['group_name']
|
|
);
|
|
|
|
if (is_array($cleanedName)) {
|
|
$properName = $cleanedName['properlynamed'];
|
|
$prehashID = (isset($cleanerName['predb']) ? $cleanerName['predb'] : false);
|
|
$isReqID = (isset($cleanerName['requestid']) ? $cleanerName['requestid'] : false);
|
|
$cleanedName = $cleanedName['cleansubject'];
|
|
} else {
|
|
$properName = true;
|
|
$isReqID = $prehashID = false;
|
|
}
|
|
|
|
if ($prehashID === false && $cleanedName !== '') {
|
|
// try to match the cleaned searchname to predb title or filename here
|
|
$preHash = new PreHash();
|
|
$preMatch = $preHash->matchPre($cleanedName);
|
|
if ($preMatch !== false) {
|
|
$cleanedName = $preMatch['title'];
|
|
$prehashID = $preMatch['prehashid'];
|
|
$properName = true;
|
|
}
|
|
}
|
|
$relid = $this->insertRelease(
|
|
[
|
|
'name' => $this->pdo->escapeString($cleanRelName),
|
|
'searchname' => $this->pdo->escapeString(utf8_encode($cleanedName)),
|
|
'totalpart' => $row["parts"],
|
|
'groupid' => $row["groupid"],
|
|
'guid' => $this->pdo->escapeString($relguid),
|
|
'categoryid' => $categorize->determineCategory($groupID, $cleanedName),
|
|
'regexid' => $row["regexid"],
|
|
'postdate' => $this->pdo->escapeString($row['date']),
|
|
'fromname' => $this->pdo->escapeString($row['fromname']),
|
|
'reqid' => $row["reqid"],
|
|
'passwordstatus' => ($page->settings->getSetting('checkpasswordedrar') > 0 ? -1 : 0),
|
|
'nzbstatus' => \Enzebe::NZB_NONE,
|
|
'isrenamed' => ($properName === true ? 1 : 0),
|
|
'reqidstatus' => ($isReqID === true ? 1 : 0),
|
|
'prehashid' => ($prehashID === false ? 0 : $prehashID)
|
|
]
|
|
);
|
|
//
|
|
// Tag every binary for this release with its parent release id
|
|
//
|
|
$this->pdo->queryExec(sprintf("UPDATE %s SET procstat = %d, releaseid = %d WHERE relname = %s AND procstat = %d AND %s fromname=%s",
|
|
$group['bname'], Releases::PROCSTAT_RELEASED, $relid, $this->pdo->escapeString($row["relname"]), Releases::PROCSTAT_READYTORELEASE, (!empty($groupID) ? ' groupid = ' . $groupID . ' AND ' : ' '), $this->pdo->escapeString($row["fromname"])
|
|
)
|
|
);
|
|
$cat = new \Categorize(['Settings' => $this->pdo]);
|
|
|
|
//
|
|
// Write the nzb to disk
|
|
//
|
|
$catId = $cat->determineCategory($groupID, $cleanRelName);
|
|
$nzbfile = $this->nzb->getNZBPath($relguid, $page->settings->getSetting('nzbpath'), true);
|
|
$this->nzb->writeNZBforreleaseID($relid, $cleanRelName, $catId, $nzbfile, $groupID);
|
|
|
|
//
|
|
// Remove used binaries
|
|
//
|
|
$this->pdo->queryDelete(sprintf("DELETE %s, %s FROM %s JOIN %s ON %s.id = %s.binaryid WHERE releaseid = %d ",
|
|
$group['pname'],
|
|
$group['bname'],
|
|
$group['pname'],
|
|
$group['bname'],
|
|
$group['bname'],
|
|
$group['pname'],
|
|
$relid
|
|
)
|
|
);
|
|
|
|
//
|
|
// If nzb successfully written, then load it and get size completion from it
|
|
//
|
|
$nzbInfo = new NZBInfo;
|
|
if (!$nzbInfo->loadFromFile($nzbfile)) {
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Failed to write nzb file (bad perms?) ' . $nzbfile . ''));
|
|
$this->delete($relid);
|
|
} else {
|
|
// Check if gid already exists
|
|
$dupes = $this->pdo->queryOneRow(sprintf("SELECT EXISTS(SELECT 1 FROM releases WHERE gid = %s) AS total", $this->pdo->escapeString($nzbInfo->gid)));
|
|
if ($dupes['total'] > 0) {
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Duplicate - ' . $cleanRelName . ''));
|
|
$this->delete($relid);
|
|
$duplicate++;
|
|
} else {
|
|
$this->pdo->queryExec(sprintf("UPDATE releases SET totalpart = %d, size = %s, COMPLETION = %d, GID=%s , nzb_guid = %s WHERE id = %d",
|
|
$nzbInfo->filecount,
|
|
$nzbInfo->filesize,
|
|
$nzbInfo->completion,
|
|
$this->pdo->escapeString($nzbInfo->gid),
|
|
$this->pdo->escapeString($nzbInfo->gid),
|
|
$relid
|
|
)
|
|
);
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Added release ' . $cleanRelName . ''));
|
|
$returnCount++;
|
|
|
|
if ($this->echoCLI) {
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Added ' . $returnCount . 'releases.'));
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
if ($this->echoCLI) {
|
|
$this->pdo->log->doEcho(
|
|
$this->pdo->log->primary(
|
|
PHP_EOL .
|
|
number_format($returnCount) .
|
|
' Releases added and ' .
|
|
number_format($duplicate) .
|
|
' duplicate releases deleted in ' .
|
|
$this->consoleTools->convertTime(time() - $startTime)
|
|
), true
|
|
);
|
|
}
|
|
|
|
return ['added' => $returnCount, 'dupes' => $duplicate];
|
|
}
|
|
/**
|
|
* @param $url
|
|
* @param $rev
|
|
* @param $nnid
|
|
*/
|
|
public function checkRegexesUptoDate($url, $rev, $nnid)
|
|
{
|
|
if ($url != "") {
|
|
if ($nnid != "")
|
|
$nnid = "?newznabID=" . $nnid . "&rev=" . $rev;
|
|
$regfile = Utility::getUrl(['url' => $url . $nnid, 'method' => 'get', 'enctype' => 'gzip']);
|
|
if ($regfile !== false && $regfile != "") {
|
|
/*$Rev: 728 $*/
|
|
if (preg_match('/\/\*\$Rev: (\d{3,4})/i', $regfile, $matches)) {
|
|
$serverrev = intval($matches[1]);
|
|
if ($serverrev > $rev) {
|
|
|
|
$site = new Sites();
|
|
|
|
$queries = explode(";", $regfile);
|
|
$queries = array_map("trim", $queries);
|
|
foreach ($queries as $q) {
|
|
if ($q) {
|
|
$this->pdo->queryExec($q);
|
|
}
|
|
}
|
|
|
|
$site->updateLatestRegexRevision($serverrev);
|
|
echo "Updated regexes to revision " . $serverrev . "\n";
|
|
} else {
|
|
echo "Using latest regex revision " . $rev . "\n";
|
|
}
|
|
} else {
|
|
echo "Error Processing Regex File\n";
|
|
}
|
|
} else {
|
|
echo "Error Regex File Does Not Exist or Unable to Connect\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Post-process releases.
|
|
*
|
|
* @param int $postProcess
|
|
* @param NNTP $nntp
|
|
*
|
|
* @void
|
|
* @access public
|
|
*/
|
|
public function postProcessReleases($postProcess, &$nntp)
|
|
{
|
|
if ($postProcess == 1) {
|
|
(new PProcess(['Echo' => $this->echoCLI, 'Settings' => $this->pdo, 'Groups' => $this->groups]))->processAll($nntp);
|
|
} else {
|
|
if ($this->echoCLI) {
|
|
$this->pdo->log->doEcho(
|
|
$this->pdo->log->info(
|
|
"\nPost-processing is not running inside the Releases class.\n" .
|
|
"If you are using tmux or screen they might have their own scripts running Post-processing."
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* @param int|string $groupID (optional)
|
|
*/
|
|
public function applyRegex($groupID)
|
|
{
|
|
//
|
|
// Get all regexes for all groups which are to be applied to new binaries
|
|
// in order of how they should be applied
|
|
//
|
|
$group = $this->groups->getCBPTableNames($this->tablePerGroup, $groupID);
|
|
|
|
$activeGroups = $this->groups->getActive();
|
|
$this->releaseRegex->get();
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Applying regex to binaries'), true);
|
|
foreach($activeGroups as $groupArr) {
|
|
//check if regexes have already been applied during update binaries
|
|
if ($groupArr['regexmatchonly'] == 1)
|
|
continue;
|
|
|
|
$groupRegexes = $this->releaseRegex->getForGroup($groupArr['name']);
|
|
|
|
$this->pdo->log->doEcho($this->pdo->log->primary('Applying ' . sizeof($groupRegexes) . ' regexes to group ' . $groupArr['name']), true);
|
|
|
|
// Get out all binaries of STAGE0 for current group
|
|
$newUnmatchedBinaries = array();
|
|
$ressql = sprintf('SELECT id, name, date, totalparts, procstat, fromname FROM %s b
|
|
WHERE groupid = %d AND procstat IN (%d, %d) AND regexid IS NULL ORDER BY b.date ASC',
|
|
$group['bname'],
|
|
$groupArr['id'],
|
|
Releases::PROCSTAT_NEW,
|
|
Releases::PROCSTAT_TITLENOTMATCHED
|
|
);
|
|
$resbin = $this->pdo->queryDirect($ressql);
|
|
|
|
$matchedbins = 0;
|
|
while ($rowbin = $this->pdo->getAssocArray($resbin)) {
|
|
$regexMatches = array();
|
|
foreach ($groupRegexes as $groupRegex) {
|
|
$regexCheck = $this->releaseRegex->performMatch($groupRegex, $rowbin['name']);
|
|
if ($regexCheck !== false) {
|
|
$regexMatches = $regexCheck;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!empty($regexMatches)) {
|
|
$matchedbins++;
|
|
$relparts = explode("/", $regexMatches['parts']);
|
|
$this->pdo->queryExec(sprintf("UPDATE %s SET relname = replace(%s, '_', ' '), relpart = %d, reltotalpart = %d, procstat=%d, categoryid=%s, regexid=%d, reqid=%s WHERE id = %d",
|
|
$group['bname'], $this->pdo->escapeString($regexMatches['name']), $relparts[0], $relparts[1], Releases::PROCSTAT_TITLEMATCHED, $regexMatches['regcatid'], $regexMatches['regexid'], $this->pdo->escapeString($regexMatches['reqid']), $rowbin["id"]
|
|
)
|
|
);
|
|
} else {
|
|
if ($rowbin['procstat'] == Releases::PROCSTAT_NEW)
|
|
$newUnmatchedBinaries[] = $rowbin['id'];
|
|
}
|
|
|
|
}
|
|
|
|
//mark as not matched
|
|
if (!empty($newUnmatchedBinaries))
|
|
$this->pdo->queryExec(sprintf("UPDATE %s SET procstat=%d WHERE id IN (%s)", $group['bname'], Releases::PROCSTAT_TITLENOTMATCHED, implode(',', $newUnmatchedBinaries)));
|
|
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $url
|
|
* @param $nnid
|
|
* @param $groupname
|
|
* @param $reqid
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getReleaseNameForReqId($url, $nnid, $groupname, $reqid)
|
|
{
|
|
if ($reqid == " null " || $reqid == "0" || $reqid == "")
|
|
return "";
|
|
|
|
$url = str_ireplace("[GROUP]", urlencode($groupname), $url);
|
|
$url = str_ireplace("[REQID]", urlencode($reqid), $url);
|
|
|
|
if ($nnid != "") {
|
|
$url = $url . "&newznabID=" . $nnid;
|
|
}
|
|
|
|
|
|
$xml = Utility::getUrl([$url]);
|
|
|
|
if ($xml === false || preg_match('/no feed/i', $xml))
|
|
return "no feed";
|
|
else {
|
|
if ($xml != "") {
|
|
$xmlObj = @simplexml_load_string($xml);
|
|
$arrXml = objectsIntoArray($xmlObj);
|
|
|
|
if (isset($arrXml["item"]) && is_array($arrXml["item"])) {
|
|
foreach ($arrXml["item"] as $item) {
|
|
$title = (array_key_exists("@attributes", $item) ? $item["@attributes"]["title"] : $item["title"]);
|
|
|
|
return $title;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* @param $relname
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function cleanReleaseName($relname)
|
|
{
|
|
$cleanArr = array('#', '@', '$', '%', '^', '§', '¨', '©', 'Ö');
|
|
|
|
$relname = str_replace($cleanArr, '', $relname);
|
|
$relname = str_replace('_', ' ', $relname);
|
|
|
|
return $relname;
|
|
}
|
|
|
|
/**
|
|
* @param array $parameters
|
|
*
|
|
* @return bool|int
|
|
*/
|
|
public function insertRelease(array $parameters = [])
|
|
{
|
|
|
|
if ($parameters['regexid'] == "")
|
|
$parameters['regexid'] = " null ";
|
|
|
|
if ($parameters['reqid'] != "")
|
|
$parameters['reqid'] = $this->pdo->escapeString($parameters['reqid']);
|
|
else
|
|
$parameters['reqid'] = " null ";
|
|
|
|
$parameters['id'] = $this->pdo->queryInsert(sprintf("INSERT INTO releases (name, searchname, totalpart, groupid, adddate, guid, categoryid, regexid, rageid, postdate, fromname, size, reqid, passwordstatus, completion, haspreview, nfostatus, nzbstatus,
|
|
isrenamed, iscategorized, reqidstatus, prehashid)
|
|
VALUES (%s, %s, %d, %d, now(), %s, %d, %s, -1, %s, %s, 0, %s, %d, 100,-1, -1, %d, %d, 1, %d, %d)",
|
|
$parameters['name'],
|
|
$parameters['searchname'],
|
|
$parameters['totalpart'],
|
|
$parameters['groupid'],
|
|
$parameters['guid'],
|
|
$parameters['categoryid'],
|
|
$parameters['regexid'],
|
|
$parameters['postdate'],
|
|
$parameters['fromname'],
|
|
$parameters['reqid'],
|
|
$parameters['passwordstatus'],
|
|
$parameters['nzbstatus'],
|
|
$parameters['isrenamed'],
|
|
$parameters['reqidstatus'],
|
|
$parameters['prehashid']
|
|
)
|
|
);
|
|
|
|
$this->sphinxSearch->insertRelease($parameters);
|
|
|
|
return $parameters['id'];
|
|
}
|
|
|
|
|
|
/**
|
|
* @param $id
|
|
* @param bool $isGuid
|
|
*/
|
|
public function delete($id, $isGuid = false)
|
|
{
|
|
|
|
$users = new Users();
|
|
$s = new Settings();
|
|
$nfo = new Nfo();
|
|
$rf = new ReleaseFiles();
|
|
$re = new ReleaseExtra();
|
|
$rc = new ReleaseComments();
|
|
$ri = new ReleaseImage();
|
|
|
|
if (!is_array($id))
|
|
$id = array($id);
|
|
|
|
foreach ($id as $identifier) {
|
|
//
|
|
// delete from disk.
|
|
//
|
|
$rel = ($isGuid) ? $this->getByGuid($identifier) : $this->getById($identifier);
|
|
|
|
$nzbpath = "";
|
|
if ($isGuid)
|
|
$nzbpath = $s->getSetting('nzbpath') . substr($identifier, 0, 1) . "/" . $identifier . ".nzb.gz";
|
|
elseif ($rel)
|
|
$nzbpath = $s->getSetting('nzbpath') . substr($rel["guid"], 0, 1) . "/" . $rel["guid"] . ".nzb.gz";
|
|
|
|
if ($nzbpath != "" && file_exists($nzbpath))
|
|
unlink($nzbpath);
|
|
|
|
$audiopreviewpath = "";
|
|
if ($isGuid)
|
|
$audiopreviewpath = WWW_DIR . 'covers/audio/' . $identifier . ".mp3";
|
|
elseif ($rel)
|
|
$audiopreviewpath = WWW_DIR . 'covers/audio/' . $rel["guid"] . ".mp3";
|
|
|
|
if ($audiopreviewpath && file_exists($audiopreviewpath))
|
|
unlink($audiopreviewpath);
|
|
|
|
if ($rel) {
|
|
$nfo->deleteReleaseNfo($rel['id']);
|
|
$rc->deleteCommentsForRelease($rel['id']);
|
|
$users->delCartForRelease($rel['id']);
|
|
$users->delDownloadRequestsForRelease($rel['id']);
|
|
$rf->delete($rel['id']);
|
|
$re->delete($rel['id']);
|
|
$re->deleteFull($rel['id']);
|
|
$ri->delete($rel['guid']);
|
|
$this->pdo->queryExec(sprintf("DELETE FROM releases WHERE id = %d", $rel['id']));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes a single release by GUID, and all the corresponding files.
|
|
*
|
|
* @param array $identifiers ['g' => Release GUID(mandatory), 'id => ReleaseID(optional, pass false)]
|
|
* @param NZB $nzb
|
|
* @param ReleaseImage $releaseImage
|
|
*/
|
|
public function deleteSingle($identifiers, $nzb, $releaseImage)
|
|
{
|
|
// Delete NZB from disk.
|
|
$nzbPath = $nzb->getNZBPath($identifiers['g']);
|
|
if ($nzbPath) {
|
|
@unlink($nzbPath);
|
|
}
|
|
|
|
|
|
// Delete images.
|
|
$releaseImage->delete($identifiers['g']);
|
|
|
|
//Delete from sphinx.
|
|
$this->sphinxSearch->deleteRelease($identifiers, $this->pdo);
|
|
|
|
// Delete from DB.
|
|
$this->pdo->queryDelete(
|
|
sprintf('
|
|
DELETE r, rn, rc, uc, rf, ra, rs, rv, re
|
|
FROM releases r
|
|
LEFT OUTER JOIN releasenfo rn ON rn.releaseid = r.id
|
|
LEFT OUTER JOIN releasecomment rc ON rc.releaseid = r.id
|
|
LEFT OUTER JOIN usercart uc ON uc.releaseid = r.id
|
|
LEFT OUTER JOIN releasefiles rf ON rf.releaseid = r.id
|
|
LEFT OUTER JOIN releaseaudio ra ON ra.releaseid = r.id
|
|
LEFT OUTER JOIN releasesubs rs ON rs.releaseid = r.id
|
|
LEFT OUTER JOIN releasevideo rv ON rv.releaseid = r.id
|
|
LEFT OUTER JOIN releaseextrafull re ON re.releaseid = r.id
|
|
WHERE r.guid = %s',
|
|
$this->pdo->escapeString($identifiers['g'])
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getTopDownloads()
|
|
{
|
|
|
|
|
|
return $this->pdo->query("SELECT id, searchname, guid, adddate, grabs FROM releases
|
|
WHERE grabs > 0
|
|
ORDER BY grabs DESC
|
|
LIMIT 10"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getTopComments()
|
|
{
|
|
|
|
|
|
return $this->pdo->query("SELECT id, guid, searchname, adddate, comments FROM releases
|
|
WHERE comments > 0
|
|
ORDER BY comments DESC
|
|
LIMIT 10"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getRecentlyAdded()
|
|
{
|
|
|
|
|
|
return $this->pdo->query("SELECT concat(cp.title, ' > ', category.title) AS title, COUNT(*) AS count
|
|
FROM category
|
|
LEFT OUTER JOIN category cp ON cp.id = category.parentid
|
|
INNER JOIN releases ON releases.categoryid = category.id
|
|
WHERE releases.adddate > NOW() - INTERVAL 1 WEEK
|
|
GROUP BY concat(cp.title, ' > ', category.title)
|
|
ORDER BY COUNT(*) DESC"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get all newest movies with coves for poster wall.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getNewestMovies()
|
|
{
|
|
return $this->pdo->queryDirect(
|
|
"SELECT r.imdbid, r.guid, r.name, r.searchname, r.size, r.completion,
|
|
postdate, categoryid, comments, grabs,
|
|
m.cover
|
|
FROM releases r
|
|
INNER JOIN movieinfo m USING (imdbid)
|
|
WHERE r.categoryid BETWEEN 2000 AND 2999
|
|
AND m.imdbid > 0
|
|
AND m.cover = 1
|
|
AND r.id in (select max(id) from releases where imdbid > 0 group by imdbid)
|
|
ORDER BY r.postdate DESC
|
|
LIMIT 24"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get all newest console games with covers for poster wall.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getNewestConsole()
|
|
{
|
|
return $this->pdo->queryDirect(
|
|
"SELECT r.consoleinfoid, r.guid, r.name, r.searchname, r.size, r.completion,
|
|
r.postdate, r.categoryid, r.comments, r.grabs,
|
|
con.cover
|
|
FROM releases r
|
|
INNER JOIN consoleinfo con ON r.consoleinfoid = con.id
|
|
WHERE r.categoryid BETWEEN 1000 AND 1999
|
|
AND con.id > 0
|
|
AND con.cover > 0
|
|
AND r.id in (select max(id) from releases where consoleinfoid > 0 group by consoleinfoid)
|
|
ORDER BY r.postdate DESC
|
|
LIMIT 35"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get all newest PC games with covers for poster wall.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getNewestGames()
|
|
{
|
|
return $this->pdo->queryDirect(
|
|
"SELECT r.gamesinfo_id, r.guid, r.name, r.searchname, r.size, r.completion,
|
|
r.postdate, r.categoryid, r.comments, r.grabs,
|
|
gi.cover
|
|
FROM releases r
|
|
INNER JOIN gamesinfo gi ON r.gamesinfo_id = gi.id
|
|
WHERE r.categoryid = 4050
|
|
AND gi.id > 0
|
|
AND gi.cover > 0
|
|
AND r.id in (select max(id) from releases where gamesinfo_id > 0 group by gamesinfo_id)
|
|
ORDER BY r.postdate DESC
|
|
LIMIT 35"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get all newest music with covers for poster wall.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getNewestMP3s()
|
|
{
|
|
return $this->pdo->queryDirect(
|
|
"SELECT r.musicinfoid, r.guid, r.name, r.searchname, r.size, r.completion,
|
|
r.postdate, r.categoryid, r.comments, r.grabs,
|
|
m.cover
|
|
FROM releases r
|
|
INNER JOIN musicinfo m ON r.musicinfoid = m.id
|
|
WHERE r.categoryid BETWEEN 3000 AND 3999
|
|
AND r.categoryid != 3030
|
|
AND m.id > 0
|
|
AND m.cover > 0
|
|
AND r.id in (select max(id) from releases where musicinfoid > 0 group by musicinfoid)
|
|
ORDER BY r.postdate DESC
|
|
LIMIT 24"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get all newest books with covers for poster wall.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getNewestBooks()
|
|
{
|
|
return $this->pdo->queryDirect(
|
|
"SELECT r.bookinfoid, r.guid, r.name, r.searchname, r.size, r.completion,
|
|
r.postdate, r.categoryid, r.comments, r.grabs,
|
|
b.url, b.cover, b.title as booktitle, b.author
|
|
FROM releases r
|
|
INNER JOIN bookinfo b ON r.bookinfoid = b.id
|
|
WHERE r.categoryid BETWEEN 7000 AND 7999
|
|
OR r.categoryid = 3030
|
|
AND b.id > 0
|
|
AND b.cover > 0
|
|
AND r.id in (select max(id) from releases where bookinfoid > 0 group by bookinfoid)
|
|
ORDER BY r.postdate DESC
|
|
LIMIT 24"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get all newest xxx with covers for poster wall.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getNewestXXX()
|
|
{
|
|
return $this->pdo->queryDirect(
|
|
"SELECT r.xxxinfo_id, r.guid, r.name, r.searchname, r.size, r.completion,
|
|
r.postdate, r.categoryid, r.comments, r.grabs,
|
|
xxx.cover, xxx.title
|
|
FROM releases r
|
|
INNER JOIN xxxinfo xxx ON r.xxxinfo_id = xxx.id
|
|
WHERE r.categoryid BETWEEN 6000 AND 6999
|
|
AND xxx.id > 0
|
|
AND xxx.cover = 1
|
|
AND r.id in (select max(id) from releases where xxxinfo_id > 0 group by xxxinfo_id)
|
|
ORDER BY r.postdate DESC
|
|
LIMIT 24"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get all newest TV with covers for poster wall.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getNewestTV()
|
|
{
|
|
return $this->pdo->queryDirect(
|
|
"SELECT r.rageid, r.guid, r.name, r.searchname, r.size, r.completion,
|
|
r.postdate, r.categoryid, r.comments, r.grabs,
|
|
tv.id as tvid, tv.imgdata, tv.releasetitle as tvtitle
|
|
FROM releases r
|
|
INNER JOIN tvrage tv USING (rageid)
|
|
WHERE r.categoryid BETWEEN 5000 AND 5999
|
|
AND tv.rageid > 0
|
|
AND length(tv.imgdata) > 0
|
|
GROUP BY tv.rageid
|
|
ORDER BY r.postdate DESC
|
|
LIMIT 24"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Process RequestID's.
|
|
*
|
|
* @param int|string $groupID
|
|
* @param int $limit
|
|
* @param bool $local
|
|
*
|
|
* @access public
|
|
* @void
|
|
*/
|
|
public function processRequestIDs($groupID = '', $limit = 5000, $local = true)
|
|
{
|
|
|
|
$echoCLI = NN_ECHOCLI;
|
|
$groups = new Groups();
|
|
$s = new Settings();
|
|
$consoleTools = new ConsoleTools(['ColorCLI' => $this->pdo->log]);
|
|
if ($local === false && $s->getSetting('lookup_reqids') == 0) {
|
|
return;
|
|
}
|
|
|
|
$startTime = time();
|
|
if ($echoCLI) {
|
|
$this->pdo->log->doEcho(
|
|
$this->pdo->log->header(
|
|
sprintf(
|
|
"Process Releases -> Request id %s lookup -- limit %s",
|
|
($local === true ? 'local' : 'web'),
|
|
$limit
|
|
)
|
|
)
|
|
);
|
|
}
|
|
|
|
if ($local === true) {
|
|
$foundRequestIDs = (
|
|
new \RequestIDLocal(
|
|
['Echo' => $echoCLI, 'ConsoleTools' => $consoleTools,
|
|
'Groups' => $groups, 'Settings' => $this->pdo
|
|
]
|
|
)
|
|
)->lookupRequestIDs(['GroupID' => $groupID, 'limit' => $limit, 'time' => 168]);
|
|
} else {
|
|
$foundRequestIDs = (
|
|
new \RequestIDWeb(
|
|
['Echo' => $echoCLI, 'ConsoleTools' => $consoleTools,
|
|
'Groups' => $groups, 'Settings' => $this->pdo
|
|
]
|
|
)
|
|
)->lookupRequestIDs(['GroupID' => $groupID, 'limit' => $limit, 'time' => 168]);
|
|
}
|
|
if ($echoCLI) {
|
|
$this->pdo->log->doEcho(
|
|
$this->pdo->log->primary(
|
|
number_format($foundRequestIDs) .
|
|
' releases updated in ' .
|
|
$consoleTools->convertTime(time() - $startTime)
|
|
), true
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete unwanted releases based on admin settings.
|
|
* This deletes releases based on group.
|
|
*
|
|
* @param int|string $groupID (optional)
|
|
*
|
|
* @void
|
|
* @access public
|
|
*/
|
|
public function deletedReleasesByGroup($groupID = '')
|
|
{
|
|
$startTime = time();
|
|
$minSizeDeleted = $maxSizeDeleted = $minFilesDeleted = 0;
|
|
|
|
if ($this->echoCLI) {
|
|
echo $this->pdo->log->header("Process Releases -> Delete releases smaller/larger than minimum size/file count from group/site setting.");
|
|
}
|
|
|
|
if ($groupID == '') {
|
|
$groupIDs = $this->groups->getActiveIDs();
|
|
} else {
|
|
$groupIDs = [['id' => $groupID]];
|
|
}
|
|
|
|
$maxSizeSetting = $this->pdo->getSetting('maxsizetoformrelease');
|
|
$minSizeSetting = $this->pdo->getSetting('minsizetoformrelease');
|
|
$minFilesSetting = $this->pdo->getSetting('minfilestoformrelease');
|
|
|
|
foreach ($groupIDs as $groupID) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf("
|
|
SELECT r.guid, r.id
|
|
FROM releases r
|
|
INNER JOIN groups g ON g.id = r.groupid
|
|
WHERE r.groupid = %d
|
|
AND greatest(IFNULL(g.minsizetoformrelease, 0), %d) > 0
|
|
AND r.size < greatest(IFNULL(g.minsizetoformrelease, 0), %d)",
|
|
$groupID['id'],
|
|
$minSizeSetting,
|
|
$minSizeSetting
|
|
)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$minSizeDeleted++;
|
|
}
|
|
}
|
|
|
|
if ($maxSizeSetting > 0) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf('
|
|
SELECT id, guid
|
|
FROM releases
|
|
WHERE groupid = %d
|
|
AND size > %d',
|
|
$groupID['id'],
|
|
$maxSizeSetting
|
|
)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$maxSizeDeleted++;
|
|
}
|
|
}
|
|
}
|
|
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf("
|
|
SELECT r.id, r.guid
|
|
FROM releases r
|
|
INNER JOIN groups g ON g.id = r.groupid
|
|
WHERE r.groupid = %d
|
|
AND greatest(IFNULL(g.minfilestoformrelease, 0), %d) > 0
|
|
AND r.totalpart < greatest(IFNULL(g.minfilestoformrelease, 0), %d)",
|
|
$groupID['id'],
|
|
$minFilesSetting,
|
|
$minFilesSetting
|
|
)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$minFilesDeleted++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($this->echoCLI) {
|
|
$this->pdo->log->doEcho(
|
|
$this->pdo->log->primary(
|
|
'Deleted ' . ($minSizeDeleted + $maxSizeDeleted + $minFilesDeleted) . ' releases: ' . PHP_EOL .
|
|
$minSizeDeleted . ' smaller than, ' .
|
|
$maxSizeDeleted . ' bigger than, ' .
|
|
$minFilesDeleted . ' with less files than site/group settings in: ' .
|
|
$this->consoleTools->convertTime(time() - $startTime)
|
|
), true
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete releases using admin settings.
|
|
* This deletes releases, regardless of group.
|
|
*
|
|
* @void
|
|
* @access public
|
|
*/
|
|
public function deleteReleases()
|
|
{
|
|
$startTime = time();
|
|
$category = new \Category(['Settings' => $this->pdo]);
|
|
$genres = new \Genres(['Settings' => $this->pdo]);
|
|
$passwordDeleted = $duplicateDeleted = $retentionDeleted = $completionDeleted = $disabledCategoryDeleted = 0;
|
|
$disabledGenreDeleted = $miscRetentionDeleted = $miscHashedDeleted = $categoryMinSizeDeleted = 0;
|
|
|
|
// Delete old releases and finished collections.
|
|
if ($this->echoCLI) {
|
|
$this->pdo->log->doEcho($this->pdo->log->header("Process Releases -> Delete old releases and passworded releases."));
|
|
}
|
|
|
|
// Releases past retention.
|
|
if ($this->pdo->getSetting('releaseretentiondays') != 0) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf(
|
|
'SELECT id, guid FROM releases WHERE postdate < (NOW() - INTERVAL %d DAY)',
|
|
$this->pdo->getSetting('releaseretentiondays')
|
|
)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$retentionDeleted++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Passworded releases.
|
|
if ($this->pdo->getSetting('deletepasswordedrelease') == 1) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf(
|
|
'SELECT id, guid FROM releases WHERE passwordstatus = %d',
|
|
\Releases::PASSWD_RAR
|
|
)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$passwordDeleted++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Possibly passworded releases.
|
|
if ($this->pdo->getSetting('deletepossiblerelease') == 1) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf(
|
|
'SELECT id, guid FROM releases WHERE passwordstatus = %d',
|
|
\Releases::PASSWD_POTENTIAL
|
|
)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$passwordDeleted++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($this->crossPostTime != 0) {
|
|
// Crossposted releases.
|
|
do {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf(
|
|
'SELECT id, guid FROM releases WHERE adddate > (NOW() - INTERVAL %d HOUR) GROUP BY name HAVING COUNT(name) > 1',
|
|
$this->crossPostTime
|
|
)
|
|
);
|
|
$total = 0;
|
|
if ($releases && $releases->rowCount()) {
|
|
$total = $releases->rowCount();
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$duplicateDeleted++;
|
|
}
|
|
}
|
|
} while ($total > 0);
|
|
}
|
|
|
|
if ($this->completion > 0) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf('SELECT id, guid FROM releases WHERE completion < %d AND completion > 0', $this->completion)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$completionDeleted++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Disabled categories.
|
|
$disabledCategories = $category->getDisabledIDs();
|
|
if (count($disabledCategories) > 0) {
|
|
foreach ($disabledCategories as $disabledCategory) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf('SELECT id, guid FROM releases WHERE categoryid = %d', $disabledCategory['id'])
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$disabledCategoryDeleted++;
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Delete smaller than category minimum sizes.
|
|
$categories = $this->pdo->queryDirect('
|
|
SELECT c.id AS id,
|
|
CASE WHEN c.minsizetoformrelease = 0 THEN cp.minsizetoformrelease ELSE c.minsizetoformrelease END AS minsize
|
|
FROM category c
|
|
INNER JOIN category cp ON cp.id = c.parentid
|
|
WHERE c.parentid IS NOT NULL'
|
|
);
|
|
|
|
if ($categories instanceof \Traversable) {
|
|
foreach ($categories as $category) {
|
|
if ($category['minsize'] > 0) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf('
|
|
SELECT r.id, r.guid
|
|
FROM releases r
|
|
WHERE r.categoryid = %d
|
|
AND r.size < %d',
|
|
$category['id'],
|
|
$category['minsize']
|
|
)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$categoryMinSizeDeleted++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Disabled music genres.
|
|
$genrelist = $genres->getDisabledIDs();
|
|
if (count($genrelist) > 0) {
|
|
foreach ($genrelist as $genre) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf('
|
|
SELECT id, guid
|
|
FROM releases
|
|
INNER JOIN (SELECT id AS mid FROM musicinfo WHERE musicinfo.genreID = %d) mi
|
|
ON musicinfoid = mid',
|
|
$genre['id']
|
|
)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$disabledGenreDeleted++;
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Misc other.
|
|
if ($this->pdo->getSetting('miscotherretentionhours') > 0) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf('
|
|
SELECT id, guid
|
|
FROM releases
|
|
WHERE categoryid = %d
|
|
AND adddate <= NOW() - INTERVAL %d HOUR',
|
|
\Category::CAT_MISC_OTHER,
|
|
$this->pdo->getSetting('miscotherretentionhours')
|
|
)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$miscRetentionDeleted++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Misc hashed.
|
|
if ($this->pdo->getSetting('mischashedretentionhours') > 0) {
|
|
$releases = $this->pdo->queryDirect(
|
|
sprintf('
|
|
SELECT id, guid
|
|
FROM releases
|
|
WHERE categoryid = %d
|
|
AND adddate <= NOW() - INTERVAL %d HOUR',
|
|
\Category::CAT_MISC_HASHED,
|
|
$this->pdo->getSetting('mischashedretentionhours')
|
|
)
|
|
);
|
|
if ($releases instanceof \Traversable) {
|
|
foreach ($releases as $release) {
|
|
$this->deleteSingle(['g' => $release['guid'], 'i' => $release['id']], $this->nzb, $this->releaseImage);
|
|
$miscHashedDeleted++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($this->echoCLI) {
|
|
$this->pdo->log->doEcho(
|
|
$this->pdo->log->primary(
|
|
'Removed releases: ' .
|
|
number_format($retentionDeleted) .
|
|
' past retention, ' .
|
|
number_format($passwordDeleted) .
|
|
' passworded, ' .
|
|
number_format($duplicateDeleted) .
|
|
' crossposted, ' .
|
|
number_format($disabledCategoryDeleted) .
|
|
' from disabled categories, ' .
|
|
number_format($categoryMinSizeDeleted) .
|
|
' smaller than category settings, ' .
|
|
number_format($disabledGenreDeleted) .
|
|
' from disabled music genres, ' .
|
|
number_format($miscRetentionDeleted) .
|
|
' from misc->other' .
|
|
number_format($miscHashedDeleted) .
|
|
' from misc->hashed' .
|
|
($this->completion > 0
|
|
? ', ' . number_format($completionDeleted) . ' under ' . $this->completion . '% completion.'
|
|
: '.'
|
|
)
|
|
)
|
|
);
|
|
|
|
$totalDeleted = (
|
|
$retentionDeleted + $passwordDeleted + $duplicateDeleted + $disabledCategoryDeleted +
|
|
$disabledGenreDeleted + $miscRetentionDeleted + $miscHashedDeleted + $completionDeleted +
|
|
$categoryMinSizeDeleted
|
|
);
|
|
if ($totalDeleted > 0) {
|
|
$this->pdo->log->doEcho(
|
|
$this->pdo->log->primary(
|
|
"Removed " . number_format($totalDeleted) . ' releases in ' .
|
|
$this->consoleTools->convertTime(time() - $startTime)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Categorizes releases.
|
|
*
|
|
* @param string $type name or searchname | Categorize using the search name or subject.
|
|
* @param string $where Optional "where" query parameter.
|
|
*
|
|
* @return int Quantity of categorized releases.
|
|
* @access public
|
|
*/
|
|
public function categorizeRelease($type, $where = '')
|
|
{
|
|
$cat = new \Categorize(['Settings' => $this->pdo]);
|
|
$categorized = $total = 0;
|
|
$releases = $this->pdo->queryDirect(sprintf('SELECT id, %s, groupid FROM releases %s', $type, $where));
|
|
if ($releases && $releases->rowCount()) {
|
|
$total = $releases->rowCount();
|
|
foreach ($releases as $release) {
|
|
$catId = $cat->determineCategory($release['groupid'], $release[$type]);
|
|
$this->pdo->queryExec(
|
|
sprintf('UPDATE releases SET categoryid = %d, iscategorized = 1 WHERE id = %d', $catId, $release['id'])
|
|
);
|
|
$categorized++;
|
|
if ($this->echoCLI) {
|
|
$this->consoleTools->overWritePrimary(
|
|
'Categorizing: ' . $this->consoleTools->percentString($categorized, $total)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if ($this->echoCLI !== false && $categorized > 0) {
|
|
echo PHP_EOL;
|
|
}
|
|
|
|
return $categorized;
|
|
}
|
|
|
|
/**
|
|
* Categorize releases.
|
|
*
|
|
* @param int $categorize
|
|
* @param int|string $groupID (optional)
|
|
*
|
|
* @void
|
|
* @access public
|
|
*/
|
|
public function categorizeReleases($categorize, $groupID = '')
|
|
{
|
|
$startTime = time();
|
|
if ($this->echoCLI) {
|
|
echo $this->pdo->log->header("Process Releases -> Categorize releases.");
|
|
}
|
|
switch ((int)$categorize) {
|
|
case 2:
|
|
$type = 'searchname';
|
|
break;
|
|
case 1:
|
|
default:
|
|
|
|
$type = 'name';
|
|
break;
|
|
}
|
|
$this->categorizeRelease(
|
|
$type,
|
|
(!empty($groupID) ? 'WHERE iscategorized = 0 AND groupid = ' . $groupID : 'WHERE iscategorized = 0')
|
|
);
|
|
|
|
if ($this->echoCLI) {
|
|
$this->pdo->log->doEcho($this->pdo->log->primary($this->consoleTools->convertTime(time() - $startTime)), true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return all releases to other->misc category.
|
|
*
|
|
* @param string $where Optional "where" query parameter.
|
|
*
|
|
* @void
|
|
* @access public
|
|
*/
|
|
public function resetCategorize($where = '')
|
|
{
|
|
$this->pdo->queryExec(
|
|
sprintf('UPDATE releases SET categoryid = %d, iscategorized = 0 %s', \Category::CAT_MISC_OTHER, $where)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create a GUID for a release.
|
|
* @return string
|
|
*/
|
|
public function createGUID()
|
|
{
|
|
return bin2hex(openssl_random_pseudo_bytes(20));
|
|
}
|
|
|
|
/**
|
|
* Buffer of the password status string to form part of the query.
|
|
* @var null|string
|
|
*/
|
|
private $passwordSettingBuffer = null;
|
|
|
|
/**
|
|
* Return site setting for hiding/showing passworded releases.
|
|
*
|
|
* @return int
|
|
*/
|
|
public function showPasswords()
|
|
{
|
|
if (!is_null($this->passwordSettingBuffer)) {
|
|
return $this->passwordSettingBuffer;
|
|
}
|
|
$setting = $this->pdo->queryOneRow(
|
|
"SELECT value
|
|
FROM settings
|
|
WHERE setting = 'showpasswordedrelease'"
|
|
);
|
|
$passwordStatus = ('= ' . \Releases::PASSWD_NONE);
|
|
if ($setting !== false) {
|
|
switch ($setting['value']) {
|
|
case 1:
|
|
$passwordStatus = ('<= ' . \Releases::PASSWD_POTENTIAL);
|
|
break;
|
|
case 10:
|
|
$passwordStatus = ('<= ' . \Releases::PASSWD_RAR);
|
|
break;
|
|
}
|
|
}
|
|
$this->passwordSettingBuffer = $passwordStatus;
|
|
return $passwordStatus;
|
|
}
|
|
/**
|
|
* Retrieve alternate release with same or similar searchname
|
|
*
|
|
* @param string $guid
|
|
* @param string $searchname
|
|
* @param string $userid
|
|
* @return string
|
|
*/
|
|
public function getAlternate($guid, $searchname, $userid)
|
|
{
|
|
//status values
|
|
// 0/false = successfully downloaded
|
|
// 1/true = failed download
|
|
$this->pdo->queryInsert(sprintf("INSERT IGNORE INTO dnzb_failures (userid, guid) VALUES (%d, %s)",
|
|
$userid,
|
|
$this->pdo->escapeString($guid)
|
|
)
|
|
);
|
|
|
|
$alternate = $this->pdo->queryOneRow(sprintf('SELECT * FROM releases r
|
|
WHERE r.searchname %s
|
|
AND r.guid NOT IN (SELECT guid FROM failed_downloads WHERE userid = %d)',
|
|
$this->pdo->likeString($searchname),
|
|
$userid
|
|
)
|
|
);
|
|
return $alternate;
|
|
}
|
|
} |