Better better

This commit is contained in:
Quetzal
2020-07-10 21:25:25 +00:00
committed by Spine
parent 4489804b26
commit f02de68cb1
9 changed files with 496 additions and 410 deletions

View File

@@ -10,7 +10,7 @@ class Base {
protected $cache;
public function __construct() {
$this->db = new \DB_MYSQL;
$this->cache = \G::$Cache;
$this->db = \G::$DB;
}
}

315
app/Manager/Better.php Normal file
View File

@@ -0,0 +1,315 @@
<?php
namespace Gazelle\Manager;
class Better extends \Gazelle\Base
{
protected $releaseTypes;
public function __construct(array $releaseTypes) {
parent::__construct();
$this->releaseTypes = $releaseTypes;
}
public function removeAttribute(string $type, int $id) {
$table = $this->badMap[$type] ?? null;
if (!$table) {
return;
}
$this->db->prepared_query(sprintf('
DELETE FROM %s
WHERE TorrentID = ?
', $table), $id
);
$torrent = new \Gazelle\Torrent();
$groupId = $torrent->idToGroup($id);
$this->cache->delete_value('torrents_details_'.$groupId);
}
public function missing(string $type, string $filter, string $search, int $limit, int $offset, int $userId) {
$baseQuery = '';
$columns = '';
$joins = [];
$where = [];
$order = '';
$params = [];
$joinParams = [];
switch ($type) {
case 'checksum':
$columns = 't.ID AS TorrentID, t.GroupID';
$baseQuery = '
FROM torrents t
INNER JOIN torrents_group tg ON (tg.ID = t.GroupID)
INNER JOIN torrents_leech_stats tls ON (tls.TorrentID = t.ID)';
$order = 'ORDER BY tls.Snatched DESC, t.Time ASC';
$where[] = "t.HasLogDB = '1' AND t.LogChecksum = '0'";
$mode = 'torrents';
switch ($filter) {
case 'snatched':
$joins[] = 'INNER JOIN xbt_snatched as x ON x.fid = t.ID AND x.uid = ?';
$joinParams[] = $userId;
break;
case 'uploaded':
$where[] = 't.UserID = ?';
$params[] = $userId;
break;
}
break;
case 'tags':
case 'folders':
case 'files':
case 'lineage':
$columns = 'bad.TorrentID, t.GroupID';
$baseQuery = sprintf('
FROM %s AS bad
INNER JOIN torrents t ON (t.ID = bad.TorrentID)
INNER JOIN torrents_group tg ON (tg.ID = t.GroupID)', $this->badMap[$type]);
$order = 'ORDER BY bad.TimeAdded ASC';
$mode = 'torrents';
switch ($filter) {
case 'snatched':
$joins[] = 'INNER JOIN xbt_snatched x ON (x.fid = bad.TorrentID AND x.uid = ?)';
$joinParams[] = $userId;
break;
case 'uploaded':
$where[] = 't.UserID = ?';
$params[] = $userId;
break;
}
break;
case 'artwork':
$columns = 'tg.ID, tg.Name';
$baseQuery = "
FROM torrents_group tg
LEFT JOIN wiki_torrents wt ON (wt.RevisionID = tg.RevisionID)
LEFT JOIN torrent_group_has_attr tgha ON (tgha.TorrentGroupID = tg.ID
AND tgha.TorrentGroupAttrID = (
SELECT tga.ID FROM torrent_group_attr tga WHERE tga.Name = 'no-cover-art'
)
)";
$where[] = "tg.CategoryID = 1 AND coalesce(wt.Image, tg.WikiImage) = '' AND tgha.TorrentGroupID IS NULL";
$order = 'ORDER BY tg.Name';
switch ($filter) {
case 'snatched':
$joins[] = '
INNER JOIN
(
SELECT DISTINCT t.GroupID
FROM torrents t
INNER JOIN xbt_snatched x ON (x.fid = t.ID AND x.uid = ?)
) s ON (s.GroupID = tg.ID)';
$joinParams[] = $userId;
break;
case 'uploaded':
$joins[] = '
INNER JOIN
(
SELECT DISTINCT GroupID
FROM torrents
WHERE UserID = ?
) u ON (u.GroupID = tg.ID)';
$joinParams[] = $userId;
break;
}
$mode = 'groups';
break;
case 'artistimg':
$where[] = "(wa.Image IS NULL OR wa.Image = '')";
$mode = 'artists';
break;
case 'artistdesc':
$where[] = "(wa.Body IS NULL OR wa.Body = '')";
$mode = 'artists';
break;
case 'artistdiscogs':
$where[] = "(dg.artist_id IS NULL)";
$mode = 'artists';
break;
}
if ($mode === 'artists') {
$columns = 'a.ArtistID, a.Name';
$baseQuery = '
FROM artists_group a
LEFT JOIN wiki_artists wa ON (wa.RevisionID = a.RevisionID)
LEFT JOIN artist_usage au ON (au.artist_id = a.ArtistID)';
$order = 'ORDER BY coalesce(au.uses, 0) DESC, a.Name ASC';
}
if ($search !== '') {
switch ($mode) {
case 'torrents':
$where[] = '(
tg.Name LIKE ?
OR t.Description LIKE ?
OR coalesce(wt.Body, tg.WikiBody) LIKE ?
OR tg.TagList LIKE ?
)';
$searchString = "%$search%";
$params = array_merge($params, array_fill(0, 4, $searchString));
$joins[] = 'LEFT JOIN wiki_torrents wt ON (wt.RevisionID = tg.RevisionID)';
break;
case 'groups':
$where[] = '(
tg.Name LIKE ?
OR coalesce(wt.Body, tg.WikiBody) LIKE ?
OR tg.TagList LIKE ?
)';
$searchString = "%$search%";
$params = array_merge($params, array_fill(0, 3, $searchString));
break;
case 'artists':
$where[] = 'a.Name LIKE ?';
$searchString = "%$search%";
$params[] = $searchString;
break;
}
}
if (count($where) > 0) {
$where = 'WHERE '.implode(' AND ', $where);
} else {
$where = '';
}
$joins = implode("\n", $joins);
$params = array_merge($joinParams, $params);
$query = sprintf('
SELECT count(*)
%s
%s
%s', $baseQuery, $joins, $where
);
$resultCount = $this->db->scalar($query, ...$params);
$query = sprintf('
SELECT %s
%s
%s
%s
%s
LIMIT %s OFFSET %s', $columns, $baseQuery, $joins, $where, $order, $limit, $offset
);
$this->db->prepared_query($query, ...$params);
switch ($mode) {
case 'torrents':
if ($resultCount > 0) {
$torrents = $this->db->to_array('TorrentID', MYSQLI_ASSOC);
} else {
$torrents = [];
}
$groups = \Torrents::get_groups(array_column($torrents, 'GroupID'));
$results = array_map(function ($torrent) use ($groups) {
return ['ID' => $torrent['TorrentID'], 'Group' => $groups[$torrent['GroupID']]];
}, $torrents);
break;
case 'groups':
if ($resultCount > 0) {
$results = $this->db->to_array('ID', MYSQLI_ASSOC);
foreach (\Artists::get_artists(array_keys($results)) as $groupId => $data) {
$results[$groupId]['Artists'] = [];
$results[$groupId]['ExtendedArtists'] = [];
foreach ([1, 4, 6] as $importance) {
if (isset($data[$importance])) {
$results[$groupId]['Artists'] = array_merge($results[$groupId]['Artists'], $data[$importance]);
}
}
}
} else {
$results = [];
}
break;
case 'artists':
if ($resultCount > 0) {
$results = $this->db->to_array('ArtistID', MYSQLI_ASSOC);
} else {
$results = [];
}
break;
}
return [$results, $resultCount, $mode];
}
public function singleSeeded() {
$this->db->prepared_query("
SELECT t.ID, t.GroupID
FROM torrents t
INNER JOIN torrents_leech_stats tls On (t.ID = tls.TorrentID)
WHERE t.Format = 'FLAC'
AND tls.Seeders = 1
ORDER BY t.LogScore DESC, rand()
LIMIT 50
"
);
$torrents = $this->db->to_array('ID', MYSQLI_ASSOC);
$groups = \Torrents::get_groups(array_column($torrents, 'GroupID'));
return array_map(function ($torrent) use ($groups) {
return ['ID' => $torrent['ID'], 'Group' => $groups[$torrent['GroupID']]];
}, $torrents);
}
public function twigGroups(array $results) {
$releaseTypes = $this->releaseTypes;
return array_reduce($results, function ($acc, $item) use ($releaseTypes) {
$torrent = $item['ID'];
$group = $item['Group'];
$groupId = $group['ID'];
$groupYear = $group['Year'];
$groupName = $group['Name'];
$groupFlags = isset($group['Flags']) ? $group['Flags'] : ['IsSnatched' => false];
$groupTorrents = isset($group['Torrents']) ? $group['Torrents'] : [];
$releaseType = $group['ReleaseType'];
$tags = new \Tags($group['TagList']);
$extendedArtists = $group['ExtendedArtists'];
if (!empty($extendedArtists[1]) || !empty($extendedArtists[4]) || !empty($extendedArtists[5]) || !empty($extendedArtists[6])) {
unset($extendedArtists[2]);
unset($extendedArtists[3]);
$displayName = \Artists::display_artists($extendedArtists);
} else {
$displayName = '';
}
$displayName .= "<a href=\"torrents.php?id=$groupId&amp;torrentid=$torrent#torrent$torrent\">$groupName";
if ($groupYear > 0) {
$displayName .= " [$groupYear]";
}
if ($releaseType > 0) {
$displayName .= ' ['.$releaseTypes[$releaseType].']';
}
$extraInfo = \Torrents::torrent_info($groupTorrents[$torrent]);
if ($extraInfo) {
$displayName .= " - $extraInfo";
}
$displayName .= '</a>';
$acc[$torrent] = [
'group_id' => $groupId,
'snatched' => $groupTorrents[$torrent]['IsSnatched'] ?? false,
'name' => $displayName,
'tags' => $tags->format(),
'token' => \Torrents::can_use_token($groupTorrents[$torrent]),
'fl_message' => FL_confirmation_msg($groupTorrents[$torrent]['Seeders'], $groupTorrents[$torrent]['Size']),
];
return $acc;
}, []);
}
private $badMap = [
'tags' => 'torrents_bad_tags',
'folders' => 'torrents_bad_folders',
'files' => 'torrents_bad_files',
'lineage' => 'torrents_missing_lineage'
];
}

View File

@@ -1,10 +1,7 @@
<?php
$badMap = [
'tags' => 'torrents_bad_tags',
'folders' => 'torrents_bad_folders',
'files' => 'torrents_bad_files',
'lineage' => 'torrents_missing_lineage'
];
$attrTypes = ['tags', 'folders', 'files', 'lineage'];
$filters = ['all', 'snatched', 'uploaded'];
$types = ['checksum', 'tags', 'folders', 'files', 'lineage', 'artwork', 'artistimg', 'artistdesc', 'artistdiscogs'];
if (!empty($_GET['userid']) && is_number($_GET['userid'])) {
if (check_perms('users_override_paranoia')) {
@@ -16,357 +13,74 @@ if (!empty($_GET['userid']) && is_number($_GET['userid'])) {
$userId = $LoggedUser['ID'];
}
if (empty($_GET['type']) || !in_array($_GET['type'], ['checksum', 'tags', 'folders', 'files', 'lineage', 'artwork', 'artistimg', 'artistdesc', 'artistdiscogs'])) {
$_GET['type'] = 'checksum';
}
$type = $_GET['type'];
$filter = in_array($_GET['filter'] ?? '', $filters) ? $_GET['filter'] : $filters[0];
$type = in_array($_GET['type'] ?? '', $types) ? $_GET['type'] : $types[0];
$search = $_GET['search'] ?? '';
if (empty($_GET['filter']) || !in_array($_GET['filter'], ['snatched', 'uploaded'])) {
$_GET['filter'] = 'all';
}
$filter = $_GET['filter'];
$better = new \Gazelle\Manager\Better($ReleaseTypes);
if (empty($_GET['search'])) {
$_GET['search'] = '';
}
$search = $_GET['search'];
if (check_perms('admin_reports') && in_array($type, array_keys($badMap)) && !empty($_GET['remove']) && is_number($_GET['remove'])) {
$remove = $_GET['remove'];
$DB->prepared_query(sprintf('
DELETE FROM %s
WHERE TorrentID = ?', $badMap[$type]), $remove);
$DB->prepared_query('
SELECT GroupID
FROM torrents
WHERE ID = ?', $remove);
list($groupId) = $DB->next_record();
$Cache->delete_value('torrents_details_'.$groupId);
if (check_perms('admin_reports') && in_array($type, $attrTypes) && $remove = (int)($_GET['remove'] ?? 0)) {
$better->removeAttribute($type, $remove);
}
$query = '';
$joins = [];
$where = [];
$order = '';
$params = [];
$joinparams = [];
[$page, $limit, $offset] = \Gazelle\DB::pageLimit(TORRENTS_PER_PAGE);
switch ($type) {
case 'checksum':
$query = '
SELECT SQL_CALC_FOUND_ROWS t.ID AS TorrentID, t.GroupID
FROM torrents t
INNER JOIN torrents_group tg ON tg.ID = t.GroupID';
$order = 'ORDER BY t.Time ASC';
$where[] = "t.HasLogDB = '1' AND t.LogChecksum = '0'";
$mode = 'torrents';
switch ($filter) {
case 'snatched':
$joins[] = 'INNER JOIN xbt_snatched as x ON x.fid = t.ID AND x.uid = ?';
$joinparams[] = $userId;
break;
case 'uploaded':
$where[] = 't.UserID = ?';
$params[] = $userId;
break;
}
break;
case 'tags':
case 'folders':
case 'files':
case 'lineage':
$query = sprintf('
SELECT SQL_CALC_FOUND_ROWS bad.TorrentID, t.GroupID
FROM %s AS bad
INNER JOIN torrents t ON t.ID = bad.TorrentID
INNER JOIN torrents_group tg ON tg.ID = t.GroupID', $badMap[$type]);
$order = 'ORDER BY bad.TimeAdded ASC';
$mode = 'torrents';
switch ($filter) {
case 'snatched':
$joins[] = 'INNER JOIN xbt_snatched as x ON x.fid = bad.TorrentID AND x.uid = ?';
$joinparams[] = $userId;
break;
case 'uploaded':
$where[] = 't.UserID = ?';
$params[] = $userId;
break;
}
break;
case 'artwork':
$query = '
SELECT SQL_CALC_FOUND_ROWS tg.ID, tg.Name
FROM torrents_group tg';
$where[] = "tg.CategoryID = 1 AND coalesce(wt.Image, tg.WikiImage) = ''";
$order = 'ORDER BY tg.Name';
$joins[] = 'LEFT JOIN wiki_torrents wt ON wt.RevisionID = tg.RevisionID';
$mode = 'groups';
break;
case 'artistimg':
$query = '
SELECT SQL_CALC_FOUND_ROWS a.ArtistID, a.Name
FROM artists_group a';
$where[] = "(wa.Image IS NULL OR wa.Image = '')";
$order = 'ORDER BY a.Name';
$joins[] = 'LEFT JOIN wiki_artists wa ON wa.RevisionID = a.RevisionID';
$mode = 'artists';
break;
case 'artistdesc':
$query = '
SELECT SQL_CALC_FOUND_ROWS a.ArtistID, a.Name
FROM artists_group a';
$where[] = "(wa.Body IS NULL OR wa.Body = '')";
$order = 'ORDER BY a.Name';
$joins[] = 'LEFT JOIN wiki_artists wa ON wa.RevisionID = a.RevisionID';
$mode = 'artists';
break;
case 'artistdiscogs':
$query = '
SELECT SQL_CALC_FOUND_ROWS a.ArtistID, a.Name
FROM artists_group a';
$where[] = "(dg.artist_id IS NULL)";
$order = 'ORDER BY a.Name';
$joins[] = 'LEFT JOIN artist_discogs dg ON dg.artist_id = a.ArtistID';
$mode = 'artists';
break;
}
if ($search !== '') {
switch ($mode) {
case 'torrents':
$where[] = '(
tg.Name LIKE ?
OR t.Description LIKE ?
OR coalesce(wt.Body, tg.WikiBody) LIKE ?
OR tg.TagList LIKE ?
)';
$searchString = "%$search%";
$params = array_merge($params, array_fill(0, 4, $searchString));
$joins[] = 'LEFT JOIN wiki_torrents wt ON wt.RevisionID = tg.RevisionID';
break;
case 'groups':
$where[] = '(
tg.Name LIKE ?
OR coalesce(wt.Body, tg.WikiBody) LIKE ?
OR tg.TagList LIKE ?
)';
$searchString = "%$search%";
$params = array_merge($params, array_fill(0, 3, $searchString));
break;
case 'artists':
$where[] = 'a.Name LIKE ?';
$searchString = "%$search%";
$params = array_merge($params, [$searchString]);
break;
}
}
if (count($where) > 0) {
$where = 'WHERE '.implode(' AND ', $where);
} else {
$where = '';
}
$page = !empty($_GET['page']) ? intval($_GET['page']) : 1;
$page = max(1, $page);
$limit = TORRENTS_PER_PAGE;
$offset = TORRENTS_PER_PAGE * ($page - 1);
$joins = implode("\n", $joins);
$params = array_merge($joinparams, $params);
$query = sprintf('
%s
%s
%s
%s LIMIT %s OFFSET %s', $query, $joins, $where, $order, $limit, $offset);
$qId = $DB->prepared_query($query, ...$params);
$DB->prepared_query('SELECT FOUND_ROWS()');
list($resultCount) = $DB->next_record();
[$results, $resultCount, $mode] = $better->missing($type, $filter, $search, $limit, $offset, $userId);
$pages = Format::get_pages($page, $resultCount, TORRENTS_PER_PAGE);
switch ($mode) {
case 'torrents':
if ($resultCount > 0) {
$DB->set_query_id($qId);
$torrents = $DB->to_array('TorrentID', MYSQLI_ASSOC);
} else {
$torrents = [];
}
$groups = array_map(function ($t) { return $t['GroupID']; }, $torrents);
$results = Torrents::get_groups($groups);
break;
case 'groups':
if ($resultCount > 0) {
$DB->set_query_id($qId);
$groups = $DB->to_array('ID', MYSQLI_ASSOC);
foreach (Artists::get_artists(array_keys($groups)) as $groupId => $data) {
$groups[$groupId]['Artists'] = [];
$groups[$groupId]['ExtendedArtists'] = [];
foreach ([1, 4, 6] as $importance) {
if (isset($data[$importance])) {
$groups[$groupId]['Artists'] = array_merge($groups[$groupId]['Artists'], $data[$importance]);
}
}
}
} else {
$groups = [];
}
break;
case 'artists':
if ($resultCount > 0) {
$DB->set_query_id($qId);
$artists = $DB->to_array('ArtistID', MYSQLI_ASSOC);
} else {
$artists = [];
}
break;
}
View::show_header('Missing Search');
function selected($val) {
return $val ? ' selected="selected"' : '';
}
?>
<br />
<div class="thin">
<h2>Missing</h2>
<div class="linkbox">
<a class="brackets" href="better.php?method=transcode">Transcodes</a>
<a class="brackets" href="better.php?method=missing">Missing</a>
<a class="brackets" href="better.php?method=single">Single Seeded</a>
</div>
<form class="search_form" name="missing" action="" method="get">
<input type="hidden" name="method" value="missing" />
<table cellpadding="6" cellspacing="1" border="0" class="border" width="100%">
<tr>
<td class="label"><strong>Filter</strong></td>
<td>
<select name="type">
<option value="checksum"<?=selected($type == 'checksum')?>>Missing Checksums</option>
<option value="tags"<?=selected($type == 'tags')?>>Bad Tags</option>
<option value="folders"<?=selected($type == 'folders')?>>Bad Folders</option>
<option value="files"<?=selected($type == 'files')?>>Bad Files</option>
<option value="lineage"<?=selected($type == 'lineage')?>>Missing Lineage</option>
<option value="artwork"<?=selected($type == 'artwork')?>>Missing Artwork</option>
<option value="artistimg"<?=selected($type == 'artistimg')?>>Missing Artist Images</option>
<option value="artistdesc"<?=selected($type == 'artistdesc')?>>Missing Artist Descriptions</option>
<option value="artistdiscogs"<?=selected($type == 'artistdiscogs')?>>Missing Artist Discogs ID</option>
</select>
<select name="filter">
<option value="all"<?=selected($filter == 'all')?>>All</option>
<option value="snatched"<?=selected($filter == 'snatched')?>>Snatched</option>
<option value="uploaded"<?=selected($filter == 'uploaded')?>>Uploaded</option>
</select>
</td>
</tr>
<tr>
<td class="label"><strong>Search</strong></td>
<td>
<input type="search" name="search" size="60" value="<?=(!empty($_GET['search']) ? display_str($_GET['search']) : '')?>" />
</td>
</tr>
<tr><td>&nbsp;</td><td><input type="submit" value="Search" /></td></tr>
</table>
</form>
<div class="linkbox">
<?=$pages?>
</div>
<div class="box pad">
<div class="torrent">
<h3>There are <?=$resultCount?> <?=$mode?> remaining<?php
if ($mode == 'torrents' && count($torrents) > 1 && check_perms('zip_downloader')) {
$idList = implode(',', array_map(function ($t) { return $t['TorrentID']; }, $torrents));
?>
<span class="torrents_links_block">
<a class="brackets" href="torrents.php?action=collector&amp;title=better&amp;ids=<?=$idList?>" onclick="return confirm('If you do not have the content, your ratio WILL be affected; be sure to check the size of all torrents before downloading.');">Download All</a>
</span>
</h3>
</div>
<?php
}
?>
<table width"=100%" class="torrent_table">
<?php
$filters = array_reduce($filters, function ($acc, $item) use ($filter) {
$acc[$item] = $item === $filter;
return $acc;
}, []);
$types = array_reduce($types, function ($acc, $item) use ($type) {
$acc[$item] = $item === $type;
return $acc;
}, []);
switch ($mode) {
case 'torrents':
foreach ($torrents as $torrent => $info) {
$group = $results[$info['GroupID']];
$groupId = $group['ID'];
$groupYear = $group['Year'];
$groupName = $group['Name'];
$groupFlags = isset($group['Flags']) ? $group['Flags'] : ['IsSnatched' => false];
$groupTorrents = isset($group['Torrents']) ? $group['Torrents'] : [];
$releaseType = $group['ReleaseType'];
$tags = new Tags($group['TagList']);
$extendedArtists = $group['ExtendedArtists'];
if (!empty($extendedArtists[1]) || !empty($extendedArtists[4]) || !empty($extendedArtists[5]) || !empty($extendedArtists[6])) {
unset($extendedArtists[2]);
unset($extendedArtists[3]);
$displayName = Artists::display_artists($extendedArtists);
} else {
$displayName = '';
}
$displayName .= "<a href=\"torrents.php?id=$groupId&amp;torrentid=$torrent#torrent$torrent\" class=\"tooltip\" title=\"View torrent group\" dir=\"ltr\">$groupName</a>";
if ($groupYear > 0) {
$displayName .= " [$groupYear]";
}
if ($releaseType > 0) {
$displayName .= ' ['.$ReleaseTypes[$releaseType].']';
}
$extraInfo = Torrents::torrent_info($groupTorrents[$torrent]);
if ($extraInfo) {
$displayName .= " - $extraInfo";
}
?>
<tr class="torrent torrent_row<?=$groupFlags['IsSnatched'] ? ' snatched_torrent"' : ''?>">
<td>
<span class="torrent_links_block">
<a href="torrents.php?action=download&amp;id=<?=$torrent?>&amp;authkey=<?=$LoggedUser['AuthKey']?>&amp;torrent_pass=<?=$LoggedUser['torrent_pass']?>" class="brackets tooltip" title="Download">DL</a>
</span>
<?=$displayName?>
<?php if (check_perms('admin_reports')) { ?>
<a href="better.php?method=missing&amp;type=<?=$type?>&amp;remove=<?=$torrent?>&amp;filter=<?=$filter?>&amp;search=<?=$search?>" class="brackets">X</a>
<?php } ?>
<div class="tags"><?=$tags->format()?></div>
</td>
</tr>
<?php
}
case 'artists':
$results = array_column($results, 'Name', 'ArtistID');
break;
case 'groups':
foreach ($groups as $id => $group) {
if (count($group['Artists']) > 1) {
$results = array_reduce($results, function ($acc, $item) {
if (count($item['Artists']) > 1) {
$artist = 'Various Artists';
} else {
$artist = sprintf('<a href="artist.php?id=%s" target="_blank">%s</a>', $group['Artists'][0]['id'], $group['Artists'][0]['name']);
$artist = sprintf('<a href="artist.php?id=%s" target="_blank">%s</a>', $item['Artists'][0]['id'], $item['Artists'][0]['name']);
}
?>
<tr>
<td><?=$artist?> - <a href="torrents.php?id=<?=$id?>" target="_blank"><?=$group['Name']?></a></td>
</tr>
<?php
}
$acc[$item['ID']] = ['artist' => $artist, 'name' => $item['Name']];
return $acc;
}, []);
break;
case 'artists':
foreach ($artists as $id => $artist) {
?>
<tr>
<td><a href="artist.php?id=<?=$id?>"><?=$artist['Name']?></a></td>
</tr>
<?php
}
case 'torrents':
$results = $better->twigGroups($results);
break;
}
?>
</table>
</div>
</div>
<?php
echo G::$Twig->render('better/missing.twig', [
'mode' => $mode,
'results' => $results,
'result_count' => $resultCount,
'filters' => $filters,
'search' => $search,
'types' => $types,
'auth_key' => $LoggedUser['AuthKey'],
'torrent_pass' => $LoggedUser['torrent_pass'],
'torrent_ids' => $mode !== 'torrents' ? null : implode(',', array_keys($results)),
'pages' => $pages,
'perms' => [
'zip_downloader' => check_perms('zip_downloader'),
'admin_reports' => check_perms('admin_reports'),
],
]);
View::show_footer();

View File

@@ -1,80 +1,19 @@
<?php
if (($Results = $Cache->get_value('better_single_groupids')) === false) {
$DB->query("
SELECT
t.ID AS TorrentID,
t.GroupID AS GroupID
FROM xbt_files_users AS x
JOIN torrents AS t ON t.ID=x.fid
WHERE t.Format='FLAC'
GROUP BY x.fid
HAVING COUNT(x.uid) = 1
ORDER BY t.LogScore DESC, t.Time ASC
LIMIT 30");
$Results = $DB->to_pair('GroupID', 'TorrentID', false);
$Cache->cache_value('better_single_groupids', $Results, 30 * 60);
}
$Groups = Torrents::get_groups(array_keys($Results));
$better = new \Gazelle\Manager\Better($ReleaseTypes);
$results = $better->twigGroups($better->singleSeeded());
View::show_header('Single seeder FLACs');
?>
<br />
<div class="thin">
<h2>Single Seeded</h2>
<div class="linkbox">
<a class="brackets" href="better.php?method=transcode">Transcodes</a>
<a class="brackets" href="better.php?method=missing">Missing</a>
<a class="brackets" href="better.php?method=single">Single Seeded</a>
</div>
<div class="box pad">
<table width="100%" class="torrent_table">
<tr class="colhead">
<td>Torrent</td>
</tr>
<?php
foreach ($Results as $GroupID => $FlacID) {
if (!isset($Groups[$GroupID])) {
continue;
}
$Group = $Groups[$GroupID];
if (!empty($Group['ExtendedArtists'][1]) || !empty($Group['ExtendedArtists'][4]) || !empty($Group['ExtendedArtists'][5]) || !empty($Group['ExtendedArtists'][6])) {
unset($Group['ExtendedArtists'][2]);
unset($Group['ExtendedArtists'][3]);
$DisplayName = Artists::display_artists($Group['ExtendedArtists']);
} else {
$DisplayName = '';
}
echo G::$Twig->render('better/single.twig', [
'results' => $results,
'result_count' => count($results),
'auth_key' => $LoggedUser['AuthKey'],
'torrent_pass' => $LoggedUser['torrent_pass'],
'tokens' => $LoggedUser['FLTokens'] > 0,
'torrent_ids' => implode(',', array_keys($results)),
'perms' => [
'zip_downloader' => check_perms('zip_downloader'),
],
]);
$DisplayName .= "<a href=\"torrents.php?id=$GroupID&amp;torrentid=$FlacID\" class=\"tooltip\" title=\"View torrent\" dir=\"ltr\">" . $Group['GroupName'] . '</a>';
if ($Group['GroupYear'] > 0) {
$DisplayName .= ' [' . $Group['GroupYear'] . ']';
}
if ($Group['ReleaseType'] > 0) {
$DisplayName .= ' [' . $ReleaseTypes[$Group['ReleaseType']] . ']';
}
$ExtraInfo = Torrents::torrent_info($Torrents[$FlacID]);
if ($ExtraInfo) {
$DisplayName .= ' - ' . $ExtraInfo;
}
$TorrentTags = new Tags($Group['TagList']);
?>
<tr class="torrent torrent_row<?=$Torrents[$FlacID]['IsSnatched'] ? ' snatched_torrent' : ''?>">
<td>
<span class="torrent_links_block">
<a href="torrents.php?action=download&amp;id=<?=$FlacID?>&amp;authkey=<?=$LoggedUser['AuthKey']?>&amp;torrent_pass=<?=$LoggedUser['torrent_pass']?>" title="Download" class="brackets tooltip">DL</a>
</span>
<?=$DisplayName?>
<div class="tags"><?=$TorrentTags->format()?></div>
</td>
</tr>
<?php
} ?>
</table>
</div>
</div>
<?php
View::show_footer();

View File

@@ -0,0 +1,5 @@
<div class="linkbox">
<a class="brackets" href="better.php?method=transcode">Transcodes</a>
<a class="brackets" href="better.php?method=missing">Missing</a>
<a class="brackets" href="better.php?method=single">Single Seeded</a>
</div>

View File

@@ -0,0 +1,73 @@
<br />
<div class="thin">
<h2>Missing</h2>
{% include 'better/links.twig' only %}
<form class="search_form" name="missing" action="" method="get">
<input type="hidden" name="method" value="missing" />
<table cellpadding="6" cellspacing="1" border="0" class="border" width="100%">
<tr>
<td class="label"><strong>Filter</strong></td>
<td>
<select name="type">
<option value="checksum"{{ types.checksum | selected }}>Missing Checksums</option>
<option value="tags"{{ types.tags | selected }}>Bad Tags</option>
<option value="folders"{{ types.folders | selected }}>Bad Folders</option>
<option value="files"{{ types.files | selected }}>Bad Files</option>
<option value="lineage"{{ types.lineage | selected }}>Missing Lineage</option>
<option value="artwork"{{ types.artwork | selected }}>Missing Artwork</option>
<option value="artistimg"{{ types.artistimg | selected }}>Missing Artist Images</option>
<option value="artistdesc"{{ types.artistdesc | selected }}>Missing Artist Descriptions</option>
<option value="artistdiscogs"{{ types.artistdiscogs | selected }}>Missing Artist Discogs ID</option>
</select>
<select name="filter">
<option value="all"{{ filters.all | selected }}>All</option>
<option value="snatched"{{ filters.snatched | selected }}>Snatched</option>
<option value="uploaded"{{ filters.uploaded | selected }}>Uploaded</option>
</select>
</td>
</tr>
<tr>
<td class="label"><strong>Search</strong></td>
<td>
<input type="search" name="search" size="60" value="{{ search }}" />
</td>
</tr>
<tr><td>&nbsp;</td><td><input type="submit" value="Search" /></td></tr>
</table>
</form>
<div class="linkbox">
{{ pages | raw }}
</div>
<div class="box pad">
<div class="torrent">
<h3>There are {{ result_count }} {{ mode }} remaining
{% if mode == 'torrents' and result_count > 1 and perms.zip_downloader %}
{% include 'better/zip.twig' with {torrent_ids: torrent_ids} only %}
{% endif %}
</h3>
</div>
{% if mode is same as('torrents') %}
{% include 'better/torrents.twig' with {results: results, auth_key: auth_key, torrent_pass: torrent_pass, tokens: tokens} only %}
{% elseif mode is same as('groups') %}
<table width"=100%" class="torrent_table">
{% for id, group in results %}
<tr>
<td>{{ group.artist | raw }} - <a href="torrents.php?id={{ id }}" target="_blank">{{ group.name }}</a></td>
</tr>
{% endfor %}
</table>
{% else %}
<table width"=100%" class="torrent_table">
{% for id, name in results %}
<tr>
<td><a href="artist.php?id={{ id }}">{{ name }}</a></td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
<div class="linkbox">
{{ pages | raw }}
</div>
</div>

View File

@@ -0,0 +1,16 @@
<br />
<div class="thin">
<h2>Single Seeded</h2>
{% include 'better/links.twig' only %}
<div class="box pad">
<div class="torrent">
<h3>Here are {{ result_count }} random torrents
{% if result_count > 0 and perms.zip_downloader %}
{% include 'better/zip.twig' with {torrent_ids: torrent_ids} only %}
{% endif %}
</h3>
</div>
{% include 'better/torrents.twig' with {results: results, auth_key: auth_key, torrent_pass: torrent_pass, tokens: tokens} only %}
</div>
</div>

View File

@@ -0,0 +1,20 @@
<table width"=100%" class="torrent_table">
{% for id, row in results %}
<tr class="torrent torrent_row{{ row.snatched ? ' snatched_torrent' : '' }}">
<td>
<span class="torrent_links_block">
<a href="torrents.php?action=download&amp;id={{ id }}&amp;authkey={{ auth_key }}&amp;torrent_pass={{ torrent_pass }}" class="brackets tooltip" title="Download">DL</a>
{% if row.token %}
| <a href="torrents.php?action=download&amp;id={{ id }}&amp;authkey={{ auth_key }}&amp;torrent_pass={{ torrent_pass }}&amp;usetoken=1" class="brackets tooltip" title="Use a FL Token" onclick="return confirm('{{ row.fl_message }}');">FL</a>
{% endif %}
</span>
{{ row.name | raw }}
{% if perms.admin_reports %}
<a href="better.php?method=missing&amp;type={{ type }}&amp;remove={{ id }}&amp;filter={{ filter }}&amp;search={{ search }}" class="brackets">X</a>
{% endif %}
<div class="tags">{{ row.tags | raw }}</div>
</td>
</tr>
{% endfor %}
</table>

View File

@@ -0,0 +1,4 @@
<span class="torrents_links_block">
<a class="brackets" href="torrents.php?action=collector&amp;title=better&amp;ids={{ torrent_ids }}" onclick="return confirm('If you do not have the content, your ratio WILL be affected; be sure to check the size of all torrents before downloading.');">Download All</a>
</span>