BioTorrents.de’s version of Gazelle
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

browse.php 33KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. <?php
  2. # todo: Go through line by line
  3. include(SERVER_ROOT.'/sections/torrents/functions.php');
  4. // The "order by x" links on columns headers
  5. function header_link($SortKey, $DefaultWay = 'desc')
  6. {
  7. global $OrderBy, $OrderWay;
  8. if ($SortKey == $OrderBy) {
  9. if ($OrderWay == 'desc') {
  10. $NewWay = 'asc';
  11. } else {
  12. $NewWay = 'desc';
  13. }
  14. } else {
  15. $NewWay = $DefaultWay;
  16. }
  17. return "torrents.php?order_way=$NewWay&amp;order_by=$SortKey&amp;".Format::get_url(['order_way', 'order_by']);
  18. }
  19. if (!empty($_GET['searchstr']) || !empty($_GET['groupname'])) {
  20. if (!empty($_GET['searchstr'])) {
  21. $InfoHash = $_GET['searchstr'];
  22. } else {
  23. $InfoHash = $_GET['groupname'];
  24. }
  25. // Search by infohash
  26. if ($InfoHash = is_valid_torrenthash($InfoHash)) {
  27. $InfoHash = db_string(pack('H*', $InfoHash));
  28. $DB->query("
  29. SELECT ID, GroupID
  30. FROM torrents
  31. WHERE info_hash = '$InfoHash'");
  32. if ($DB->has_results()) {
  33. list($ID, $GroupID) = $DB->next_record();
  34. header("Location: torrents.php?id=$GroupID&torrentid=$ID");
  35. die();
  36. }
  37. }
  38. }
  39. // Setting default search options
  40. if (!empty($_GET['setdefault'])) {
  41. $UnsetList = ['page', 'setdefault'];
  42. $UnsetRegexp = '/(&|^)('.implode('|', $UnsetList).')=.*?(&|$)/i';
  43. $DB->query("
  44. SELECT SiteOptions
  45. FROM users_info
  46. WHERE UserID = ?", $LoggedUser['ID']);
  47. list($SiteOptions) = $DB->next_record(MYSQLI_NUM, false);
  48. $SiteOptions = json_decode($SiteOptions, true) ?? [];
  49. $SiteOptions['DefaultSearch'] = preg_replace($UnsetRegexp, '', $_SERVER['QUERY_STRING']);
  50. $DB->query("
  51. UPDATE users_info
  52. SET SiteOptions = ?
  53. WHERE UserID = ?", json_encode($SiteOptions), $LoggedUser['ID']);
  54. $Cache->begin_transaction("user_info_heavy_$UserID");
  55. $Cache->update_row(false, ['DefaultSearch' => $SiteOptions['DefaultSearch']]);
  56. $Cache->commit_transaction(0);
  57. // Clearing default search options
  58. } elseif (!empty($_GET['cleardefault'])) {
  59. $DB->query("
  60. SELECT SiteOptions
  61. FROM users_info
  62. WHERE UserID = ?", $LoggedUser['ID']);
  63. list($SiteOptions) = $DB->next_record(MYSQLI_NUM, false);
  64. $SiteOptions = json_decode($SiteOptions, true) ?? [];
  65. $SiteOptions['DefaultSearch'] = '';
  66. $DB->query("
  67. UPDATE users_info
  68. SET SiteOptions = ?
  69. WHERE UserID = ?", json_encode($SiteOptions), $LoggedUser['ID']);
  70. $Cache->begin_transaction("user_info_heavy_$UserID");
  71. $Cache->update_row(false, ['DefaultSearch' => '']);
  72. $Cache->commit_transaction(0);
  73. // Use default search options
  74. } elseif (empty($_SERVER['QUERY_STRING']) || (count($_GET) === 1 && isset($_GET['page']))) {
  75. if (!empty($LoggedUser['DefaultSearch'])) {
  76. if (!empty($_GET['page'])) {
  77. $Page = $_GET['page'];
  78. parse_str($LoggedUser['DefaultSearch'], $_GET);
  79. $_GET['page'] = $Page;
  80. } else {
  81. parse_str($LoggedUser['DefaultSearch'], $_GET);
  82. }
  83. }
  84. }
  85. // Terms were not submitted via the search form
  86. if (isset($_GET['searchsubmit'])) {
  87. $GroupResults = !empty($_GET['group_results']);
  88. } else {
  89. $GroupResults = !$LoggedUser['DisableGrouping2'];
  90. }
  91. if (!empty($_GET['order_way']) && $_GET['order_way'] == 'asc') {
  92. $OrderWay = 'asc';
  93. } else {
  94. $OrderWay = 'desc';
  95. }
  96. if (empty($_GET['order_by']) || !isset(TorrentSearch::$SortOrders[$_GET['order_by']])) {
  97. $OrderBy = 'time'; // For header links
  98. } else {
  99. $OrderBy = $_GET['order_by'];
  100. }
  101. $Page = !empty($_GET['page']) ? (int) $_GET['page'] : 1;
  102. $Search = new TorrentSearch($GroupResults, $OrderBy, $OrderWay, $Page, TORRENTS_PER_PAGE);
  103. if (isset($LoggedUser['HideLolicon']) && $LoggedUser['HideLolicon'] == 1) {
  104. $Search->insert_hidden_tags('!lolicon !shotacon !toddlercon');
  105. }
  106. if (isset($LoggedUser['HideScat']) && $LoggedUser['HideScat'] == 1) {
  107. $Search->insert_hidden_tags('!scat');
  108. }
  109. if (isset($LoggedUser['HideSnuff']) && $LoggedUser['HideSnuff'] == 1) {
  110. $Search->insert_hidden_tags('!snuff');
  111. }
  112. $Results = $Search->query($_GET);
  113. $Groups = $Search->get_groups();
  114. $NumResults = $Search->record_count();
  115. $HideFilter = isset($LoggedUser['ShowTorFilter']) && $LoggedUser['ShowTorFilter'] == 0;
  116. // This is kinda ugly, but the enormous if paragraph was really hard to read
  117. $AdvancedSearch = !empty($_GET['action']) && $_GET['action'] == 'advanced';
  118. $AdvancedSearch |= !empty($LoggedUser['SearchType']) && (empty($_GET['action']) || $_GET['action'] == 'advanced');
  119. $AdvancedSearch &= check_perms('site_advanced_search');
  120. if ($AdvancedSearch) {
  121. $Action = 'action=advanced';
  122. $HideBasic = ' hidden';
  123. $HideAdvanced = '';
  124. } else {
  125. $Action = 'action=basic';
  126. $HideBasic = '';
  127. $HideAdvanced = ' hidden';
  128. }
  129. View::show_header('Browse Torrents', 'browse');
  130. ?>
  131. <div class="thin widethin">
  132. <div class="header">
  133. <h2>Torrents</h2>
  134. </div>
  135. <form class="search_form" name="torrents" method="get" onsubmit="$(this).disableUnset();">
  136. <div class="box filter_torrents">
  137. <div class="head">
  138. <strong>
  139. <span id="ft_basic" class="<?=$HideBasic?>">Basic Search (<a class="clickable" onclick="toggleTorrentSearch('advanced')">Advanced</a>)</span>
  140. <span id="ft_advanced" class="<?=$HideAdvanced?>">Advanced Search (<a class="clickable" onclick="toggleTorrentSearch('basic')">Basic</a>)</span>
  141. </strong>
  142. <span class="float_right">
  143. <a onclick="return toggleTorrentSearch(0);" id="ft_toggle" class="brackets"><?=$HideFilter ? 'Show' : 'Hide'?></a>
  144. </span>
  145. </div>
  146. <div id="ft_container" class="pad<?=$HideFilter ? ' hidden' : ''?>">
  147. <?php if ((isset($LoggedUser['HideLolicon']) && $LoggedUser['HideLolicon'] == 1)
  148. || (isset($LoggedUser['HideScat']) && $LoggedUser['HideScat'] == 1)
  149. || (isset($LoggedUser['HideSnuff']) && $LoggedUser['HideSnuff'] == 1)
  150. ) { ?>
  151. <svg title="Your profile settings exclude some results" class="search_warning tooltip" width="10" height="15"><rect x=3 width="4" height="10" rx="2" ry="2"/><circle cx="5" cy="13" r="2"/></svg>
  152. <?php } ?>
  153. <table class="layout">
  154. <tr id="catalogue_number" class="ftr_advanced<?=$HideAdvanced?>">
  155. <td class="label"><!--Catalogue number:--></td>
  156. <td class="ft_cataloguenumber">
  157. <input type="search" size="19" name="cataloguenumber" class="inputtext smallest fti_advanced" placeholder="Accession Number" value="<?Format::form('cataloguenumber')?>" />
  158. </td>
  159. </tr>
  160. <tr id="album_torrent_name" class="ftr_advanced<?=$HideAdvanced?>">
  161. <td class="label"><!--Torrent name:--></td>
  162. <td class="ft_groupname">
  163. <input type="search" spellcheck="false" size="65" name="advgroupname" class="inputtext smaller fti_advanced" placeholder="Torrent Title" value="<?Format::form('advgroupname')?>" />
  164. </td>
  165. </tr>
  166. <tr id="artist_name" class="ftr_advanced<?=$HideAdvanced?>">
  167. <td class="label"><!--Artist name:--></td>
  168. <td class="ft_artistname">
  169. <input type="search" spellcheck="false" size="65" name="artistname" class="inputtext smaller fti_advanced" placeholder="Author Name" value="<?Format::form('artistname')?>" />
  170. </td>
  171. </tr>
  172. <tr id="year" class="ftr_advanced<?=$HideAdvanced?>">
  173. <td class="label"><!--Year:--></td>
  174. <td class="ft_year">
  175. <input type="search" name="year" class="inputtext smallest fti_advanced" placeholder="Year" value="<?Format::form('year')?>" size="12" />
  176. </td>
  177. </tr>
  178. <tr id="torrent_description" class="ftr_advanced<?=$HideAdvanced?>">
  179. <td class="label"><!--<span title="Search torrent descriptions (not group information)" class="tooltip">Torrent description:</span>--></td>
  180. <td class="ft_description">
  181. <input type="search" spellcheck="false" size="65" name="description" class="inputtext fti_advanced" placeholder="Torrent Description" value="<?php Format::form('description') ?>" /><br /><br />
  182. Search torrent descriptions (not group information)
  183. </td>
  184. </tr>
  185. <tr id="file_list" class="ftr_advanced<?=$HideAdvanced?>">
  186. <td class="label"><!--File list:--></td>
  187. <td class="ft_filelist">
  188. <input type="search" spellcheck="false" size="65" name="filelist" class="inputtext fti_advanced" placeholder="File List" value="<?Format::form('filelist')?>" />
  189. </td>
  190. </tr>
  191. <tr id="rip_specifics" class="ftr_advanced<?=$HideAdvanced?>">
  192. <td class="label">Specifics</td>
  193. <td class="nobr ft_ripspecifics">
  194. <select name="media" class="ft_media fti_advanced">
  195. <option value="">Seq Platform</option>
  196. <?php foreach ($Media as $MediaName) { ?>
  197. <option value="<?=display_str($MediaName); ?>"<?Format::selected('media', $MediaName)?>><?=display_str($MediaName); ?></option>
  198. <?php } ?>
  199. </select>
  200. <select id="container" name="container" class="ft_container fti_advanced">
  201. <option value="">Seq Format</option>
  202. <?php foreach ($Containers as $Key => $Container) { ?>
  203. <option value="<?=display_str($Key);?>" <?Format::selected('container', $Key)?>><?=display_str($Key);?></option>
  204. <?php } foreach ($ContainersProt as $Key => $ContainerProt) { ?>
  205. <option value="<?=display_str($Key);?>" <?Format::selected('container', $Key)?>><?=display_str($Key);?></option>
  206. <?php } ?>
  207. </select>
  208. <select name="media" class="ft_media fti_advanced">
  209. <option value="">Img Platform</option>
  210. <? foreach ($MediaManga as $MediaName) { ?>
  211. <option value="<?=display_str($MediaName); ?>"<?Format::selected('media', $MediaName)?>><?=display_str($MediaName); ?></option>
  212. <? } ?>
  213. </select>
  214. <select id="container" name="container" class="ft_container fti_advanced">
  215. <option value="">Img Format</option>
  216. <?php foreach ($ContainersGames as $Key => $Container) { ?>
  217. <option value="<?=display_str($Key);?>" <?Format::selected('container', $Key)?>><?=display_str($Key);?></option>
  218. <?php } ?>
  219. </select>
  220. <select name="codec" class="ft_codec fti_advanced">
  221. <option value="">License</option>
  222. <?php foreach ($Codecs as $Codec) { ?>
  223. <option value="<?=display_str($Codec); ?>"<?Format::selected('codec', $Codec)?>><?=display_str($Codec); ?></option>
  224. <?php } ?>
  225. </select>
  226. </td>
  227. </tr>
  228. <tr id="size" class="ftr_advanced<?=$HideAdvanced?>">
  229. <td class="label">Size</td>
  230. <td class="ft_size">
  231. <input type="size_min" spellcheck="false" size="6" name="size_min" class="inputtext smaller fti_advanced" placeholder="Min" value="<?Format::form('size_min')?>" /> &ndash;
  232. <input type="size_max" spellcheck="false" size="6" name="size_max" class="inputtext smaller fti_advanced" placeholder="Max" value="<?Format::form('size_max')?>" />
  233. <select name="size_unit" class="ft_size fti_advanced">
  234. <option value="">Unit</option>
  235. <option value="0"<?Format::selected('size_unit', 0)?>>B</option>
  236. <option value="1"<?Format::selected('size_unit', 1)?>>KiB</option>
  237. <option value="2"<?Format::selected('size_unit', 2)?>>MiB</option>
  238. <option value="3"<?Format::selected('size_unit', 3)?>>GiB</option>
  239. <option value="4"<?Format::selected('size_unit', 4)?>>TiB</option>
  240. </select>
  241. </td>
  242. </tr>
  243. <tr id="misc" class="ftr_advanced<?=$HideAdvanced?>">
  244. <td class="label">Misc</td>
  245. <td class="nobr ft_misc">
  246. <select name="resolution" class="ft_resolution fti_advanced">
  247. <option value="">Assembly Level</option>
  248. <?php foreach ($Resolutions as $Resolution) { ?>
  249. <option value="<?=display_str($Resolution); ?>"<?Format::selected('resolution', $Resolution)?>><?=display_str($Resolution); ?></option>
  250. <?php } ?>
  251. </select>
  252. <select name="censored" class="ft_censored fti_advanced">
  253. <option value="">Alignment</option>
  254. <option value="1"<?Format::selected('censored', 1)?>>Aligned</option>
  255. <option value="0"<?Format::selected('censored', 0)?>>Unaligned</option>
  256. </select>
  257. <select name="freetorrent" class="ft_freetorrent fti_advanced">
  258. <option value="">Leech Status</option>
  259. <option value="1"<?Format::selected('freetorrent', 1)?>>Freeleech</option>
  260. <option value="2"<?Format::selected('freetorrent', 2)?>>Neutral Leech</option>
  261. <option value="3"<?Format::selected('freetorrent', 3)?>>Either</option>
  262. <option value="0"<?Format::selected('freetorrent', 0)?>>Normal</option>
  263. </select>
  264. </td>
  265. </tr>
  266. <tr id="search_terms" class="ftr_basic<?=$HideBasic?>">
  267. <td class="label"><!--Search terms:--></td>
  268. <td class="ftb_searchstr">
  269. <input type="search" spellcheck="false" size="48" name="searchstr" class="inputtext fti_basic" placeholder="Search Terms" value="<?Format::form('searchstr')?>" aria-label="Terms to search">
  270. </td>
  271. </tr>
  272. <tr id="tagfilter">
  273. <td class="label"><!--<span title="Use !tag to exclude tag" class="tooltip">Tags (comma-separated):</span>--></td>
  274. <td class="ft_taglist">
  275. <input type="search" size="37" id="tags" name="taglist" class="inputtext smaller" placeholder="Tags (comma-separated)" value="<?=display_str($Search->get_terms('taglist'))?>"<?php Users::has_autocomplete_enabled('other'); ?> aria-label="Tags to search">&nbsp;
  276. <input type="radio" name="tags_type" id="tags_type0" value="0"<?Format::selected('tags_type', 0, 'checked')?> /><label for="tags_type0"> Any</label>&nbsp;&nbsp;
  277. <input type="radio" name="tags_type" id="tags_type1" value="1"<?Format::selected('tags_type', 1, 'checked')?> /><label for="tags_type1"> All</label><br /><br />
  278. Use !tag to exclude tags
  279. </td>
  280. </tr>
  281. <tr id="order">
  282. <td class="label">Order By</td>
  283. <td class="ft_order">
  284. <select name="order_by" style="width: auto;" class="ft_order_by" aria-label="Property to order by">
  285. <option value="time"<?Format::selected('order_by', 'time')?>>Time Added</option>
  286. <option value="year"<?Format::selected('order_by', 'year')?>>Year</option>
  287. <option value="size"<?Format::selected('order_by', 'size')?>>Size</option>
  288. <option value="snatched"<?Format::selected('order_by', 'snatched')?>>Snatched</option>
  289. <option value="seeders"<?Format::selected('order_by', 'seeders')?>>Seeders</option>
  290. <option value="leechers"<?Format::selected('order_by', 'leechers')?>>Leechers</option>
  291. <option value="cataloguenumber"<?Format::selected('order_by', 'cataloguenumber')?>>Accession Number</option>
  292. <option value="random"<?Format::selected('order_by', 'random')?>>Random</option>
  293. </select>
  294. <select name="order_way" class="ft_order_way" aria-label="Direction to order">
  295. <option value="desc"<?Format::selected('order_way', 'desc')?>>Descending</option>
  296. <option value="asc"<?Format::selected('order_way', 'asc')?>>Ascending</option>
  297. </select>
  298. </td>
  299. </tr>
  300. <tr id="search_group_results">
  301. <td class="label">
  302. <label for="group_results">Group Torrents</label>
  303. </td>
  304. <td class="ft_group_results">
  305. <input type="checkbox" value="1" name="group_results" id="group_results"<?=$GroupResults ? ' checked="checked"' : ''?> />
  306. </td>
  307. </tr>
  308. </table>
  309. <table class="layout cat_list ft_cat_list">
  310. <?php
  311. $x = 0;
  312. reset($Categories);
  313. foreach ($Categories as $CatKey => $CatName) {
  314. if ($x % 7 == 0) {
  315. if ($x > 0) {
  316. ?>
  317. </tr>
  318. <?php
  319. } ?>
  320. <tr>
  321. <?php
  322. }
  323. $x++; ?>
  324. <td>
  325. <input type="checkbox" name="filter_cat[<?=($CatKey + 1)?>]" id="cat_<?=($CatKey + 1)?>" value="1"<?php if (isset($_GET['filter_cat'][$CatKey + 1])) { ?> checked="checked"<?php } ?> />
  326. <label for="cat_<?=($CatKey + 1)?>"><?=$CatName?></label>
  327. </td>
  328. <?php
  329. }
  330. ?>
  331. </tr>
  332. </table>
  333. <table class="layout cat_list<?php if (empty($LoggedUser['ShowTags'])) { ?> hidden<?php } ?>" id="taglist">
  334. <tr>
  335. <?php
  336. $GenreTags = $Cache->get_value('genre_tags');
  337. if (!$GenreTags) {
  338. $DB->query('
  339. SELECT Name
  340. FROM tags
  341. WHERE TagType = \'genre\'
  342. ORDER BY Name');
  343. $GenreTags = $DB->collect('Name');
  344. $Cache->cache_value('genre_tags', $GenreTags, 3600 * 6);
  345. }
  346. $x = 0;
  347. foreach ($GenreTags as $Tag) {
  348. ?>
  349. <td><a href="#" onclick="add_tag('<?=$Tag?>'); return false;"><?=$Tag?></a></td>
  350. <?php
  351. $x++;
  352. if ($x % 7 == 0) {
  353. ?>
  354. </tr>
  355. <tr>
  356. <?php
  357. }
  358. }
  359. if ($x % 7 != 0) { // Padding
  360. ?>
  361. <td colspan="<?=(7 - ($x % 7))?>"> </td>
  362. <?php } ?>
  363. </tr>
  364. </table>
  365. <table class="layout cat_list">
  366. <tr>
  367. <td class="label">
  368. <a class="brackets" data-toggle-target="#taglist" data-toggle-replace="<?=(empty($LoggedUser['ShowTags']) ? 'Hide tags' : 'View tags')?>"><?=(empty($LoggedUser['ShowTags']) ? 'View tags' : 'Hide tags')?></a>
  369. </td>
  370. </tr>
  371. </table>
  372. <div class="submit ft_submit">
  373. <span class="float_left"><?=number_format($NumResults)?> Results</span>
  374. <input type="submit" value="Search" />
  375. <input type="hidden" name="action" id="ft_type" value="<?=($AdvancedSearch ? 'advanced' : 'basic')?>" />
  376. <input type="hidden" name="searchsubmit" value="1" />
  377. <input type="button" value="Reset" onclick="location.href = 'torrents.php<?php if (isset($_GET['action']) && $_GET['action'] === 'advanced') { ?>?action=advanced<?php } ?>'" />
  378. &nbsp;&nbsp;
  379. <?php if ($Search->has_filters()) { ?>
  380. <input type="submit" name="setdefault" value="Make Default" />
  381. <?php }
  382. if (!empty($LoggedUser['DefaultSearch'])) { ?>
  383. <input type="submit" name="cleardefault" value="Clear Default" />
  384. <?php } ?>
  385. </div>
  386. </div>
  387. </div>
  388. </form>
  389. <?php if ($NumResults == 0) { ?>
  390. <div class="torrents_nomatch box pad" align="center">
  391. <h2>Your search did not match anything.</h2>
  392. <p>Make sure all names are spelled correctly, or try making your search less specific.</p>
  393. </div>
  394. </div>
  395. <?php View::show_footer();die();
  396. }
  397. if ($NumResults < ($Page - 1) * TORRENTS_PER_PAGE + 1) {
  398. $LastPage = ceil($NumResults / TORRENTS_PER_PAGE);
  399. $Pages = Format::get_pages(0, $NumResults, TORRENTS_PER_PAGE); ?>
  400. <div class="torrents_nomatch box pad" align="center">
  401. <h2>The requested page contains no matches.</h2>
  402. <p>You are requesting page <?=$Page?>, but the search returned only <?=number_format($LastPage) ?> pages.</p>
  403. </div>
  404. <div class="linkbox">Go to page <?=$Pages?></div>
  405. </div>
  406. <?php
  407. View::show_footer();
  408. die();
  409. }
  410. // List of pages
  411. $Pages = Format::get_pages($Page, $NumResults, TORRENTS_PER_PAGE);
  412. $Bookmarks = Bookmarks::all_bookmarks('torrent');
  413. ?>
  414. <div class="linkbox"><?=$Pages?></div>
  415. <table class="box torrent_table cats <?=$GroupResults ? 'grouping' : 'no_grouping'?>" id="torrent_table">
  416. <tr class="colhead">
  417. <?php if ($GroupResults) { ?>
  418. <td class="small"></td>
  419. <?php } ?>
  420. <td class="small cats_col"></td>
  421. <td>Name / <a href="<?=header_link('year')?>">Year</a></td>
  422. <td>Files</td>
  423. <td><a href="<?=header_link('time')?>">Time</a></td>
  424. <td><a href="<?=header_link('size')?>">Size</a></td>
  425. <td class="sign snatches">
  426. <a href="<?=header_link('snatched')?>" aria-label="Sort by snatches">
  427. <svg width="15" height="15" fill="black" class="tooltip" alt="Snatches" title="Snatches" viewBox="3 0 88 98"><path d="M20 20 A43 43,0,1,0,77 23 L90 10 L55 10 L55 45 L68 32 A30.27 30.27,0,1,1,28 29"></path></svg>
  428. </a>
  429. </td>
  430. <td class="sign seeders">
  431. <a href="<?=header_link('seeders')?>" aria-label="Sort by seeders">
  432. <svg width="11" height="15" fill="black" class="tooltip" alt="Seeders" title="Seeders"><polygon points="0,7 5.5,0 11,7 8,7 8,15 3,15 3,7"></polygon></svg>
  433. </a>
  434. </td>
  435. <td class="sign leechers">
  436. <a href="<?=header_link('leechers')?>" aria-label="Sort by leechers">
  437. <svg width="11" height="15" fill="black" class="tooltip" alt="Leechers" title="Leechers"><polygon points="0,8 5.5,15 11,8 8,8 8,0 3,0 3,8"></polygon></svg>
  438. </a>
  439. </td>
  440. </tr>
  441. <?php
  442. // Start printing torrent list
  443. foreach ($Results as $Key => $GroupID) {
  444. $GroupInfo = $Groups[$GroupID];
  445. if (empty($GroupInfo['Torrents'])) {
  446. continue;
  447. }
  448. $CategoryID = $GroupInfo['CategoryID'];
  449. $GroupYear = $GroupInfo['Year'];
  450. $Artists = $GroupInfo['Artists'];
  451. $GroupCatalogueNumber = $GroupInfo['CatalogueNumber'];
  452. $GroupPages = $GroupInfo['Pages'];
  453. $GroupStudio = $GroupInfo['Studio'];
  454. $GroupDLsiteID = $GroupInfo['DLSiteID'];
  455. $GroupName = empty($GroupInfo['Name']) ? (empty($GroupInfo['NameRJ']) ? $GroupInfo['NameJP'] : $GroupInfo['NameRJ']) : $GroupInfo['Name'];
  456. if ($GroupResults) {
  457. $Torrents = $GroupInfo['Torrents'];
  458. $GroupTime = $MaxSize = $TotalLeechers = $TotalSeeders = $TotalSnatched = 0;
  459. foreach ($Torrents as $T) {
  460. $GroupTime = max($GroupTime, strtotime($T['Time']));
  461. $MaxSize = max($MaxSize, $T['Size']);
  462. $TotalLeechers += $T['Leechers'];
  463. $TotalSeeders += $T['Seeders'];
  464. $TotalSnatched += $T['Snatched'];
  465. }
  466. } else {
  467. $TorrentID = $Key;
  468. $Torrents = [$TorrentID => $GroupInfo['Torrents'][$TorrentID]];
  469. }
  470. $TorrentTags = new Tags($GroupInfo['TagList']);
  471. if (isset($Artists)) {
  472. $DisplayName = '<div class="torrent_artists">'.Artists::display_artists($Artists).'</div> ';
  473. } else {
  474. $DisplayName = '';
  475. }
  476. $SnatchedGroupClass = $GroupInfo['Flags']['IsSnatched'] ? ' snatched_group' : '';
  477. if ($GroupResults && (count($Torrents) > 1 && isset($GroupedCategories[$CategoryID - 1]))) {
  478. // These torrents are in a group
  479. $CoverArt = $GroupInfo['WikiImage'];
  480. $DisplayName .= "<a class=\"torrent_title\" href=\"torrents.php?id=$GroupID\" ";
  481. if (!isset($LoggedUser['CoverArt']) || $LoggedUser['CoverArt']) {
  482. $DisplayName .= 'data-cover="'.ImageTools::process($CoverArt, 'thumb').'" ';
  483. }
  484. $DisplayName .= "dir=\"ltr\">$GroupName</a>";
  485. if ($GroupYear) {
  486. $DisplayName .= " [$GroupYear]";
  487. }
  488. if ($GroupStudio) {
  489. $DisplayName .= " [$GroupStudio]";
  490. }
  491. if ($GroupCatalogueNumber) {
  492. $DisplayName .= " [$GroupCatalogueNumber]";
  493. }
  494. if ($GroupPages) {
  495. $DisplayName .= " [{$GroupPages}p]";
  496. }
  497. if ($GroupDLsiteID) {
  498. $DisplayName .= " [$GroupDLsiteID]";
  499. } ?>
  500. <tr class="group<?=$SnatchedGroupClass?>">
  501. <?php
  502. $ShowGroups = !(!empty($LoggedUser['TorrentGrouping']) && $LoggedUser['TorrentGrouping'] == 1); ?>
  503. <td class="center">
  504. <div id="showimg_<?=$GroupID?>" class="<?=($ShowGroups ? 'hide' : 'show')?>_torrents">
  505. <a class="tooltip show_torrents_link" onclick="toggle_group(<?=$GroupID?>, this, event)" title="Toggle this group (Hold &quot;Shift&quot; to toggle all groups)"></a>
  506. </div>
  507. </td>
  508. <td class="center cats_col">
  509. <div title="<?=Format::pretty_category($CategoryID)?>" class="tooltip <?=Format::css_category($CategoryID)?>">
  510. </div>
  511. </td>
  512. <td colspan="2" class="big_info">
  513. <div class="group_info clear">
  514. <?=$DisplayName?>
  515. <?php if (in_array($GroupID, $Bookmarks)) { ?>
  516. <span class="remove_bookmark float_right">
  517. <a href="#" id="bookmarklink_torrent_<?=$GroupID?>" class="brackets" onclick="Unbookmark('torrent', <?=$GroupID?>, 'Bookmark'); return false;">Remove bookmark</a>
  518. </span>
  519. <?php } else { ?>
  520. <span class="add_bookmark float_right">
  521. <a href="#" id="bookmarklink_torrent_<?=$GroupID?>" class="brackets" onclick="Bookmark('torrent', <?=$GroupID?>, 'Remove bookmark'); return false;">Bookmark</a>
  522. </span>
  523. <?php } ?>
  524. <br />
  525. <div class="tags"><?=$TorrentTags->format('torrents.php?'.$Action.'&amp;taglist=')?></div>
  526. </div>
  527. </td>
  528. <td class="nobr"><?=time_diff($GroupTime, 1)?></td>
  529. <td class="number_column nobr"><?=Format::get_size($MaxSize)?> (Max)</td>
  530. <td class="number_column"><?=number_format($TotalSnatched)?></td>
  531. <td class="number_column<?=($TotalSeeders == 0 ? ' r00' : '')?>"><?=number_format($TotalSeeders)?></td>
  532. <td class="number_column"><?=number_format($TotalLeechers)?></td>
  533. </tr>
  534. <?php
  535. foreach ($Torrents as $TorrentID => $Data) {
  536. $Data['CategoryID'] = $CategoryID;
  537. // All of the individual torrents in the group
  538. // Get report info for each torrent, use the cache if available, if not, add to it.
  539. $Reported = false;
  540. $Reports = Torrents::get_reports($TorrentID);
  541. if (count($Reports) > 0) {
  542. $Reported = true;
  543. }
  544. $SnatchedTorrentClass = $Data['IsSnatched'] ? ' snatched_torrent' : '';
  545. $TorrentDL = "torrents.php?action=download&amp;id=".$TorrentID."&amp;authkey=".$LoggedUser['AuthKey']."&amp;torrent_pass=".$LoggedUser['torrent_pass'];
  546. if (!empty(G::$LoggedUser) && (G::$LoggedUser['ShowMagnets'] ?? false)) {
  547. if (!($TorrentFileName = $Cache->get_value('torrent_file_name_'.$TorrentID))) {
  548. $TorrentFile = file_get_contents(TORRENT_STORE.$TorrentID.'.torrent');
  549. $Tor = new BencodeTorrent($TorrentFile, false, false);
  550. $TorrentFileName = $Tor->Dec['info']['name'];
  551. $Cache->cache_value('torrent_file_name_'.$TorrentID, $TorrentFileName);
  552. }
  553. $TorrentMG = "magnet:?dn=".rawurlencode($TorrentFileName)."&xt=urn:btih:".$Data['info_hash']."&as=https://".SITE_DOMAIN."/".str_replace('&amp;', '%26', $TorrentDL)."&tr=".implode("/".$LoggedUser['torrent_pass']."/announce&tr=", ANNOUNCE_URLS[0])."/".$LoggedUser['torrent_pass']."/announce&xl=".$Data['Size'];
  554. } ?>
  555. <tr class="group_torrent groupid_<?=$GroupID?> <?=$SnatchedTorrentClass . $SnatchedGroupClass . (!empty($LoggedUser['TorrentGrouping']) && $LoggedUser['TorrentGrouping'] == 1 ? ' hidden' : '')?>">
  556. <td colspan="3">
  557. <span>
  558. [ <a href="<?=$TorrentDL?>" class="tooltip" title="Download"><?=$Data['HasFile'] ? 'DL' : 'Missing'?></a>
  559. <?php if (isset($TorrentMG)) { ?>
  560. | <a href="<?=$TorrentMG?>" class="tooltip" title="Magnet Link">MG</a>
  561. <?php }
  562. if (Torrents::can_use_token($Data)) { ?>
  563. | <a href="torrents.php?action=download&amp;id=<?=$TorrentID?>&amp;authkey=<?=$LoggedUser['AuthKey']?>&amp;torrent_pass=<?=$LoggedUser['torrent_pass']?>&amp;usetoken=1" class="tooltip" title="Use a FL Token" onclick="return confirm('Are you sure you want to use a freeleech token here?');">FL</a>
  564. <?php } ?>
  565. | <a href="reportsv2.php?action=report&amp;id=<?=$TorrentID?>" class="tooltip" title="Report">RP</a> ]
  566. </span>
  567. &raquo; <a href="torrents.php?id=<?=$GroupID?>&amp;torrentid=<?=$TorrentID?>"><?=Torrents::torrent_info($Data)?><?php if ($Reported) { ?> / <strong class="torrent_label tl_reported tooltip" title="Type: <?=ucfirst($Reports[0]['Type'])?><br>Comment: <?=htmlentities(htmlentities($Reports[0]['UserComment']))?>">Reported</strong><?php } ?></a>
  568. </td>
  569. <td class="number_column"><?=$Data['FileCount']?></td>
  570. <td class="nobr"><?=time_diff($Data['Time'], 1)?></td>
  571. <td class="number_column nobr"><?=Format::get_size($Data['Size'])?></td>
  572. <td class="number_column"><?=number_format($Data['Snatched'])?></td>
  573. <td class="number_column<?=($Data['Seeders'] == 0) ? ' r00' : ''?>"><?=number_format($Data['Seeders'])?></td>
  574. <td class="number_column"><?=number_format($Data['Leechers'])?></td>
  575. </tr>
  576. <?php
  577. }
  578. } else {
  579. // Viewing a type that does not require grouping
  580. $TorrentID = key($Torrents);
  581. $Data = current($Torrents);
  582. $Reported = false;
  583. $Reports = Torrents::get_reports($TorrentID);
  584. if (count($Reports) > 0) {
  585. $Reported = true;
  586. }
  587. $Data['CategoryID'] = $CategoryID;
  588. $CoverArt = $GroupInfo['WikiImage'];
  589. $DisplayName .= "<a class=\"torrent_name\" href=\"torrents.php?id=$GroupID&amp;torrentid=$TorrentID#torrent$TorrentID\" ";
  590. if (!isset($LoggedUser['CoverArt']) || $LoggedUser['CoverArt']) {
  591. $DisplayName .= 'data-cover="'.ImageTools::process($CoverArt, 'thumb').'" ';
  592. }
  593. $DisplayName .= "dir=\"ltr\">$GroupName</a>";
  594. if (isset($GroupedCategories[$CategoryID - 1])) {
  595. if ($GroupYear) {
  596. $DisplayName .= " [$GroupYear]";
  597. }
  598. if ($GroupStudio) {
  599. $DisplayName .= " [$GroupStudio]";
  600. }
  601. if ($GroupCatalogueNumber) {
  602. $DisplayName .= " [$GroupCatalogueNumber]";
  603. }
  604. if ($GroupPages) {
  605. $DisplayName .= " [{$GroupPages}p]";
  606. }
  607. if ($GroupDLsiteID) {
  608. $DisplayName .= " [$GroupDLsiteID]";
  609. }
  610. $ExtraInfo = Torrents::torrent_info($Data, true, true);
  611. } elseif ($Data['IsSnatched']) {
  612. $ExtraInfo = Format::torrent_label('Snatched!');
  613. } else {
  614. $ExtraInfo = '';
  615. }
  616. $SnatchedTorrentClass = $Data['IsSnatched'] ? ' snatched_torrent' : '';
  617. $TorrentDL = "torrents.php?action=download&amp;id=".$TorrentID."&amp;authkey=".$LoggedUser['AuthKey']."&amp;torrent_pass=".$LoggedUser['torrent_pass'];
  618. if (!empty(G::$LoggedUser) && (G::$LoggedUser['ShowMagnets'] ?? false)) {
  619. if (!($TorrentFileName = $Cache->get_value('torrent_file_name_'.$TorrentID))) {
  620. $TorrentFile = file_get_contents(TORRENT_STORE.$TorrentID.'.torrent');
  621. $Tor = new BencodeTorrent($TorrentFile, false, false);
  622. $TorrentFileName = $Tor->Dec['info']['name'];
  623. $Cache->cache_value('torrent_file_name_'.$TorrentID, $TorrentFileName);
  624. }
  625. $TorrentMG = "magnet:?dn=".rawurlencode($TorrentFileName)."&xt=urn:btih:".$Data['info_hash']."&as=https://".SITE_DOMAIN."/".str_replace('&amp;', '%26', $TorrentDL)."&tr=".implode("/".$LoggedUser['torrent_pass']."/announce&tr=", ANNOUNCE_URLS[0])."/".$LoggedUser['torrent_pass']."/announce&xl=".$Data['Size'];
  626. } ?>
  627. <tr class="torrent<?=$SnatchedTorrentClass . $SnatchedGroupClass?>">
  628. <?php if ($GroupResults) { ?>
  629. <td></td>
  630. <?php } ?>
  631. <td class="center cats_col">
  632. <div title="<?=Format::pretty_category($CategoryID)?>" class="tooltip <?=Format::css_category($CategoryID)?>"></div>
  633. </td>
  634. <td class="big_info">
  635. <div class="group_info clear">
  636. <div class="float_right">
  637. <span>
  638. [ <a href="<?=$TorrentDL?>" class="tooltip" title="Download">DL</a>
  639. <?php if (isset($TorrentMG)) { ?>
  640. | <a href="<?=$TorrentMG?>" class="tooltip" title="Magnet Link">MG</a>
  641. <?php }
  642. if (Torrents::can_use_token($Data)) { ?>
  643. | <a href="torrents.php?action=download&amp;id=<?=$TorrentID?>&amp;authkey=<?=$LoggedUser['AuthKey']?>&amp;torrent_pass=<?=$LoggedUser['torrent_pass']?>&amp;usetoken=1" class="tooltip" title="Use a FL Token" onclick="return confirm('Are you sure you want to use a freeleech token here?');">FL</a>
  644. <?php } ?>
  645. | <a href="reportsv2.php?action=report&amp;id=<?=$TorrentID?>" class="tooltip" title="Report">RP</a> ]
  646. </span>
  647. <br />
  648. <?php if (in_array($GroupID, $Bookmarks)) { ?>
  649. <span class="remove_bookmark float_right">
  650. <a href="#" id="bookmarklink_torrent_<?=$GroupID?>" class="brackets" onclick="Unbookmark('torrent', <?=$GroupID?>, 'Bookmark'); return false;">Remove bookmark</a>
  651. </span>
  652. <?php } else { ?>
  653. <span class="add_bookmark float_right">
  654. <a href="#" id="bookmarklink_torrent_<?=$GroupID?>" class="brackets" onclick="Bookmark('torrent', <?=$GroupID?>, 'Remove bookmark'); return false;">Bookmark</a>
  655. </span>
  656. <?php } ?>
  657. </div>
  658. <?=$DisplayName?>
  659. <br />
  660. <div style="display: inline;" class="torrent_info"><?=$ExtraInfo?><?php if ($Reported) { ?> / <strong class="torrent_label tl_reported tooltip" title="Type: <?=ucfirst($Reports[0]['Type'])?><br>Comment: <?=htmlentities(htmlentities($Reports[0]['UserComment']))?>">Reported</strong><?php } ?></div>
  661. <div class="tags"><?=$TorrentTags->format("torrents.php?$Action&amp;taglist=")?></div>
  662. </div>
  663. </td>
  664. <td class="number_column"><?=$Data['FileCount']?></td>
  665. <td class="nobr"><?=time_diff($Data['Time'], 1)?></td>
  666. <td class="number_column nobr"><?=Format::get_size($Data['Size'])?></td>
  667. <td class="number_column"><?=number_format($Data['Snatched'])?></td>
  668. <td class="number_column<?=($Data['Seeders'] == 0) ? ' r00' : ''?>"><?=number_format($Data['Seeders'])?></td>
  669. <td class="number_column"><?=number_format($Data['Leechers'])?></td>
  670. </tr>
  671. <?php
  672. }
  673. }
  674. ?>
  675. </table>
  676. <div class="linkbox"><?=$Pages?></div>
  677. </div>
  678. <?php View::show_footer(); ?>