2
from flexget.plugin import register_plugin, priority, PluginError
3
# TORRENT_RE is redundant by now, but keep it here, in case someone was crazy enough to import it
4
from flexget.utils.bittorrent import Torrent, is_torrent_file, TORRENT_RE
7
log = logging.getLogger('modif_torrent')
10
class TorrentFilename(object):
12
Makes sure that entries containing torrent-file have .torrent
13
extension. This is enabled always by default (builtins).
17
@priority(TORRENT_PRIO)
18
def on_feed_modify(self, feed):
19
for entry in feed.entries:
20
# skip if entry does not have file assigned
21
if not 'file' in entry:
22
log.debugall('%s doesn\'t have a file associated' % entry['title'])
24
if not os.path.exists(entry['file']):
25
raise PluginError('File %s does not exists' % entry['file'])
26
if os.path.getsize(entry['file']) == 0:
27
raise PluginError('File %s is 0 bytes in size' % entry['file'])
29
if not is_torrent_file(entry['file']):
31
log.debug('%s seems to be a torrent' % entry['title'])
33
# create torrent object from torrent
35
f = open(entry['file'], 'rb')
36
# NOTE: this reads entire file into memory, but we're pretty sure it's
37
# a small torrent file since it starts with TORRENT_RE
41
if 'content-length' in entry:
42
if len(data) != entry['content-length']:
43
feed.fail(entry, 'Torrent file length doesn\'t match to the one reported by the server')
47
# construct torrent object
49
torrent = Torrent(data)
50
except SyntaxError, e:
51
feed.fail(entry, '%s - Torrent could not be parsed' % e.message)
55
entry['torrent'] = torrent
56
entry['torrent_info_hash'] = torrent.get_info_hash()
57
# if we do not have good filename (by download plugin)
58
# for this entry, try to generate one from torrent content
59
if entry.get('filename'):
60
if not entry['filename'].lower().endswith('.torrent'):
61
# filename present but without .torrent extension, add it
62
entry['filename'] = entry['filename'] + '.torrent'
64
# generate filename from torrent or fall back to title plus extension
65
entry['filename'] = self.make_filename(torrent, entry)
69
@priority(TORRENT_PRIO)
70
def on_feed_output(self, feed):
71
for entry in feed.entries:
72
if 'torrent' in entry:
73
if entry['torrent'].modified:
74
# re-write data into a file
75
log.debug('Writing modified torrent file for %s' % entry['title'])
76
f = open(entry['file'], 'wb+')
77
f.write(entry['torrent'].encode())
80
def make_filename(self, torrent, entry):
81
"""Build a filename for this torrent"""
83
title = entry['title']
84
files = torrent.get_filelist()
86
# single file, if filename is longer than title use it
88
if len(fn) > len(title):
89
title = fn[:fn.rfind('.')]
92
title = title.replace('/', '_')
93
title = title.replace(' ', '_')
94
title = title.replace('\u200b', '')
96
# title = title.encode('iso8859-1', 'ignore') # Damn \u200b -character, how I loathe thee
97
# TODO: replace only zero width spaces, leave unicode alone?
99
fn = '%s.torrent' % title
100
log.debug('make_filename made %s' % fn)
103
def purge(self, entry):
105
if os.path.exists(entry['file']):
106
log.debug('removing temp file %s from %s' % (entry['file'], entry['title']))
107
os.remove(entry['file'])
111
register_plugin(TorrentFilename, 'torrent', builtin=True)