From 0a258d59e1386e2e966cbe831b33d44922ec035d Mon Sep 17 00:00:00 2001 From: nyaadev Date: Mon, 22 May 2017 01:49:02 +0200 Subject: [PATCH] temporary ghetto import, will be removed once importing is done. --- nyaa/api_handler.py | 137 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/nyaa/api_handler.py b/nyaa/api_handler.py index 6638af7..4ddd510 100644 --- a/nyaa/api_handler.py +++ b/nyaa/api_handler.py @@ -186,3 +186,140 @@ def v2_api_upload(): # Map errors back from form fields into the api keys mapped_errors = {UPLOAD_API_FORM_KEYMAP.get(k, k): v for k, v in upload_form.errors.items()} return flask.jsonify({'errors': mapped_errors}), 400 + + +# #################################### TEMPORARY #################################### + +from orderedset import OrderedSet + + +@api_blueprint.route('/ghetto_import', methods=['POST']) +def ghetto_import(): + if flask.request.remote_addr != '127.0.0.1': + return flask.error(403) + + torrent_file = flask.request.files.get('torrent') + + try: + torrent_dict = bencode.decode(torrent_file) + # field.data.close() + except (bencode.MalformedBencodeException, UnicodeError): + return 'Malformed torrent file', 500 + + try: + forms._validate_torrent_metadata(torrent_dict) + except AssertionError as e: + return 'Malformed torrent metadata ({})'.format(e.args[0]), 500 + + try: + tracker_found = forms._validate_trackers(torrent_dict) + except AssertionError as e: + return 'Malformed torrent trackers ({})'.format(e.args[0]), 500 + + bencoded_info_dict = bencode.encode(torrent_dict['info']) + info_hash = utils.sha1_hash(bencoded_info_dict) + + # Check if the info_hash exists already in the database + torrent = models.Torrent.by_info_hash(info_hash) + if not torrent: + return 'This torrent does not exists', 500 + + if torrent.has_torrent: + return 'This torrent already has_torrent', 500 + + # Torrent is legit, pass original filename and dict along + torrent_data = forms.TorrentFileData(filename=os.path.basename(torrent_file.filename), + torrent_dict=torrent_dict, + info_hash=info_hash, + bencoded_info_dict=bencoded_info_dict) + + # The torrent has been validated and is safe to access with ['foo'] etc - all relevant + # keys and values have been checked for (see UploadForm in forms.py for details) + info_dict = torrent_data.torrent_dict['info'] + + changed_to_utf8 = backend._replace_utf8_values(torrent_data.torrent_dict) + + torrent_filesize = info_dict.get('length') or sum( + f['length'] for f in info_dict.get('files')) + + # In case no encoding, assume UTF-8. + torrent_encoding = torrent_data.torrent_dict.get('encoding', b'utf-8').decode('utf-8') + + # Store bencoded info_dict + torrent.info = models.TorrentInfo(info_dict=torrent_data.bencoded_info_dict) + torrent.has_torrent = True + + # To simplify parsing the filelist, turn single-file torrent into a list + torrent_filelist = info_dict.get('files') + + used_path_encoding = changed_to_utf8 and 'utf-8' or torrent_encoding + + parsed_file_tree = dict() + if not torrent_filelist: + # If single-file, the root will be the file-tree (no directory) + file_tree_root = parsed_file_tree + torrent_filelist = [{'length': torrent_filesize, 'path': [info_dict['name']]}] + else: + # If multi-file, use the directory name as root for files + file_tree_root = parsed_file_tree.setdefault( + info_dict['name'].decode(used_path_encoding), {}) + + # Parse file dicts into a tree + for file_dict in torrent_filelist: + # Decode path parts from utf8-bytes + path_parts = [path_part.decode(used_path_encoding) for path_part in file_dict['path']] + + filename = path_parts.pop() + current_directory = file_tree_root + + for directory in path_parts: + current_directory = current_directory.setdefault(directory, {}) + + # Don't add empty filenames (BitComet directory) + if filename: + current_directory[filename] = file_dict['length'] + + parsed_file_tree = utils.sorted_pathdict(parsed_file_tree) + + json_bytes = json.dumps(parsed_file_tree, separators=(',', ':')).encode('utf8') + torrent.filelist = models.TorrentFilelist(filelist_blob=json_bytes) + + db.session.add(torrent) + db.session.flush() + + # Store the users trackers + trackers = OrderedSet() + announce = torrent_data.torrent_dict.get('announce', b'').decode('ascii') + if announce: + trackers.add(announce) + + # List of lists with single item + announce_list = torrent_data.torrent_dict.get('announce-list', []) + for announce in announce_list: + trackers.add(announce[0].decode('ascii')) + + # Remove our trackers, maybe? TODO ? + + # Search for/Add trackers in DB + db_trackers = OrderedSet() + for announce in trackers: + tracker = models.Trackers.by_uri(announce) + + # Insert new tracker if not found + if not tracker: + tracker = models.Trackers(uri=announce) + db.session.add(tracker) + + db_trackers.add(tracker) + + db.session.flush() + + # Store tracker refs in DB + for order, tracker in enumerate(db_trackers): + torrent_tracker = models.TorrentTrackers(torrent_id=torrent.id, + tracker_id=tracker.id, order=order) + db.session.add(torrent_tracker) + + db.session.commit() + + return 'success'