mirror of
https://git.deluge-torrent.org/deluge
synced 2025-08-03 06:58:42 +00:00
AutoAdd plugin can now recover when one of the watchfolders has an unhandled exception.
This commit is contained in:
parent
a794223d96
commit
4b92912577
2 changed files with 56 additions and 58 deletions
|
@ -78,9 +78,7 @@ OPTIONS_AVAILABLE = { #option: builtin
|
||||||
MAX_NUM_ATTEMPTS = 10
|
MAX_NUM_ATTEMPTS = 10
|
||||||
|
|
||||||
class AutoaddOptionsChangedEvent(DelugeEvent):
|
class AutoaddOptionsChangedEvent(DelugeEvent):
|
||||||
"""
|
"""Emitted when the options for the plugin are changed."""
|
||||||
Emitted when a new command is added.
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -95,12 +93,9 @@ class Core(CorePluginBase):
|
||||||
self.config = deluge.configmanager.ConfigManager("autoadd.conf", DEFAULT_PREFS)
|
self.config = deluge.configmanager.ConfigManager("autoadd.conf", DEFAULT_PREFS)
|
||||||
self.watchdirs = self.config["watchdirs"]
|
self.watchdirs = self.config["watchdirs"]
|
||||||
self.core_cfg = deluge.configmanager.ConfigManager("core.conf")
|
self.core_cfg = deluge.configmanager.ConfigManager("core.conf")
|
||||||
|
|
||||||
|
# Dict of Filename:Attempts
|
||||||
# A list of filenames
|
self.invalid_torrents = {}
|
||||||
self.invalid_torrents = []
|
|
||||||
# Filename:Attempts
|
|
||||||
self.attempts = {}
|
|
||||||
# Loopingcall timers for each enabled watchdir
|
# Loopingcall timers for each enabled watchdir
|
||||||
self.update_timers = {}
|
self.update_timers = {}
|
||||||
# If core autoadd folder is enabled, move it to the plugin
|
# If core autoadd folder is enabled, move it to the plugin
|
||||||
|
@ -127,16 +122,13 @@ class Core(CorePluginBase):
|
||||||
for loopingcall in self.update_timers.itervalues():
|
for loopingcall in self.update_timers.itervalues():
|
||||||
loopingcall.stop()
|
loopingcall.stop()
|
||||||
self.config.save()
|
self.config.save()
|
||||||
pass
|
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@export()
|
@export()
|
||||||
def set_options(self, watchdir_id, options):
|
def set_options(self, watchdir_id, options):
|
||||||
"""
|
"""Update the options for a watch folder."""
|
||||||
update the options for a watch folder
|
|
||||||
"""
|
|
||||||
watchdir_id = str(watchdir_id)
|
watchdir_id = str(watchdir_id)
|
||||||
options = self._clean_unicode(options)
|
options = self._clean_unicode(options)
|
||||||
CheckInput(watchdir_id in self.watchdirs , _("Watch folder does not exist."))
|
CheckInput(watchdir_id in self.watchdirs , _("Watch folder does not exist."))
|
||||||
|
@ -179,28 +171,25 @@ class Core(CorePluginBase):
|
||||||
return filedump
|
return filedump
|
||||||
|
|
||||||
def update_watchdir(self, watchdir_id):
|
def update_watchdir(self, watchdir_id):
|
||||||
|
"""Check the watch folder for new torrents to add."""
|
||||||
watchdir_id = str(watchdir_id)
|
watchdir_id = str(watchdir_id)
|
||||||
watchdir = self.watchdirs[watchdir_id]
|
watchdir = self.watchdirs[watchdir_id]
|
||||||
if not watchdir['enabled']:
|
if not watchdir['enabled']:
|
||||||
# We shouldn't be updating because this watchdir is not enabled
|
# We shouldn't be updating because this watchdir is not enabled
|
||||||
#disable the looping call
|
self.disable_watchdir(watchdir_id)
|
||||||
self.update_timers[watchdir_id].stop()
|
|
||||||
del self.update_timers[watchdir_id]
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check the auto add folder for new torrents to add
|
|
||||||
if not os.path.isdir(watchdir["abspath"]):
|
if not os.path.isdir(watchdir["abspath"]):
|
||||||
log.warning("Invalid AutoAdd folder: %s", watchdir["abspath"])
|
log.warning("Invalid AutoAdd folder: %s", watchdir["abspath"])
|
||||||
#disable the looping call
|
self.disable_watchdir(watchdir_id)
|
||||||
watchdir['enabled'] = False
|
|
||||||
self.update_timers[watchdir_id].stop()
|
|
||||||
del self.update_timers[watchdir_id]
|
|
||||||
return
|
return
|
||||||
|
|
||||||
#Generate options dict for watchdir
|
# Generate options dict for watchdir
|
||||||
opts={}
|
opts = {}
|
||||||
if watchdir.get('stop_at_ratio_toggle'):
|
if 'stop_at_ratio_toggle' in watchdir:
|
||||||
watchdir['stop_ratio_toggle'] = True
|
watchdir['stop_ratio_toggle'] = watchdir['stop_at_ratio_toggle']
|
||||||
|
# We default to True wher reading _toggle values, so a config
|
||||||
|
# without them is valid, and applies all its settings.
|
||||||
for option, value in watchdir.iteritems():
|
for option, value in watchdir.iteritems():
|
||||||
if OPTIONS_AVAILABLE.get(option):
|
if OPTIONS_AVAILABLE.get(option):
|
||||||
if watchdir.get(option+'_toggle', True):
|
if watchdir.get(option+'_toggle', True):
|
||||||
|
@ -221,18 +210,17 @@ class Core(CorePluginBase):
|
||||||
# torrents may not be fully saved during the pass.
|
# torrents may not be fully saved during the pass.
|
||||||
log.debug("Torrent is invalid: %s", e)
|
log.debug("Torrent is invalid: %s", e)
|
||||||
if filename in self.invalid_torrents:
|
if filename in self.invalid_torrents:
|
||||||
self.attempts[filename] += 1
|
self.invalid_torrents[filename] += 1
|
||||||
if self.attempts[filename] >= MAX_NUM_ATTEMPTS:
|
if self.invalid_torrents[filename] >= MAX_NUM_ATTEMPTS:
|
||||||
os.rename(filepath, filepath + ".invalid")
|
os.rename(filepath, filepath + ".invalid")
|
||||||
del self.attempts[filename]
|
del self.invalid_torrents[filename]
|
||||||
self.invalid_torrents.remove(filename)
|
|
||||||
else:
|
else:
|
||||||
self.invalid_torrents.append(filename)
|
self.invalid_torrents[filename] = 1
|
||||||
self.attempts[filename] = 1
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# The torrent looks good, so lets add it to the session
|
# The torrent looks good, so lets add it to the session.
|
||||||
torrent_id = component.get("TorrentManager").add(filedump=filedump, filename=filename, options=opts)
|
torrent_id = component.get("TorrentManager").add(filedump=filedump, filename=filename, options=opts)
|
||||||
|
# If the torrent added successfully, set the extra options.
|
||||||
if torrent_id:
|
if torrent_id:
|
||||||
if 'Label' in component.get("CorePluginManager").get_enabled_plugins():
|
if 'Label' in component.get("CorePluginManager").get_enabled_plugins():
|
||||||
if watchdir.get('label_toggle', True) and watchdir.get('label'):
|
if watchdir.get('label_toggle', True) and watchdir.get('label'):
|
||||||
|
@ -240,41 +228,54 @@ class Core(CorePluginBase):
|
||||||
if not watchdir['label'] in label.get_labels():
|
if not watchdir['label'] in label.get_labels():
|
||||||
label.add(watchdir['label'])
|
label.add(watchdir['label'])
|
||||||
label.set_torrent(torrent_id, watchdir['label'])
|
label.set_torrent(torrent_id, watchdir['label'])
|
||||||
if watchdir.get('queue_to_top_toggle'):
|
if watchdir.get('queue_to_top_toggle', True) and 'queue_to_top' in watchdir:
|
||||||
if watchdir.get('queue_to_top', True):
|
if watchdir['queue_to_top']:
|
||||||
component.get("TorrentManager").queue_top(torrent_id)
|
component.get("TorrentManager").queue_top(torrent_id)
|
||||||
else:
|
else:
|
||||||
component.get("TorrentManager").queue_bottom(torrent_id)
|
component.get("TorrentManager").queue_bottom(torrent_id)
|
||||||
if watchdir.get('append_extension_toggle', False):
|
# Rename or delete the torrent once added to deluge.
|
||||||
|
if watchdir.get('append_extension_toggle'):
|
||||||
if not watchdir.get('append_extension'):
|
if not watchdir.get('append_extension'):
|
||||||
watchdir['append_extension'] = ".added"
|
watchdir['append_extension'] = ".added"
|
||||||
os.rename(filepath, filepath + watchdir['append_extension'])
|
os.rename(filepath, filepath + watchdir['append_extension'])
|
||||||
else:
|
else:
|
||||||
os.remove(filepath)
|
os.remove(filepath)
|
||||||
|
|
||||||
|
def on_update_watchdir_error(self, failure, watchdir_id):
|
||||||
|
"""Disables any watch folders with unhandled exceptions."""
|
||||||
|
self.disable_watchdir(watchdir_id)
|
||||||
|
log.error("Disabling '%s', error during update: %s" % (self.watchdirs[watchdir_id]["path"], failure))
|
||||||
|
|
||||||
@export
|
@export
|
||||||
def enable_watchdir(self, watchdir_id):
|
def enable_watchdir(self, watchdir_id):
|
||||||
watchdir_id = str(watchdir_id)
|
watchdir_id = str(watchdir_id)
|
||||||
self.watchdirs[watchdir_id]['enabled'] = True
|
# Enable the looping call
|
||||||
#Enable the looping call
|
if watchdir_id not in self.update_timers or not self.update_timers[watchdir_id].running:
|
||||||
self.update_timers[watchdir_id] = LoopingCall(self.update_watchdir, watchdir_id)
|
self.update_timers[watchdir_id] = LoopingCall(self.update_watchdir, watchdir_id)
|
||||||
self.update_timers[watchdir_id].start(5)
|
self.update_timers[watchdir_id].start(5).addErrback(self.on_update_watchdir_error, watchdir_id)
|
||||||
self.config.save()
|
# Update the config
|
||||||
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
|
if not self.watchdirs[watchdir_id]['enabled']:
|
||||||
|
self.watchdirs[watchdir_id]['enabled'] = True
|
||||||
|
self.config.save()
|
||||||
|
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
|
||||||
|
|
||||||
@export
|
@export
|
||||||
def disable_watchdir(self, watchdir_id):
|
def disable_watchdir(self, watchdir_id):
|
||||||
watchdir_id = str(watchdir_id)
|
watchdir_id = str(watchdir_id)
|
||||||
self.watchdirs[watchdir_id]['enabled'] = False
|
# Disable the looping call
|
||||||
#disable the looping call here
|
if watchdir_id in self.update_timers:
|
||||||
self.update_timers[watchdir_id].stop()
|
if self.update_timers[watchdir_id].running:
|
||||||
del self.update_timers[watchdir_id]
|
self.update_timers[watchdir_id].stop()
|
||||||
self.config.save()
|
del self.update_timers[watchdir_id]
|
||||||
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
|
# Update the config
|
||||||
|
if self.watchdirs[watchdir_id]['enabled']:
|
||||||
|
self.watchdirs[watchdir_id]['enabled'] = False
|
||||||
|
self.config.save()
|
||||||
|
component.get("EventManager").emit(AutoaddOptionsChangedEvent())
|
||||||
|
|
||||||
@export
|
@export
|
||||||
def set_config(self, config):
|
def set_config(self, config):
|
||||||
"""sets the config dictionary"""
|
"""Sets the config dictionary."""
|
||||||
for key in config.keys():
|
for key in config.keys():
|
||||||
self.config[key] = config[key]
|
self.config[key] = config[key]
|
||||||
self.config.save()
|
self.config.save()
|
||||||
|
@ -282,7 +283,7 @@ class Core(CorePluginBase):
|
||||||
|
|
||||||
@export
|
@export
|
||||||
def get_config(self):
|
def get_config(self):
|
||||||
"""returns the config dictionary"""
|
"""Returns the config dictionary."""
|
||||||
return self.config.config
|
return self.config.config
|
||||||
|
|
||||||
@export()
|
@export()
|
||||||
|
@ -298,19 +299,16 @@ class Core(CorePluginBase):
|
||||||
value = str(value)
|
value = str(value)
|
||||||
opts[key] = value
|
opts[key] = value
|
||||||
return opts
|
return opts
|
||||||
|
|
||||||
#Labels:
|
|
||||||
@export()
|
@export()
|
||||||
def add(self, options={}):
|
def add(self, options={}):
|
||||||
"""add a watchdir
|
"""Add a watch folder."""
|
||||||
"""
|
|
||||||
options = self._clean_unicode(options)
|
options = self._clean_unicode(options)
|
||||||
abswatchdir = os.path.abspath(options['path'])
|
abswatchdir = os.path.abspath(options['path'])
|
||||||
CheckInput(os.path.isdir(abswatchdir) , _("Path does not exist."))
|
CheckInput(os.path.isdir(abswatchdir) , _("Path does not exist."))
|
||||||
CheckInput(os.access(abswatchdir, os.R_OK|os.W_OK), "You must have read and write access to watch folder.")
|
CheckInput(os.access(abswatchdir, os.R_OK|os.W_OK), "You must have read and write access to watch folder.")
|
||||||
for watchdir_id, watchdir in self.watchdirs.iteritems():
|
if abswatchdir in [wd['abspath'] for wd in self.watchdirs.itervalues()]:
|
||||||
if watchdir['abspath'] == abswatchdir:
|
raise Exception("Path is already being watched.")
|
||||||
raise Exception("Path is already being watched.")
|
|
||||||
options.setdefault('enabled', False)
|
options.setdefault('enabled', False)
|
||||||
options['abspath'] = abswatchdir
|
options['abspath'] = abswatchdir
|
||||||
watchdir_id = self.config['next_id']
|
watchdir_id = self.config['next_id']
|
||||||
|
@ -324,7 +322,7 @@ class Core(CorePluginBase):
|
||||||
|
|
||||||
@export
|
@export
|
||||||
def remove(self, watchdir_id):
|
def remove(self, watchdir_id):
|
||||||
"""remove a label"""
|
"""Remove a watch folder."""
|
||||||
watchdir_id = str(watchdir_id)
|
watchdir_id = str(watchdir_id)
|
||||||
CheckInput(watchdir_id in self.watchdirs, "Unknown Watchdir: %s" % self.watchdirs)
|
CheckInput(watchdir_id in self.watchdirs, "Unknown Watchdir: %s" % self.watchdirs)
|
||||||
if self.watchdirs[watchdir_id]['enabled']:
|
if self.watchdirs[watchdir_id]['enabled']:
|
||||||
|
|
|
@ -42,7 +42,7 @@ from setuptools import setup
|
||||||
__plugin_name__ = "AutoAdd"
|
__plugin_name__ = "AutoAdd"
|
||||||
__author__ = "Chase Sterling"
|
__author__ = "Chase Sterling"
|
||||||
__author_email__ = "chase.sterling@gmail.com"
|
__author_email__ = "chase.sterling@gmail.com"
|
||||||
__version__ = "1.01"
|
__version__ = "1.02"
|
||||||
__url__ = "http://forum.deluge-torrent.org/viewtopic.php?f=9&t=26775"
|
__url__ = "http://forum.deluge-torrent.org/viewtopic.php?f=9&t=26775"
|
||||||
__license__ = "GPLv3"
|
__license__ = "GPLv3"
|
||||||
__description__ = "Monitors folders for .torrent files."
|
__description__ = "Monitors folders for .torrent files."
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue