Big code clean-up in torrentmanager and torrent. This breaks
torrent.state. Sorry.
This commit is contained in:
parent
abbba8bf3b
commit
bf00795050
|
@ -65,6 +65,7 @@ DEFAULT_PREFS = {
|
||||||
"listen_ports": [6881, 6891],
|
"listen_ports": [6881, 6891],
|
||||||
"torrentfiles_location": os.path.join(deluge.configmanager.get_config_dir(), "torrentfiles"),
|
"torrentfiles_location": os.path.join(deluge.configmanager.get_config_dir(), "torrentfiles"),
|
||||||
"plugins_location": os.path.join(deluge.configmanager.get_config_dir(), "plugins"),
|
"plugins_location": os.path.join(deluge.configmanager.get_config_dir(), "plugins"),
|
||||||
|
"state_location": os.path.join(deluge.configmanager.get_config_dir(), "state"),
|
||||||
"prioritize_first_last_pieces": False,
|
"prioritize_first_last_pieces": False,
|
||||||
"random_port": True,
|
"random_port": True,
|
||||||
"dht": False,
|
"dht": False,
|
||||||
|
@ -88,7 +89,6 @@ DEFAULT_PREFS = {
|
||||||
"autoadd_location": "",
|
"autoadd_location": "",
|
||||||
"autoadd_enable": False,
|
"autoadd_enable": False,
|
||||||
"add_paused": False,
|
"add_paused": False,
|
||||||
"default_private": False,
|
|
||||||
"max_active_seeding": -1,
|
"max_active_seeding": -1,
|
||||||
"max_active_downloading": -1,
|
"max_active_downloading": -1,
|
||||||
"queue_new_to_top": False,
|
"queue_new_to_top": False,
|
||||||
|
@ -207,6 +207,8 @@ class Core(
|
||||||
# Register set functions in the Config
|
# Register set functions in the Config
|
||||||
self.config.register_set_function("torrentfiles_location",
|
self.config.register_set_function("torrentfiles_location",
|
||||||
self._on_set_torrentfiles_location)
|
self._on_set_torrentfiles_location)
|
||||||
|
self.config.register_set_function("state_location",
|
||||||
|
self._on_set_state_location)
|
||||||
self.config.register_set_function("listen_ports",
|
self.config.register_set_function("listen_ports",
|
||||||
self._on_set_listen_ports)
|
self._on_set_listen_ports)
|
||||||
self.config.register_set_function("random_port",
|
self.config.register_set_function("random_port",
|
||||||
|
@ -300,11 +302,30 @@ class Core(
|
||||||
"""Adds a torrent file to the libtorrent session
|
"""Adds a torrent file to the libtorrent session
|
||||||
This requires the torrents filename and a dump of it's content
|
This requires the torrents filename and a dump of it's content
|
||||||
"""
|
"""
|
||||||
# Make sure we are sending a string to add()
|
# Turn the filedump into a torrent_info
|
||||||
if not isinstance(filedump, str):
|
if not isinstance(filedump, str):
|
||||||
filedump = filedump.data
|
filedump = filedump.data
|
||||||
|
# filedump = "".join(chr(b) for b in filedump)
|
||||||
|
try:
|
||||||
|
torrent_info = lt.torrent_info(lt.bdecode(filedump))
|
||||||
|
except RuntimeError, e:
|
||||||
|
log.warn("Unable to decode torrent file: %s", e)
|
||||||
|
return None
|
||||||
|
|
||||||
torrent_id = self.torrents.add(filename, filedump=filedump, options=options)
|
torrent_id = self.torrents.add(torrent_info=torrent_info, options=options)
|
||||||
|
|
||||||
|
# Here we need to save a copy of the filedump for state purposes
|
||||||
|
# and also if the user wishes to save a copy of the torrent elsewhere.
|
||||||
|
if torrent_id:
|
||||||
|
# Write the .torrent file to the state directory
|
||||||
|
try:
|
||||||
|
save_file = open(os.path.join(self.config["state_location"],
|
||||||
|
torrent_id + ".torrent"),
|
||||||
|
"wb")
|
||||||
|
save_file.write(filedump)
|
||||||
|
save_file.close()
|
||||||
|
except IOError, e:
|
||||||
|
log.warning("Unable to save torrent file: %s", e)
|
||||||
|
|
||||||
# Run the plugin hooks for 'post_torrent_add'
|
# Run the plugin hooks for 'post_torrent_add'
|
||||||
self.plugins.run_post_torrent_add(torrent_id)
|
self.plugins.run_post_torrent_add(torrent_id)
|
||||||
|
@ -498,10 +519,6 @@ class Core(
|
||||||
"""Sets a torrents max download speed"""
|
"""Sets a torrents max download speed"""
|
||||||
return self.torrents[torrent_id].set_max_download_speed(value)
|
return self.torrents[torrent_id].set_max_download_speed(value)
|
||||||
|
|
||||||
def export_set_torrent_private_flag(self, torrent_id, value):
|
|
||||||
"""Sets a torrents private flag"""
|
|
||||||
return self.torrents[torrent_id].set_private_flag(value)
|
|
||||||
|
|
||||||
def export_set_torrent_file_priorities(self, torrent_id, priorities):
|
def export_set_torrent_file_priorities(self, torrent_id, priorities):
|
||||||
"""Sets a torrents file priorities"""
|
"""Sets a torrents file priorities"""
|
||||||
return self.torrents[torrent_id].set_file_priorities(priorities)
|
return self.torrents[torrent_id].set_file_priorities(priorities)
|
||||||
|
@ -637,6 +654,13 @@ class Core(
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
log.debug("Unable to copy file to %s: %s", value, e)
|
log.debug("Unable to copy file to %s: %s", value, e)
|
||||||
|
|
||||||
|
def _on_set_state_location(self, key, value):
|
||||||
|
if not os.access(value, os.F_OK):
|
||||||
|
try:
|
||||||
|
os.makedirs(value)
|
||||||
|
except Exception, e:
|
||||||
|
log.debug("Unable to make directory: %s", e)
|
||||||
|
|
||||||
def _on_set_listen_ports(self, key, value):
|
def _on_set_listen_ports(self, key, value):
|
||||||
# Only set the listen ports if random_port is not true
|
# Only set the listen ports if random_port is not true
|
||||||
if self.config["random_port"] is not True:
|
if self.config["random_port"] is not True:
|
||||||
|
|
|
@ -47,8 +47,7 @@ TORRENT_STATE = deluge.common.TORRENT_STATE
|
||||||
class Torrent:
|
class Torrent:
|
||||||
"""Torrent holds information about torrents added to the libtorrent session.
|
"""Torrent holds information about torrents added to the libtorrent session.
|
||||||
"""
|
"""
|
||||||
def __init__(self, filename, handle, compact, save_path, total_uploaded=0,
|
def __init__(self, handle, options, state=None):
|
||||||
trackers=None):
|
|
||||||
log.debug("Creating torrent object %s", str(handle.info_hash()))
|
log.debug("Creating torrent object %s", str(handle.info_hash()))
|
||||||
# Get the core config
|
# Get the core config
|
||||||
self.config = ConfigManager("core.conf")
|
self.config = ConfigManager("core.conf")
|
||||||
|
@ -57,40 +56,31 @@ class Torrent:
|
||||||
self.torrentqueue = component.get("TorrentQueue")
|
self.torrentqueue = component.get("TorrentQueue")
|
||||||
self.signals = component.get("SignalManager")
|
self.signals = component.get("SignalManager")
|
||||||
|
|
||||||
# Set the filename
|
|
||||||
self.filename = filename
|
|
||||||
# Set the libtorrent handle
|
# Set the libtorrent handle
|
||||||
self.handle = handle
|
self.handle = handle
|
||||||
# Set the torrent_id for this torrent
|
# Set the torrent_id for this torrent
|
||||||
self.torrent_id = str(handle.info_hash())
|
self.torrent_id = str(handle.info_hash())
|
||||||
# This is for saving the total uploaded between sessions
|
|
||||||
self.total_uploaded = total_uploaded
|
|
||||||
# Set the allocation mode
|
|
||||||
self.compact = compact
|
|
||||||
# Where the torrent is being saved to
|
|
||||||
self.save_path = save_path
|
|
||||||
# Status message holds error info about the torrent
|
|
||||||
self.statusmsg = "OK"
|
|
||||||
|
|
||||||
# The torrents state
|
|
||||||
self.state = ""
|
|
||||||
|
|
||||||
# Holds status info so that we don't need to keep getting it from lt
|
# Holds status info so that we don't need to keep getting it from lt
|
||||||
self.status = self.handle.status()
|
self.status = self.handle.status()
|
||||||
self.torrent_info = self.handle.get_torrent_info()
|
self.torrent_info = self.handle.get_torrent_info()
|
||||||
|
|
||||||
# Various torrent options
|
# Files dictionary
|
||||||
self.max_connections = -1
|
self.files = self.get_files()
|
||||||
self.max_upload_slots = -1
|
# Set the default file priorities to normal
|
||||||
self.max_upload_speed = -1
|
self.file_priorities = [1]* len(self.files)
|
||||||
self.max_download_speed = -1
|
|
||||||
self.private = False
|
|
||||||
self.prioritize_first_last = False
|
|
||||||
|
|
||||||
# The tracker status
|
# Default total_uploaded to 0, this may be changed by the state
|
||||||
self.tracker_status = ""
|
self.total_uploaded = 0
|
||||||
# Tracker list
|
|
||||||
if trackers == None:
|
# Load values from state if we have it
|
||||||
|
if state is not None:
|
||||||
|
# This is for saving the total uploaded between sessions
|
||||||
|
self.total_uploaded = state.total_uploaded
|
||||||
|
# Set the trackers
|
||||||
|
self.set_trackers(state.trackers)
|
||||||
|
else:
|
||||||
|
# Tracker list
|
||||||
self.trackers = []
|
self.trackers = []
|
||||||
# Create a list of trackers
|
# Create a list of trackers
|
||||||
for value in self.handle.trackers():
|
for value in self.handle.trackers():
|
||||||
|
@ -98,17 +88,33 @@ class Torrent:
|
||||||
tracker["url"] = value.url
|
tracker["url"] = value.url
|
||||||
tracker["tier"] = value.tier
|
tracker["tier"] = value.tier
|
||||||
self.trackers.append(tracker)
|
self.trackers.append(tracker)
|
||||||
else:
|
|
||||||
self.trackers = trackers
|
|
||||||
self.set_trackers(self.trackers)
|
|
||||||
|
|
||||||
# Files dictionary
|
# Various torrent options
|
||||||
self.files = self.get_files()
|
self.set_max_connections(options["max_connections_per_torrent"])
|
||||||
# Set the default file priorities to normal
|
self.set_max_upload_slots(options["max_upload_slots_per_torrent"])
|
||||||
self.file_priorities = [1]* len(self.files)
|
self.set_max_upload_speed(options["max_upload_speed_per_torrent"])
|
||||||
|
self.set_max_download_speed(options["max_download_speed_per_torrent"])
|
||||||
# Set resolve_countries to True
|
self.set_prioritize_first_last(options["prioritize_first_last_pieces"])
|
||||||
self.handle.resolve_countries(True)
|
self.handle.resolve_countries(True)
|
||||||
|
if options.has_key("file_priorities"):
|
||||||
|
self.set_file_priorities(options["file_priorities"])
|
||||||
|
|
||||||
|
# Set the allocation mode
|
||||||
|
self.compact = options["compact_allocation"]
|
||||||
|
# Where the torrent is being saved to
|
||||||
|
self.save_path = options["download_location"]
|
||||||
|
# Status message holds error info about the torrent
|
||||||
|
self.statusmsg = "OK"
|
||||||
|
|
||||||
|
# The torrents state
|
||||||
|
self.state = ""
|
||||||
|
|
||||||
|
# The tracker status
|
||||||
|
self.tracker_status = ""
|
||||||
|
|
||||||
|
# This variable is to prevent a state change to 'Paused' when it should
|
||||||
|
# be 'Queued'
|
||||||
|
self.next_pause_is_queued = False
|
||||||
|
|
||||||
log.debug("Torrent object created.")
|
log.debug("Torrent object created.")
|
||||||
|
|
||||||
|
@ -132,10 +138,6 @@ class Torrent:
|
||||||
self.max_download_speed = m_down_speed
|
self.max_download_speed = m_down_speed
|
||||||
self.handle.set_download_limit(int(m_down_speed * 1024))
|
self.handle.set_download_limit(int(m_down_speed * 1024))
|
||||||
|
|
||||||
def set_private_flag(self, private):
|
|
||||||
self.private = private
|
|
||||||
#self.handle.get_torrent_info().set_priv(private)
|
|
||||||
|
|
||||||
def set_prioritize_first_last(self, prioritize):
|
def set_prioritize_first_last(self, prioritize):
|
||||||
self.prioritize_first_last = prioritize
|
self.prioritize_first_last = prioritize
|
||||||
|
|
||||||
|
@ -156,6 +158,30 @@ class Torrent:
|
||||||
self.file_priorities = file_priorities
|
self.file_priorities = file_priorities
|
||||||
self.handle.prioritize_files(file_priorities)
|
self.handle.prioritize_files(file_priorities)
|
||||||
|
|
||||||
|
def set_trackers(self, trackers):
|
||||||
|
"""Sets trackers"""
|
||||||
|
if trackers == None:
|
||||||
|
trackers = []
|
||||||
|
|
||||||
|
log.debug("Setting trackers for %s: %s", self.torrent_id, trackers)
|
||||||
|
tracker_list = []
|
||||||
|
|
||||||
|
for tracker in trackers:
|
||||||
|
new_entry = lt.announce_entry(tracker["url"])
|
||||||
|
new_entry.tier = tracker["tier"]
|
||||||
|
tracker_list.append(new_entry)
|
||||||
|
|
||||||
|
self.handle.replace_trackers(tracker_list)
|
||||||
|
|
||||||
|
# Print out the trackers
|
||||||
|
for t in self.handle.trackers():
|
||||||
|
log.debug("tier: %s tracker: %s", t.tier, t.url)
|
||||||
|
# Set the tracker list in the torrent object
|
||||||
|
self.trackers = trackers
|
||||||
|
if len(trackers) > 0:
|
||||||
|
# Force a reannounce if there is at least 1 tracker
|
||||||
|
self.force_reannounce()
|
||||||
|
|
||||||
def set_state_based_on_ltstate(self):
|
def set_state_based_on_ltstate(self):
|
||||||
"""Updates the state based on what libtorrent's state for the torrent is"""
|
"""Updates the state based on what libtorrent's state for the torrent is"""
|
||||||
# Set the initial state based on the lt state
|
# Set the initial state based on the lt state
|
||||||
|
@ -183,8 +209,18 @@ class Torrent:
|
||||||
|
|
||||||
if state != self.state:
|
if state != self.state:
|
||||||
if state == "Queued" and not self.handle.is_paused():
|
if state == "Queued" and not self.handle.is_paused():
|
||||||
component.get("TorrentManager").append_not_state_paused(self.torrent_id)
|
#component.get("TorrentManager").append_not_state_paused(self.torrent_id)
|
||||||
|
self.next_pause_is_queued = True
|
||||||
self.handle.pause()
|
self.handle.pause()
|
||||||
|
if state == "Error" and not self.handle.is_paused():
|
||||||
|
self.next_pause_is_queued = True
|
||||||
|
|
||||||
|
if state == "Paused":
|
||||||
|
if self.next_pause_is_queued:
|
||||||
|
self.state = "Queued"
|
||||||
|
self.next_pause_is_queued = False
|
||||||
|
else:
|
||||||
|
self.state = "Paused"
|
||||||
|
|
||||||
log.debug("Setting %s's state to %s", self.torrent_id, state)
|
log.debug("Setting %s's state to %s", self.torrent_id, state)
|
||||||
self.state = state
|
self.state = state
|
||||||
|
@ -256,7 +292,6 @@ class Torrent:
|
||||||
def get_queue_position(self):
|
def get_queue_position(self):
|
||||||
# We augment the queue position + 1 so that the user sees a 1 indexed
|
# We augment the queue position + 1 so that the user sees a 1 indexed
|
||||||
# list.
|
# list.
|
||||||
|
|
||||||
return self.torrentqueue[self.torrent_id] + 1
|
return self.torrentqueue[self.torrent_id] + 1
|
||||||
|
|
||||||
def get_peers(self):
|
def get_peers(self):
|
||||||
|
@ -335,13 +370,13 @@ class Torrent:
|
||||||
"max_upload_speed": self.max_upload_speed,
|
"max_upload_speed": self.max_upload_speed,
|
||||||
"max_download_speed": self.max_download_speed,
|
"max_download_speed": self.max_download_speed,
|
||||||
"prioritize_first_last": self.prioritize_first_last,
|
"prioritize_first_last": self.prioritize_first_last,
|
||||||
"private": self.private,
|
|
||||||
"message": self.statusmsg,
|
"message": self.statusmsg,
|
||||||
"hash": self.torrent_id
|
"hash": self.torrent_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fns = {
|
fns = {
|
||||||
"name": self.torrent_info.name,
|
"name": self.torrent_info.name,
|
||||||
|
"private": self.torrent_info.priv,
|
||||||
"total_size": self.torrent_info.total_size,
|
"total_size": self.torrent_info.total_size,
|
||||||
"num_files": self.torrent_info.num_files,
|
"num_files": self.torrent_info.num_files,
|
||||||
"num_pieces": self.torrent_info.num_pieces,
|
"num_pieces": self.torrent_info.num_pieces,
|
||||||
|
@ -379,7 +414,6 @@ class Torrent:
|
||||||
self.handle.set_max_uploads(self.max_upload_slots)
|
self.handle.set_max_uploads(self.max_upload_slots)
|
||||||
self.handle.set_upload_limit(int(self.max_upload_speed * 1024))
|
self.handle.set_upload_limit(int(self.max_upload_speed * 1024))
|
||||||
self.handle.set_download_limit(int(self.max_download_speed * 1024))
|
self.handle.set_download_limit(int(self.max_download_speed * 1024))
|
||||||
self.handle.get_torrent_info().set_priv(self.private)
|
|
||||||
self.handle.prioritize_files(self.file_priorities)
|
self.handle.prioritize_files(self.file_priorities)
|
||||||
self.handle.resolve_countries(True)
|
self.handle.resolve_countries(True)
|
||||||
|
|
||||||
|
@ -472,8 +506,8 @@ class Torrent:
|
||||||
"""Writes the .fastresume file for the torrent"""
|
"""Writes the .fastresume file for the torrent"""
|
||||||
resume_data = lt.bencode(self.handle.write_resume_data())
|
resume_data = lt.bencode(self.handle.write_resume_data())
|
||||||
path = "%s/%s.fastresume" % (
|
path = "%s/%s.fastresume" % (
|
||||||
self.config["torrentfiles_location"],
|
self.config["state_location"],
|
||||||
self.filename)
|
self.torrent_id)
|
||||||
log.debug("Saving fastresume file: %s", path)
|
log.debug("Saving fastresume file: %s", path)
|
||||||
try:
|
try:
|
||||||
fastresume = open(path, "wb")
|
fastresume = open(path, "wb")
|
||||||
|
@ -485,14 +519,25 @@ class Torrent:
|
||||||
def delete_fastresume(self):
|
def delete_fastresume(self):
|
||||||
"""Deletes the .fastresume file"""
|
"""Deletes the .fastresume file"""
|
||||||
path = "%s/%s.fastresume" % (
|
path = "%s/%s.fastresume" % (
|
||||||
self.config["torrentfiles_location"],
|
self.config["state_location"],
|
||||||
self.filename)
|
self.torrent_id)
|
||||||
log.debug("Deleting fastresume file: %s", path)
|
log.debug("Deleting fastresume file: %s", path)
|
||||||
try:
|
try:
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
log.warning("Unable to delete the fastresume file: %s", e)
|
log.warning("Unable to delete the fastresume file: %s", e)
|
||||||
|
|
||||||
|
def delete_torrentfile(self):
|
||||||
|
"""Deletes the .torrent file in the state"""
|
||||||
|
path = "%s/%s.torrent" % (
|
||||||
|
self.config["state_location"],
|
||||||
|
self.torrent_id)
|
||||||
|
log.debug("Deleting torrent file: %s", path)
|
||||||
|
try:
|
||||||
|
os.remove(path)
|
||||||
|
except Exception, e:
|
||||||
|
log.warning("Unable to delete the torrent file: %s", e)
|
||||||
|
|
||||||
def force_reannounce(self):
|
def force_reannounce(self):
|
||||||
"""Force a tracker reannounce"""
|
"""Force a tracker reannounce"""
|
||||||
try:
|
try:
|
||||||
|
@ -512,52 +557,3 @@ class Torrent:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def set_trackers(self, trackers):
|
|
||||||
"""Sets trackers"""
|
|
||||||
if trackers == None:
|
|
||||||
trackers = []
|
|
||||||
|
|
||||||
log.debug("Setting trackers for %s: %s", self.torrent_id, trackers)
|
|
||||||
tracker_list = []
|
|
||||||
|
|
||||||
for tracker in trackers:
|
|
||||||
new_entry = lt.announce_entry(tracker["url"])
|
|
||||||
new_entry.tier = tracker["tier"]
|
|
||||||
tracker_list.append(new_entry)
|
|
||||||
|
|
||||||
self.handle.replace_trackers(tracker_list)
|
|
||||||
|
|
||||||
# Print out the trackers
|
|
||||||
for t in self.handle.trackers():
|
|
||||||
log.debug("tier: %s tracker: %s", t.tier, t.url)
|
|
||||||
# Set the tracker list in the torrent object
|
|
||||||
self.trackers = trackers
|
|
||||||
if len(trackers) > 0:
|
|
||||||
# Force a reannounce if there is at least 1 tracker
|
|
||||||
self.force_reannounce()
|
|
||||||
|
|
||||||
def save_torrent_file(self, filedump=None):
|
|
||||||
"""Saves a torrent file"""
|
|
||||||
log.debug("Attempting to save torrent file: %s", self.filename)
|
|
||||||
# Test if the torrentfiles_location is accessible
|
|
||||||
if os.access(
|
|
||||||
os.path.join(self.config["torrentfiles_location"]), os.F_OK) \
|
|
||||||
is False:
|
|
||||||
# The directory probably doesn't exist, so lets create it
|
|
||||||
try:
|
|
||||||
os.makedirs(os.path.join(self.config["torrentfiles_location"]))
|
|
||||||
except IOError, e:
|
|
||||||
log.warning("Unable to create torrent files directory: %s", e)
|
|
||||||
|
|
||||||
# Write the .torrent file to the torrent directory
|
|
||||||
try:
|
|
||||||
save_file = open(os.path.join(self.config["torrentfiles_location"],
|
|
||||||
self.filename),
|
|
||||||
"wb")
|
|
||||||
if filedump == None:
|
|
||||||
filedump = self.handle.get_torrent_info().create_torrent()
|
|
||||||
save_file.write(lt.bencode(filedump))
|
|
||||||
save_file.close()
|
|
||||||
except IOError, e:
|
|
||||||
log.warning("Unable to save torrent file: %s", e)
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ from deluge.log import LOG as log
|
||||||
class TorrentState:
|
class TorrentState:
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
torrent_id,
|
torrent_id,
|
||||||
filename,
|
|
||||||
total_uploaded,
|
total_uploaded,
|
||||||
trackers,
|
trackers,
|
||||||
compact,
|
compact,
|
||||||
|
@ -63,12 +62,10 @@ class TorrentState:
|
||||||
max_upload_speed,
|
max_upload_speed,
|
||||||
max_download_speed,
|
max_download_speed,
|
||||||
prioritize_first_last,
|
prioritize_first_last,
|
||||||
private,
|
|
||||||
file_priorities,
|
file_priorities,
|
||||||
queue
|
queue
|
||||||
):
|
):
|
||||||
self.torrent_id = torrent_id
|
self.torrent_id = torrent_id
|
||||||
self.filename = filename
|
|
||||||
self.total_uploaded = total_uploaded
|
self.total_uploaded = total_uploaded
|
||||||
self.trackers = trackers
|
self.trackers = trackers
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
|
@ -82,7 +79,6 @@ class TorrentState:
|
||||||
self.max_upload_speed = max_upload_speed
|
self.max_upload_speed = max_upload_speed
|
||||||
self.max_download_speed = max_download_speed
|
self.max_download_speed = max_download_speed
|
||||||
self.prioritize_first_last = prioritize_first_last
|
self.prioritize_first_last = prioritize_first_last
|
||||||
self.private = private
|
|
||||||
self.file_priorities = file_priorities
|
self.file_priorities = file_priorities
|
||||||
|
|
||||||
class TorrentManagerState:
|
class TorrentManagerState:
|
||||||
|
@ -109,9 +105,6 @@ class TorrentManager(component.Component):
|
||||||
# Create the torrents dict { torrent_id: Torrent }
|
# Create the torrents dict { torrent_id: Torrent }
|
||||||
self.torrents = {}
|
self.torrents = {}
|
||||||
|
|
||||||
# List of torrents to not set state 'Paused' on lt alert
|
|
||||||
self.not_state_paused = []
|
|
||||||
|
|
||||||
# Register set functions
|
# Register set functions
|
||||||
self.config.register_set_function("max_connections_per_torrent",
|
self.config.register_set_function("max_connections_per_torrent",
|
||||||
self.on_set_max_connections_per_torrent)
|
self.on_set_max_connections_per_torrent)
|
||||||
|
@ -173,80 +166,96 @@ class TorrentManager(component.Component):
|
||||||
"""Returns a list of torrent_ids"""
|
"""Returns a list of torrent_ids"""
|
||||||
return self.torrents.keys()
|
return self.torrents.keys()
|
||||||
|
|
||||||
def append_not_state_paused(self, torrent_id):
|
def get_torrent_info_from_file(self, filepath):
|
||||||
"""Appends to a list of torrents that we will not set state Paused to
|
"""Returns a torrent_info for the file specified or None"""
|
||||||
when we receive the paused alert from libtorrent. The torrents are removed
|
torrent_info = None
|
||||||
from this list once we receive the alert they have been paused in libtorrent."""
|
# Get the torrent data from the torrent file
|
||||||
if torrent_id not in self.not_state_paused:
|
try:
|
||||||
self.not_state_paused.append(torrent_id)
|
log.debug("Attempting to create torrent_info from %s", filepath)
|
||||||
|
_file = open(filepath, "rb")
|
||||||
|
torrent_info = lt.torrent_info(lt.bdecode(_file.read()))
|
||||||
|
_file.close()
|
||||||
|
except (IOError, RuntimeError), e:
|
||||||
|
log.warning("Unable to open %s: %s", filepath, e)
|
||||||
|
|
||||||
def add(self, filename, filedump=None, options=None, total_uploaded=0,
|
return torrent_info
|
||||||
trackers=None, queue=-1, state=None, save_state=True):
|
|
||||||
"""Add a torrent to the manager and returns it's torrent_id"""
|
|
||||||
log.info("Adding torrent: %s", filename)
|
|
||||||
log.debug("options: %s", options)
|
|
||||||
# Make sure 'filename' is a python string
|
|
||||||
filename = str(filename)
|
|
||||||
|
|
||||||
# Convert the filedump data array into a string of bytes
|
def get_resume_data_from_file(self, torrent_id):
|
||||||
if filedump is not None:
|
"""Returns an entry with the resume data or None"""
|
||||||
# If the filedump is already of type str, then it's already been
|
fastresume = None
|
||||||
# joined.
|
|
||||||
if type(filedump) is not str:
|
|
||||||
filedump = "".join(chr(b) for b in filedump)
|
|
||||||
try:
|
|
||||||
filedump = lt.bdecode(filedump)
|
|
||||||
except RuntimeError, e:
|
|
||||||
log.warn("Unable to decode torrent file: %s", e)
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
# Get the data from the file
|
|
||||||
filedump = self.load_torrent(filename)
|
|
||||||
if not filedump:
|
|
||||||
log.warning("Unable to load torrent file..")
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Attempt to load fastresume data
|
|
||||||
try:
|
try:
|
||||||
_file = open(
|
_file = open(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
self.config["torrentfiles_location"],
|
self.config["state_location"],
|
||||||
filename + ".fastresume"),
|
torrent_id + ".fastresume"),
|
||||||
"rb")
|
"rb")
|
||||||
try:
|
try:
|
||||||
fastresume = lt.bdecode(_file.read())
|
fastresume = lt.bdecode(_file.read())
|
||||||
except RuntimeError, e:
|
except RuntimeError, e:
|
||||||
log.warning("Unable to bdecode fastresume file: %s", e)
|
log.warning("Unable to bdecode fastresume file: %s", e)
|
||||||
fastresume = None
|
|
||||||
|
|
||||||
_file.close()
|
_file.close()
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
log.debug("Unable to load .fastresume: %s", e)
|
log.debug("Unable to load .fastresume: %s", e)
|
||||||
fastresume = None
|
|
||||||
|
|
||||||
handle = None
|
return fastresume
|
||||||
|
|
||||||
# Check if options is None and load defaults
|
def add(self, torrent_info=None, state=None, options=None, save_state=True):
|
||||||
options_keys = [
|
"""Add a torrent to the manager and returns it's torrent_id"""
|
||||||
"compact_allocation",
|
if torrent_info is None and state is None:
|
||||||
"max_connections_per_torrent",
|
log.debug("You must specify a valid torrent_info or a torrent state object!")
|
||||||
"max_upload_slots_per_torrent",
|
return
|
||||||
"max_upload_speed_per_torrent",
|
|
||||||
"max_download_speed_per_torrent",
|
|
||||||
"prioritize_first_last_pieces",
|
|
||||||
"download_location",
|
|
||||||
"add_paused",
|
|
||||||
"default_private"
|
|
||||||
]
|
|
||||||
|
|
||||||
if options == None:
|
log.debug("torrentmanager.add")
|
||||||
|
add_torrent_params = {}
|
||||||
|
|
||||||
|
if torrent_info is None:
|
||||||
|
# We have no torrent_info so we need to add the torrent with information
|
||||||
|
# from the state object.
|
||||||
|
|
||||||
|
# Populate the options dict from state
|
||||||
options = {}
|
options = {}
|
||||||
for key in options_keys:
|
options["max_connections_per_torrent"] = state.max_connections
|
||||||
options[key] = self.config[key]
|
options["max_upload_slots_per_torrent"] = state.max_upload_slots
|
||||||
|
options["max_upload_speed_per_torrent"] = state.max_upload_speed
|
||||||
|
options["max_download_speed_per_torrent"] = state.max_download_speed
|
||||||
|
options["prioritize_first_last_pieces"] = state.prioritize_first_last
|
||||||
|
options["file_priorities"] = state.file_priorities
|
||||||
|
options["compact_allocation"] = state.compact
|
||||||
|
options["download_location"] = state.save_path
|
||||||
|
|
||||||
|
add_torrent_params["ti"] =\
|
||||||
|
self.get_torrent_info_from_file(
|
||||||
|
os.path.join(self.config["state_location"], state.torrent_id + ".torrent"))
|
||||||
|
add_torrent_params["resume_data"] = self.get_resume_data_from_file(state.torrent_id)
|
||||||
else:
|
else:
|
||||||
for key in options_keys:
|
# We have a torrent_info object so we're not loading from state.
|
||||||
if not options.has_key(key):
|
# Check if options is None and load defaults
|
||||||
|
options_keys = [
|
||||||
|
"compact_allocation",
|
||||||
|
"max_connections_per_torrent",
|
||||||
|
"max_upload_slots_per_torrent",
|
||||||
|
"max_upload_speed_per_torrent",
|
||||||
|
"max_download_speed_per_torrent",
|
||||||
|
"prioritize_first_last_pieces",
|
||||||
|
"download_location",
|
||||||
|
"add_paused",
|
||||||
|
]
|
||||||
|
|
||||||
|
if options == None:
|
||||||
|
options = {}
|
||||||
|
for key in options_keys:
|
||||||
options[key] = self.config[key]
|
options[key] = self.config[key]
|
||||||
|
else:
|
||||||
|
for key in options_keys:
|
||||||
|
if not options.has_key(key):
|
||||||
|
options[key] = self.config[key]
|
||||||
|
|
||||||
|
add_torrent_params["ti"] = torrent_info
|
||||||
|
add_torrent_params["resume_data"] = None
|
||||||
|
|
||||||
|
#log.info("Adding torrent: %s", filename)
|
||||||
|
log.debug("options: %s", options)
|
||||||
|
|
||||||
# Set the right storage_mode
|
# Set the right storage_mode
|
||||||
if options["compact_allocation"]:
|
if options["compact_allocation"]:
|
||||||
|
@ -254,23 +263,21 @@ class TorrentManager(component.Component):
|
||||||
else:
|
else:
|
||||||
storage_mode = lt.storage_mode_t(1)
|
storage_mode = lt.storage_mode_t(1)
|
||||||
|
|
||||||
|
# Fill in the rest of the add_torrent_params dictionary
|
||||||
|
add_torrent_params["save_path"] = str(options["download_location"])
|
||||||
|
|
||||||
|
add_torrent_params["storage_mode"] = storage_mode
|
||||||
|
add_torrent_params["paused"] = True
|
||||||
|
add_torrent_params["auto_managed"] = False
|
||||||
|
add_torrent_params["duplicate_is_error"] = True
|
||||||
|
|
||||||
# We need to pause the AlertManager momentarily to prevent alerts
|
# We need to pause the AlertManager momentarily to prevent alerts
|
||||||
# for this torrent being generated before a Torrent object is created.
|
# for this torrent being generated before a Torrent object is created.
|
||||||
component.pause("AlertManager")
|
component.pause("AlertManager")
|
||||||
|
|
||||||
# Create the torrent parameters struct for the torrent's options
|
handle = None
|
||||||
t_params = {}
|
|
||||||
|
|
||||||
t_params["ti"] = lt.torrent_info(filedump)
|
|
||||||
t_params["save_path"] = str(options["download_location"])
|
|
||||||
t_params["resume_data"] = fastresume
|
|
||||||
t_params["storage_mode"] = storage_mode
|
|
||||||
t_params["paused"] = True
|
|
||||||
t_params["auto_managed"] = False
|
|
||||||
t_params["duplicate_is_error"] = True
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
handle = self.session.add_torrent(t_params)
|
handle = self.session.add_torrent(add_torrent_params)
|
||||||
except RuntimeError, e:
|
except RuntimeError, e:
|
||||||
log.warning("Error adding torrent: %s", e)
|
log.warning("Error adding torrent: %s", e)
|
||||||
|
|
||||||
|
@ -278,76 +285,59 @@ class TorrentManager(component.Component):
|
||||||
log.debug("torrent handle is invalid!")
|
log.debug("torrent handle is invalid!")
|
||||||
# The torrent was not added to the session
|
# The torrent was not added to the session
|
||||||
component.resume("AlertManager")
|
component.resume("AlertManager")
|
||||||
return None
|
return
|
||||||
|
|
||||||
|
log.debug("handle id: %s", str(handle.info_hash()))
|
||||||
# Create a Torrent object
|
# Create a Torrent object
|
||||||
torrent = Torrent(filename, handle, options["compact_allocation"],
|
torrent = Torrent(handle, options, state)
|
||||||
options["download_location"], total_uploaded, trackers)
|
|
||||||
# Add the torrent object to the dictionary
|
# Add the torrent object to the dictionary
|
||||||
self.torrents[torrent.torrent_id] = torrent
|
self.torrents[torrent.torrent_id] = torrent
|
||||||
component.resume("AlertManager")
|
component.resume("AlertManager")
|
||||||
|
|
||||||
# Add the torrent to the queue
|
# Add the torrent to the queue
|
||||||
if queue == -1 and self.config["queue_new_to_top"]:
|
if state is not None:
|
||||||
self.queue.insert(0, torrent.torrent_id)
|
self.queue.insert(state.queue, torrent.torrent_id)
|
||||||
else:
|
else:
|
||||||
self.queue.insert(queue, torrent.torrent_id)
|
if self.config["queue_new_to_top"]:
|
||||||
|
self.queue.insert(0, torrent.torrent_id)
|
||||||
# Set per-torrent options
|
else:
|
||||||
torrent.set_max_connections(options["max_connections_per_torrent"])
|
self.queue.append(torrent.torrent_id)
|
||||||
torrent.set_max_upload_slots(options["max_upload_slots_per_torrent"])
|
|
||||||
torrent.set_max_upload_speed(options["max_upload_speed_per_torrent"])
|
|
||||||
torrent.set_max_download_speed(
|
|
||||||
options["max_download_speed_per_torrent"])
|
|
||||||
torrent.set_prioritize_first_last(
|
|
||||||
options["prioritize_first_last_pieces"])
|
|
||||||
torrent.set_private_flag(options["default_private"])
|
|
||||||
|
|
||||||
if options.has_key("file_priorities"):
|
|
||||||
if options["file_priorities"] != None:
|
|
||||||
log.debug("set file priorities: %s", options["file_priorities"])
|
|
||||||
torrent.set_file_priorities(options["file_priorities"])
|
|
||||||
|
|
||||||
log.debug("state: %s", state)
|
log.debug("state: %s", state)
|
||||||
|
|
||||||
# Resume the torrent if needed
|
# Resume the torrent if needed
|
||||||
if state == "Queued":
|
if state == "Paused" or state == "Error":
|
||||||
torrent.state = "Queued"
|
|
||||||
elif state == "Paused" or state == "Error":
|
|
||||||
torrent.state = "Paused"
|
torrent.state = "Paused"
|
||||||
if state == None and not options["add_paused"]:
|
elif state == None and not options["add_paused"]:
|
||||||
torrent.handle.resume()
|
torrent.handle.resume()
|
||||||
# We set the state based on libtorrent's state
|
# We set the state based on libtorrent's state
|
||||||
torrent.set_state_based_on_ltstate()
|
torrent.set_state_based_on_ltstate()
|
||||||
if state == None and options["add_paused"]:
|
elif state == None and options["add_paused"]:
|
||||||
torrent.set_state = "Paused"
|
torrent.set_state = "Paused"
|
||||||
|
|
||||||
# Emit the torrent_added signal
|
|
||||||
self.signals.emit("torrent_added", torrent.torrent_id)
|
|
||||||
|
|
||||||
# Save the torrent file
|
|
||||||
torrent.save_torrent_file(filedump)
|
|
||||||
|
|
||||||
if save_state:
|
if save_state:
|
||||||
# Save the session state
|
# Save the session state
|
||||||
self.save_state()
|
self.save_state()
|
||||||
|
|
||||||
|
# Emit the torrent_added signal
|
||||||
|
self.signals.emit("torrent_added", torrent.torrent_id)
|
||||||
|
|
||||||
return torrent.torrent_id
|
return torrent.torrent_id
|
||||||
|
|
||||||
def load_torrent(self, filename):
|
def load_torrent(self, torrent_id):
|
||||||
"""Load a torrent file and return it's torrent info"""
|
"""Load a torrent file from state and return it's torrent info"""
|
||||||
filedump = None
|
filedump = None
|
||||||
# Get the torrent data from the torrent file
|
# Get the torrent data from the torrent file
|
||||||
try:
|
try:
|
||||||
log.debug("Attempting to open %s for add.", filename)
|
log.debug("Attempting to open %s for add.", torrent_id)
|
||||||
_file = open(
|
_file = open(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
self.config["torrentfiles_location"], filename),
|
self.config["state_location"], torrent_id + ".torrent"),
|
||||||
"rb")
|
"rb")
|
||||||
filedump = lt.bdecode(_file.read())
|
filedump = lt.bdecode(_file.read())
|
||||||
_file.close()
|
_file.close()
|
||||||
except (IOError, RuntimeError), e:
|
except (IOError, RuntimeError), e:
|
||||||
log.warning("Unable to open %s: %s", filename, e)
|
log.warning("Unable to open %s: %s", torrent_id, e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return filedump
|
return filedump
|
||||||
|
@ -379,6 +369,9 @@ class TorrentManager(component.Component):
|
||||||
# Remove the .fastresume if it exists
|
# Remove the .fastresume if it exists
|
||||||
self.torrents[torrent_id].delete_fastresume()
|
self.torrents[torrent_id].delete_fastresume()
|
||||||
|
|
||||||
|
# Remove the .torrent file in the state
|
||||||
|
self.torrents[torrent_id].delete_torrentfile()
|
||||||
|
|
||||||
# Remove the torrent from the queue
|
# Remove the torrent from the queue
|
||||||
self.queue.remove(torrent_id)
|
self.queue.remove(torrent_id)
|
||||||
|
|
||||||
|
@ -417,15 +410,12 @@ class TorrentManager(component.Component):
|
||||||
|
|
||||||
def force_recheck(self, torrent_id):
|
def force_recheck(self, torrent_id):
|
||||||
"""Forces a re-check of the torrent's data"""
|
"""Forces a re-check of the torrent's data"""
|
||||||
|
log.debug("force recheck is broken for the time being")
|
||||||
|
return
|
||||||
log.debug("Doing a forced recheck on %s", torrent_id)
|
log.debug("Doing a forced recheck on %s", torrent_id)
|
||||||
torrent = self.torrents[torrent_id]
|
torrent = self.torrents[torrent_id]
|
||||||
paused = self.torrents[torrent_id].handle.is_paused()
|
paused = self.torrents[torrent_id].handle.is_paused()
|
||||||
torrent_info = None
|
torrent_info = torrent.handle.get_torrent_info()
|
||||||
### Check for .torrent file prior to removing and make a copy if needed
|
|
||||||
if os.access(os.path.join(self.config["torrentfiles_location"] +\
|
|
||||||
"/" + torrent.filename), os.F_OK) is False:
|
|
||||||
torrent_info = torrent.handle.get_torrent_info().create_torrent()
|
|
||||||
torrent.save_torrent_file()
|
|
||||||
|
|
||||||
# We need to pause the AlertManager momentarily to prevent alerts
|
# We need to pause the AlertManager momentarily to prevent alerts
|
||||||
# for this torrent being generated before a Torrent object is created.
|
# for this torrent being generated before a Torrent object is created.
|
||||||
|
@ -439,11 +429,11 @@ class TorrentManager(component.Component):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Remove the fastresume file if there
|
# Remove the fastresume file if there
|
||||||
torrent.delete_fastresume()
|
#torrent.delete_fastresume()
|
||||||
|
|
||||||
# Load the torrent info from file if needed
|
# Load the torrent info from file if needed
|
||||||
if torrent_info == None:
|
if torrent_info == None:
|
||||||
torrent_info = self.load_torrent(torrent.filename)
|
torrent_info = self.load_torrent(torrent.torrent_id)
|
||||||
|
|
||||||
# Next we re-add the torrent
|
# Next we re-add the torrent
|
||||||
|
|
||||||
|
@ -489,7 +479,7 @@ class TorrentManager(component.Component):
|
||||||
try:
|
try:
|
||||||
log.debug("Opening torrent state file for load.")
|
log.debug("Opening torrent state file for load.")
|
||||||
state_file = open(
|
state_file = open(
|
||||||
os.path.join(self.config["config_location"], "torrents.state"), "rb")
|
os.path.join(self.config["state_location"], "torrents.state"), "rb")
|
||||||
state = cPickle.load(state_file)
|
state = cPickle.load(state_file)
|
||||||
state_file.close()
|
state_file.close()
|
||||||
except IOError:
|
except IOError:
|
||||||
|
@ -506,37 +496,20 @@ class TorrentManager(component.Component):
|
||||||
fr_first = []
|
fr_first = []
|
||||||
for torrent_state in state.torrents:
|
for torrent_state in state.torrents:
|
||||||
if os.path.exists(os.path.join(
|
if os.path.exists(os.path.join(
|
||||||
self.config["torrentfiles_location"],
|
self.config["state_location"],
|
||||||
torrent_state.filename, ".fastresume")):
|
torrent_state.torrent_id, ".fastresume")):
|
||||||
fr_first.insert(0, torrent_state)
|
fr_first.insert(0, torrent_state)
|
||||||
else:
|
else:
|
||||||
fr_first.append(torrent_state)
|
fr_first.append(torrent_state)
|
||||||
|
|
||||||
for torrent_state in fr_first:
|
for torrent_state in fr_first:
|
||||||
try:
|
try:
|
||||||
options = {
|
|
||||||
"compact_allocation": torrent_state.compact,
|
|
||||||
"max_connections_per_torrent": torrent_state.max_connections,
|
|
||||||
"max_upload_slots_per_torrent": torrent_state.max_upload_slots,
|
|
||||||
"max_upload_speed_per_torrent": torrent_state.max_upload_speed,
|
|
||||||
"max_download_speed_per_torrent": torrent_state.max_download_speed,
|
|
||||||
"prioritize_first_last_pieces": torrent_state.prioritize_first_last,
|
|
||||||
"download_location": torrent_state.save_path,
|
|
||||||
"add_paused": True,
|
|
||||||
"default_private": torrent_state.private,
|
|
||||||
"file_priorities": torrent_state.file_priorities
|
|
||||||
}
|
|
||||||
# We need to resume all non-add_paused torrents after plugin hook
|
# We need to resume all non-add_paused torrents after plugin hook
|
||||||
if torrent_state.state not in ["Paused", "Queued", "Error"]:
|
if torrent_state.state not in ["Paused", "Queued", "Error"]:
|
||||||
resume_torrents.append(torrent_state.torrent_id)
|
resume_torrents.append(torrent_state.torrent_id)
|
||||||
|
|
||||||
self.add(
|
self.add(
|
||||||
torrent_state.filename,
|
state=torrent_state,
|
||||||
options=options,
|
|
||||||
total_uploaded=torrent_state.total_uploaded,
|
|
||||||
trackers=torrent_state.trackers,
|
|
||||||
queue=torrent_state.queue,
|
|
||||||
state=torrent_state.state,
|
|
||||||
save_state=False)
|
save_state=False)
|
||||||
|
|
||||||
except AttributeError, e:
|
except AttributeError, e:
|
||||||
|
@ -559,7 +532,6 @@ class TorrentManager(component.Component):
|
||||||
for torrent in self.torrents.values():
|
for torrent in self.torrents.values():
|
||||||
torrent_state = TorrentState(
|
torrent_state = TorrentState(
|
||||||
torrent.torrent_id,
|
torrent.torrent_id,
|
||||||
torrent.filename,
|
|
||||||
torrent.get_status(["total_uploaded"])["total_uploaded"],
|
torrent.get_status(["total_uploaded"])["total_uploaded"],
|
||||||
torrent.trackers,
|
torrent.trackers,
|
||||||
torrent.compact,
|
torrent.compact,
|
||||||
|
@ -570,7 +542,6 @@ class TorrentManager(component.Component):
|
||||||
torrent.max_upload_speed,
|
torrent.max_upload_speed,
|
||||||
torrent.max_download_speed,
|
torrent.max_download_speed,
|
||||||
torrent.prioritize_first_last,
|
torrent.prioritize_first_last,
|
||||||
torrent.private,
|
|
||||||
torrent.file_priorities,
|
torrent.file_priorities,
|
||||||
torrent.get_status(["queue"])["queue"] - 1 # We subtract 1 due to augmentation
|
torrent.get_status(["queue"])["queue"] - 1 # We subtract 1 due to augmentation
|
||||||
)
|
)
|
||||||
|
@ -580,7 +551,7 @@ class TorrentManager(component.Component):
|
||||||
try:
|
try:
|
||||||
log.debug("Saving torrent state file.")
|
log.debug("Saving torrent state file.")
|
||||||
state_file = open(
|
state_file = open(
|
||||||
os.path.join(self.config["config_location"], "torrents.state"),
|
os.path.join(self.config["state_location"], "torrents.state"),
|
||||||
"wb")
|
"wb")
|
||||||
cPickle.dump(state, state_file)
|
cPickle.dump(state, state_file)
|
||||||
state_file.close()
|
state_file.close()
|
||||||
|
@ -640,13 +611,9 @@ class TorrentManager(component.Component):
|
||||||
# Get the torrent_id
|
# Get the torrent_id
|
||||||
torrent_id = str(alert.handle.info_hash())
|
torrent_id = str(alert.handle.info_hash())
|
||||||
# Set the torrent state
|
# Set the torrent state
|
||||||
log.debug("not_state_paused: %s", self.not_state_paused)
|
log.debug("Setting state 'Paused'..")
|
||||||
if not torrent_id in self.not_state_paused:
|
self.torrents[torrent_id].set_state("Paused")
|
||||||
log.debug("Setting state 'Paused'..")
|
component.get("SignalManager").emit("torrent_paused", torrent_id)
|
||||||
self.torrents[torrent_id].set_state("Paused")
|
|
||||||
component.get("SignalManager").emit("torrent_paused", torrent_id)
|
|
||||||
else:
|
|
||||||
self.not_state_paused.remove(torrent_id)
|
|
||||||
|
|
||||||
# Write the fastresume file
|
# Write the fastresume file
|
||||||
self.torrents[torrent_id].write_fastresume()
|
self.torrents[torrent_id].write_fastresume()
|
||||||
|
@ -731,4 +698,4 @@ class TorrentManager(component.Component):
|
||||||
torrent_id = str(alert.handle.info_hash())
|
torrent_id = str(alert.handle.info_hash())
|
||||||
self.torrents[torrent_id].set_state("Error")
|
self.torrents[torrent_id].set_state("Error")
|
||||||
self.torrents[torrent_id].set_status_message(str(alert.msg()))
|
self.torrents[torrent_id].set_status_message(str(alert.msg()))
|
||||||
self.not_state_paused.append(torrent_id)
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ class TorrentQueue(component.Component):
|
||||||
try:
|
try:
|
||||||
return self.queue.index(torrent_id)
|
return self.queue.index(torrent_id)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return None
|
return -1
|
||||||
|
|
||||||
def append(self, torrent_id):
|
def append(self, torrent_id):
|
||||||
"""Append torrent_id to the bottom of the queue"""
|
"""Append torrent_id to the bottom of the queue"""
|
||||||
|
|
Loading…
Reference in New Issue