mirror of
https://github.com/sb745/NyaaV3.git
synced 2025-03-12 22:06:55 +02:00

With all trackers.txt trackers being included in generated .torrents, we can now be certain the magnet (which use trackers.txt) and the .torrent uses will not be split up in different swarms in case the main announce dies. (That is, if uploaders add enough of their own trackers and additional trackers were deemed unnecessary (at least 5 already), the magnet and .torrent would only share the main site announce)
141 lines
4 KiB
Python
141 lines
4 KiB
Python
import base64
|
|
import os
|
|
import time
|
|
from urllib.parse import urlencode
|
|
|
|
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)
|
|
]
|
|
for tracker in trackers[:max_trackers]:
|
|
magnet_parts.append(('tr', tracker))
|
|
|
|
b32_info_hash = base64.b32encode(torrent.info_hash).decode('utf-8')
|
|
return 'magnet:?xt=urn:btih:' + b32_info_hash + '&' + urlencode(magnet_parts)
|
|
|
|
|
|
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(time.time()),
|
|
'comment': 'NyaaV2 Torrent #' + str(torrent.id),
|
|
# '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, 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_info = torrent.info.info_dict
|
|
bencoded_torrent = prefix[:-1] + b'4:info' + bencoded_info + suffix[1:]
|
|
|
|
return bencoded_torrent
|