1
0
Fork 0
mirror of https://gitlab.com/SIGBUS/nyaa.git synced 2024-06-09 08:08:30 +00:00
nyaa/nyaa/torrents.py
TheAMM bf090c0fab torrents: clean up & optimize magnets further
Removes the specialized template ES magnet creator, since create_magnet()
can use both Torrents and ES objects. Search results will get the
properly escaped magnets, now.
Slightly optimizes the tracker adding and string joins.
RIP base32, wonder how many bad clients will break with sha1.
2018-07-21 22:06:58 +03:00

152 lines
4.3 KiB
Python

import os
from urllib.parse import quote, urlencode
import flask
from flask import current_app as app
from orderedset import OrderedSet
from nyaa import bencode
USED_TRACKERS = OrderedSet()
def read_trackers_from_file(file_object):
USED_TRACKERS.clear()
for line in file_object:
line = line.strip()
if line and not line.startswith('#'):
USED_TRACKERS.add(line)
return USED_TRACKERS
def read_trackers():
tracker_list_file = os.path.join(app.config['BASE_DIR'], 'trackers.txt')
if os.path.exists(tracker_list_file):
with open(tracker_list_file, 'r') as in_file:
return read_trackers_from_file(in_file)
def default_trackers():
if not USED_TRACKERS:
read_trackers()
return USED_TRACKERS[:]
def get_trackers_and_webseeds(torrent):
trackers = OrderedSet()
webseeds = OrderedSet()
# Our main one first
main_announce_url = app.config.get('MAIN_ANNOUNCE_URL')
if main_announce_url:
trackers.add(main_announce_url)
# then the user ones
torrent_trackers = torrent.trackers # here be webseeds too
for torrent_tracker in torrent_trackers:
tracker = torrent_tracker.tracker
# separate potential webseeds
if tracker.is_webseed:
webseeds.add(tracker.uri)
else:
trackers.add(tracker.uri)
# and finally our tracker list
trackers.update(default_trackers())
return list(trackers), list(webseeds)
def get_default_trackers():
trackers = OrderedSet()
# Our main one first
main_announce_url = app.config.get('MAIN_ANNOUNCE_URL')
if main_announce_url:
trackers.add(main_announce_url)
# and finally our tracker list
trackers.update(default_trackers())
return list(trackers)
def create_magnet(torrent, max_trackers=5, trackers=None):
# Unless specified, we just use default trackers
if trackers is None:
trackers = get_default_trackers()
magnet_parts = [
('dn', torrent.display_name)
]
magnet_parts.extend(
('tr', tracker_url)
for tracker_url in trackers[:max_trackers]
)
# Since we accept both models.Torrents and ES objects,
# we need to make sure the info_hash is a hex string
info_hash = torrent.info_hash
if isinstance(info_hash, (bytes, bytearray)):
info_hash = info_hash.hex()
return ''.join([
'magnet:?xt=urn:btih:', info_hash,
'&', urlencode(magnet_parts, quote_via=quote)
])
def create_default_metadata_base(torrent, trackers=None, webseeds=None):
if trackers is None or webseeds is None:
db_trackers, db_webseeds = get_trackers_and_webseeds(torrent)
trackers = db_trackers if trackers is None else trackers
webseeds = db_webseeds if webseeds is None else webseeds
metadata_base = {
'created by': 'NyaaV2',
'creation date': int(torrent.created_utc_timestamp),
'comment': flask.url_for('torrents.view',
torrent_id=torrent.id,
_external=True)
# 'encoding' : 'UTF-8' # It's almost always UTF-8 and expected, but if it isn't...
}
if len(trackers) > 0:
metadata_base['announce'] = trackers[0]
if len(trackers) > 1:
# Yes, it's a list of lists with a single element inside.
metadata_base['announce-list'] = [[tracker] for tracker in trackers]
# Add webseeds
if webseeds:
metadata_base['url-list'] = webseeds
return metadata_base
def create_bencoded_torrent(torrent, bencoded_info, metadata_base=None):
''' Creates a bencoded torrent metadata for a given torrent,
optionally using a given metadata_base dict (note: 'info' key will be
popped off the dict) '''
if metadata_base is None:
metadata_base = create_default_metadata_base(torrent)
metadata_base['encoding'] = torrent.encoding
# Make sure info doesn't exist on the base
metadata_base.pop('info', None)
prefixed_dict = {key: metadata_base[key] for key in metadata_base if key < 'info'}
suffixed_dict = {key: metadata_base[key] for key in metadata_base if key > 'info'}
prefix = bencode.encode(prefixed_dict)
suffix = bencode.encode(suffixed_dict)
bencoded_torrent = prefix[:-1] + b'4:info' + bencoded_info + suffix[1:]
return bencoded_torrent