def setmagnetlink(self, wantmodified): """ Set magnet link (note could easily be modified to return torrentdata or torrentfile if wanted) - assume that metadata already fetched but that _metadata.files not converted to _list yet (as that process will use this data. :return: """ if not self._metadata: raise CodingException( message="Must have fetched metadata before read torrentdata") ff = [ f for f in self._metadata["files"] if f.get("format") == "Archive BitTorrent" ] if not len(ff) == 1: raise CodingException( message='Should be exactly one "Archive BitTorrent" file') torrentfilemeta = ff[0] torrentfileurl = "{}{}/{}".format(config["archive"]["url_download"], self.itemid, torrentfilemeta["name"]) torrentcontents = httpget(torrentfileurl, wantmime=False) self.torrentdata = bencode.bdecode( torrentcontents) # Convert to a object assert (bencode.bencode(self.torrentdata) == torrentcontents) hash_contents = bencode.bencode(self.torrentdata['info']) digest = hashlib.sha1(hash_contents).digest() b32hash = base64.b32encode(digest) # Get the hash of the torrent file # Now revise the data since IA torrents as of Dec2017 have issues if wantmodified: # The trackers at bt1 and bt2 are http, but they dont support webtorrent anyway so that doesnt matter. webtorrenttrackerlist = [ 'wss://tracker.btorrent.xyz', 'wss://tracker.openwebtorrent.com', 'wss://tracker.fastcast.nz' ] self.torrentdata["announce-list"] += [ [wtt] for wtt in webtorrenttrackerlist ] # Note announce-list is never empty after this, so can ignore announce field # Replace http with https (as cant call http from https) BUT still has cors issues # self.torrentdata["url-list"] = [ u.replace("http://","https://") for u in self.torrentdata["url-list"] ] self.torrentdata["url-list"] = [config["gateway"]["url_download"] ] # Has trailing slash externaltorrenturl = "{}{}".format( config["gateway"]["url_torrent"], self.itemid) # Intentionally no file name, we are modifying it else: externaltorrenturl = "{}{}/{}".format( config["archive"]["url_download"], self.itemid, torrentfilemeta["name"]) magnetlink = ''.join([ 'magnet:?xt=urn:btih:', b32hash.decode('ASCII'), ''.join(['&tr=' + urllib.parse.quote_plus(t[0]) for t in self.torrentdata['announce-list']]), ''.join(['&ws=' + urllib.parse.quote_plus(t) \ for t in self.torrentdata['url-list']]), '&xs=', urllib.parse.quote_plus(externaltorrenturl), ]) self._metadata["metadata"]["magnetlink"] = magnetlink return
def from_torrent_data(torrent_contents): """ return a magnet URI given Bittorrent torrent file content """ metadata = bencode.bdecode(torrent_contents) hash_contents = bencode.bencode(metadata['info']) digest = hashlib.sha1(hash_contents).digest() b32hash = base64.b32encode(digest) return 'magnet:?xt=urn:btih:%s' % b32hash.decode('ASCII')
def get_hash_from_torrent(self): from magneturi import bencode import hashlib self.download_torrent() decodedDict = bencode.bdecode(self.content) info_hash = hashlib.sha1(bencode.bencode( decodedDict["info"])).hexdigest() return info_hash
def modifiedtorrent(cls, itemid, wantmodified=True, verbose=False): # Assume its named <itemid>_archive.torrent torrentfilename = itemid + "_archive.torrent" torrentfileurl = "{}{}/{}".format(config["archive"]["url_download"], itemid, torrentfilename) try: torrentcontents = httpget(torrentfileurl, wantmime=False) except (requests.exceptions.HTTPError, TransportURLNotFound) as e: logging.warning("Inaccessible torrent at {}, {}".format(torrentfileurl, e)) return # Its ok if cant get a torrent try: # noinspection PyAttributeOutsideInit torrentdata = bencode.bdecode(torrentcontents) # Convert to a object XXX-do we use this except here except bencode.DecodingException as e: # Probably a magneturi.bencode.DecodingException - there are lots of bad torrents, mostly skipped cos files too big (according to Aaron Ximm) logging.warning("Bad Torrent file at: {}".format(torrentfileurl)) return # Dont need to throw an error - we'll just skip it assert (bencode.bencode(torrentdata) == torrentcontents) hash_contents = bencode.bencode(torrentdata['info']) digest = hashlib.sha1(hash_contents).digest() b32hash = base64.b32encode(digest) # Get the hash of the torrent file b32hashascii = b32hash.decode('ASCII') # Now possible revise the data since IA torrents as of Dec2017 have issues, this doesnt change the hash. if wantmodified: # Normally we want the torrent file modified to support WebTorrent and not use HTTP URLs # The trackers at bt1 and bt2 are http, but they dont support webtorrent anyway so that doesnt matter. webtorrenttrackerlist = ['wss://tracker.btorrent.xyz', 'wss://tracker.openwebtorrent.com', 'wss://tracker.fastcast.nz'] torrentdata["announce-list"] += [[wtt] for wtt in webtorrenttrackerlist] # Note announce-list is never empty after this, so can ignore announce field # Replace http with https (as cant call http from https) BUT still has cors issues # torrentdata["url-list"] = [ u.replace("http://","https://") for u in torrentdata["url-list"] ] torrentdata["url-list"] = [config["gateway"]["url_download"]] # Has trailing slash externaltorrenturl = "{}{}".format(config["gateway"]["url_torrent"], itemid) # Intentionally no file name, we are modifying it else: externaltorrenturl = "{}{}/{}".format(config["archive"]["url_download"], itemid, torrentfilename) magnetlink = ''.join([ 'magnet:?xt=urn:btih:', b32hashascii, ''.join(['&tr=' + urllib.parse.quote_plus(t[0]) for t in torrentdata['announce-list']]), ''.join(['&ws=' + urllib.parse.quote_plus(t) for t in torrentdata['url-list']]), '&xs=', urllib.parse.quote_plus(externaltorrenturl), ]) MagnetLinkService.archiveidset(itemid, magnetlink, verbose) # Cache it if verbose: logging.info("New magnetlink for item: {}, {}".format(itemid, magnetlink)) # We should probably extract the b32hashascii from the magnetlink if we already have one MagnetLinkService.btihset(b32hashascii, magnetlink, verbose) # Cache mapping from torrenthash to magnetlink return torrentdata
def from_torrent_data(torrent_contents): """ return a magnet URI given Bittorrent torrent file content """ metadata = bencode.bdecode(torrent_contents) hash_contents = bencode.bencode(metadata['info']) digest = hashlib.sha1(hash_contents).digest() b32hash = base64.b32encode(digest) if 'announce-list' in metadata: tracker_list = ''.join(['&tr='+urllib.parse.quote_plus(t[0]) \ for t in metadata['announce-list']]) elif 'announce' in metadata: tracker_list = '&tr='+urllib.parse.quote_plus(metadata['announce']) else: tracker_list = '' result = ''.join([b32hash.decode('ASCII'), tracker_list]) return 'magnet:?xt=urn:btih:%s' % result