def _valid_torrent_file(path: Path) -> bool: try: bdecode(path.read_bytes()) return True except BencodeError: pass # We might be racing the process writing to the filesystem. sleep(1) # This is literally killing kittens. try: bdecode(path.read_bytes()) return True except BencodeError: return False
def _get_torrent_hash(result): if result.url.startswith('magnet'): result.hash = re.findall(r'urn:btih:([\w]{32,40})', result.url)[0] if len(result.hash) == 32: result.hash = b16encode(b32decode(result.hash)).lower() else: if not result.content: sickrage.app.log.warning('Torrent without content') raise Exception('Torrent without content') try: torrent_bdecode = bdecode(result.content) except BencodeError: sickrage.app.log.warning('Unable to bdecode torrent') sickrage.app.log.debug('Torrent bencoded data: %r' % result.content) raise try: info = torrent_bdecode["info"] except Exception: sickrage.app.log.warning('Unable to find info field in torrent') raise result.hash = sha1(bencode(info)).hexdigest() return result
def add_trackers(self, result): """ Adds public trackers to either torrent file or magnet link :param result: SearchResult :return: SearchResult """ try: trackers_list = self.session.get('https://cdn.sickrage.ca/torrent_trackers/').text.split() except Exception: trackers_list = [] if trackers_list: # adds public torrent trackers to magnet url if result.url.startswith('magnet:'): if not result.url.endswith('&tr='): result.url += '&tr=' result.url += '&tr='.join(trackers_list) # adds public torrent trackers to content if result.content: decoded_data = bdecode(result.content) if not decoded_data.get('announce-list'): decoded_data['announce-list'] = [] for tracker in trackers_list: if tracker not in decoded_data['announce-list']: decoded_data['announce-list'].append([str(tracker)]) result.content = bencode(decoded_data) return result
def validateRSS(self): torrent_file = None try: add_cookie = self.add_cookies_from_ui() if not add_cookie.get('result'): return add_cookie data = self.cache._get_rss_data()['entries'] if not data: return {'result': False, 'message': 'No items found in the RSS feed {}'.format(self.urls['base_url'])} (title, url) = self._get_title_and_url(data[0]) if not title: return {'result': False, 'message': 'Unable to get title from first item'} if not url: return {'result': False, 'message': 'Unable to get torrent url from first item'} if url.startswith('magnet:') and re.search(r'urn:btih:([\w]{32,40})', url): return {'result': True, 'message': 'RSS feed Parsed correctly'} else: try: torrent_file = self.session.get(url).content bdecode(torrent_file) except Exception as e: if data: self.dumpHTML(torrent_file) return {'result': False, 'message': 'Torrent link is not a valid torrent file: {}'.format(e)} return {'result': True, 'message': 'RSS feed Parsed correctly'} except Exception as e: return {'result': False, 'message': 'Error when trying to load RSS: {}'.format(e)}
def _handle_file(self, tor_file_path): try: with open(tor_file_path, 'rb') as tor_file: metainfo = tor_file.read() except FileNotFoundError: raise TorrentError("No Torrent File With That Name.") metadict = bdecode(metainfo) self.info = metadict['info'] self.info_hash = self._hash_info(self.info) self.announce = metadict['announce'] self.length = self.info['length'] self.piece_length = self.info['piece length'] self.target_file_name = self.info['name'] # The pieces entry consists of 20 byte hash values for each pieces. self.num_pieces = len(self.info['pieces'])//20 self.piece_hashes = [] hashes = self.info['pieces'] while hashes: self.piece_hashes.append(hashes[:20]) hashes = hashes[20:]
def _handle_response(self, response): """Parse the tracker response and return decoded dictionary and make necessary state changes to tracker""" # TODO: Implement Updating the Tracker on our status. # Decode the response response_dict = bdecode(response) # Check if tracker_id should be updated. if response_dict.get('tracker id'): self.tracker_id = response_dict['tracker id'] self.interval = response_dict.get('interval', 1800) self.min_interval = response_dict.get('min interval', self.interval) # Handle list of peers peers = response_dict['peers'] if isinstance(peers, list): self.peers = peers else: response_dict['peers'] = self._parse_binary_peers(peers) return response_dict
def verify_torrent(content): try: if bdecode(content).get('info'): return content except Exception: pass