get(SCRAPE_LIST_PREFIX . bin2hex($decoded_hash))) { $torrents['files'][$info_key = array_key_first($scrape_cache)] = $scrape_cache[$info_key]; } else { $info_hashes[] = DB()->escape(($decoded_hash)); } } $info_hash_count = count($info_hashes); if (!empty($info_hash_count)) { if ($info_hash_count > $bb_cfg['max_scrapes']) { $info_hashes = array_slice($info_hashes, 0, $bb_cfg['max_scrapes']); } $info_hashes_sql = implode('\', \'', $info_hashes); /** * Currently torrent clients send truncated v2 hashes (the design raises questions). * @see https://github.com/bittorrent/bittorrent.org/issues/145#issuecomment-1720040343 */ $info_hash_where = "tor.info_hash IN ('$info_hashes_sql') OR SUBSTRING(tor.info_hash_v2, 1, 20) IN ('$info_hashes_sql')"; $sql = " SELECT tor.info_hash, tor.info_hash_v2, tor.complete_count, snap.seeders, snap.leechers FROM " . BB_BT_TORRENTS . " tor LEFT JOIN " . BB_BT_TRACKER_SNAP . " snap ON (snap.topic_id = tor.topic_id) WHERE $info_hash_where "; $scrapes = DB()->fetch_rowset($sql); if (!empty($scrapes)) { foreach ($scrapes as $scrape) { $hash_v1 = !empty($scrape['info_hash']) ? $scrape['info_hash'] : ''; $hash_v2 = !empty($scrape['info_hash_v2']) ? substr($scrape['info_hash_v2'], 0, 20) : ''; $info_hash_scrape = (in_array(urlencode($hash_v1), $info_hash_array[1])) ? $hash_v1 : $hash_v2; // Replace logic to prioritize $hash_v2, in case of future prioritization of v2 $torrents['files'][$info_hash_scrape] = [ 'complete' => (int)$scrape['seeders'], 'downloaded' => (int)$scrape['complete_count'], 'incomplete' => (int)$scrape['leechers'] ]; CACHE('tr_cache')->set(SCRAPE_LIST_PREFIX . bin2hex($info_hash_scrape), array_slice($torrents['files'], -1, null, true), SCRAPE_LIST_EXPIRE); } } } // Verify if torrent registered on tracker if (empty($torrents)) { msg_die('Torrent not registered, info_hash = ' . (mb_check_encoding($info_hash, DEFAULT_CHARSET) ? $info_hash : $info_hash_hex)); } die(\Arokettu\Bencode\Bencode::encode($torrents));