Fix up some commands
This commit is contained in:
parent
9da95552f3
commit
c17af41940
|
@ -50,6 +50,15 @@ schemes = {
|
||||||
"event": ("magenta", "black", "bold")
|
"event": ("magenta", "black", "bold")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Colors for various torrent states
|
||||||
|
state_color = {
|
||||||
|
"Seeding": "{{blue,black,bold}}",
|
||||||
|
"Downloading": "{{green,black,bold}}",
|
||||||
|
"Paused": "{{white,black}}",
|
||||||
|
"Checking": "{{green,black}}",
|
||||||
|
"Queued": "{{yellow,black}}",
|
||||||
|
"Error": "{{red,black,bold}}"
|
||||||
|
}
|
||||||
|
|
||||||
def init_colors():
|
def init_colors():
|
||||||
# Create the color_pairs dict
|
# Create the color_pairs dict
|
||||||
|
@ -65,6 +74,19 @@ def init_colors():
|
||||||
class BadColorString(Exception):
|
class BadColorString(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_line_length(line):
|
||||||
|
"""
|
||||||
|
Returns the string length without the color formatting.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if line.count("{{") != line.count ("}}"):
|
||||||
|
raise BadColorString("Number of {{ does not equal number of }}")
|
||||||
|
|
||||||
|
while line.find("{{") != -1:
|
||||||
|
line = line[:line.find("{{")] + line[line.find("}}") + 2:]
|
||||||
|
|
||||||
|
return len(line)
|
||||||
|
|
||||||
def parse_color_string(s):
|
def parse_color_string(s):
|
||||||
"""
|
"""
|
||||||
Parses a string and returns a list of 2-tuples (color, string).
|
Parses a string and returns a list of 2-tuples (color, string).
|
||||||
|
@ -72,6 +94,9 @@ def parse_color_string(s):
|
||||||
:param s:, string to parse
|
:param s:, string to parse
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if s.count("{{") != s.count ("}}"):
|
||||||
|
raise BadColorString("Number of {{ does not equal number of }}")
|
||||||
|
|
||||||
ret = []
|
ret = []
|
||||||
# Keep track of where the strings
|
# Keep track of where the strings
|
||||||
col_index = 0
|
col_index = 0
|
||||||
|
|
|
@ -22,10 +22,11 @@
|
||||||
# 51 Franklin Street, Fifth Floor
|
# 51 Franklin Street, Fifth Floor
|
||||||
# Boston, MA 02110-1301, USA.
|
# Boston, MA 02110-1301, USA.
|
||||||
#
|
#
|
||||||
from deluge.ui.console.main import BaseCommand, match_torrents
|
from deluge.ui.console.main import BaseCommand
|
||||||
from deluge.ui.console import mapping
|
|
||||||
import deluge.ui.console.colors as colors
|
import deluge.ui.console.colors as colors
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
|
import deluge.component as component
|
||||||
|
|
||||||
from optparse import make_option
|
from optparse import make_option
|
||||||
import os
|
import os
|
||||||
import base64
|
import base64
|
||||||
|
@ -40,18 +41,20 @@ class Command(BaseCommand):
|
||||||
usage = "Usage: add [-p <save-location>] <torrent-file> [<torrent-file> ...]"
|
usage = "Usage: add [-p <save-location>] <torrent-file> [<torrent-file> ...]"
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
self.console = component.get("ConsoleUI")
|
||||||
|
|
||||||
t_options = {}
|
t_options = {}
|
||||||
if options["path"]:
|
if options["path"]:
|
||||||
t_options["download_location"] = options["path"]
|
t_options["download_location"] = options["path"]
|
||||||
|
|
||||||
for arg in args:
|
for arg in args:
|
||||||
self.write("{{info}}Attempting to add torrent: %s" % arg)
|
self.console.write("{{info}}Attempting to add torrent: %s" % arg)
|
||||||
filename = os.path.split(arg)[-1]
|
filename = os.path.split(arg)[-1]
|
||||||
filedump = base64.encodestring(open(arg).read())
|
filedump = base64.encodestring(open(arg).read())
|
||||||
|
|
||||||
def on_success(result):
|
def on_success(result):
|
||||||
self.write("{{success}}Torrent added!")
|
self.console.write("{{success}}Torrent added!")
|
||||||
def on_fail(result):
|
def on_fail(result):
|
||||||
self.write("{{error}}Torrent was not added! %s" % result)
|
self.console.write("{{error}}Torrent was not added! %s" % result)
|
||||||
|
|
||||||
client.core.add_torrent_file(filename, filedump, t_options).addCallback(on_success).addErrback(on_fail)
|
client.core.add_torrent_file(filename, filedump, t_options).addCallback(on_success).addErrback(on_fail)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
#
|
||||||
# connect.py
|
# connect.py
|
||||||
#
|
#
|
||||||
|
@ -25,17 +24,20 @@
|
||||||
from deluge.ui.console.main import BaseCommand
|
from deluge.ui.console.main import BaseCommand
|
||||||
import deluge.ui.console.colors as colors
|
import deluge.ui.console.colors as colors
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
|
import deluge.component as component
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
"""Connect to a new deluge server."""
|
"""Connect to a new deluge server."""
|
||||||
def handle(self, host='localhost', port='58846', username="", password="", **options):
|
def handle(self, host="", port="58846", username="", password="", **options):
|
||||||
|
self.console = component.get("ConsoleUI")
|
||||||
|
|
||||||
port = int(port)
|
port = int(port)
|
||||||
d = client.connect(host, port, username, password)
|
d = client.connect(host, port, username, password)
|
||||||
def on_connect(result):
|
def on_connect(result):
|
||||||
print templates.SUCCESS('Connected to %s:%d!' % (host, port))
|
self.console.write("{{success}}Connected to %s:%s!" % (host, port))
|
||||||
|
|
||||||
def on_connect_fail(result):
|
def on_connect_fail(result):
|
||||||
print templates.ERROR("Failed to connect to %s:%d!" % (host, port))
|
self.console.write("{{error}}Failed to connect to %s:%s!" % (host, port))
|
||||||
|
|
||||||
d.addCallback(on_connect)
|
d.addCallback(on_connect)
|
||||||
d.addErrback(on_connect_fail)
|
d.addErrback(on_connect_fail)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
#
|
||||||
# halt.py
|
# halt.py
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
||||||
|
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
|
||||||
#
|
#
|
||||||
# Deluge is free software.
|
# Deluge is free software.
|
||||||
#
|
#
|
||||||
|
@ -22,12 +22,20 @@
|
||||||
# 51 Franklin Street, Fifth Floor
|
# 51 Franklin Street, Fifth Floor
|
||||||
# Boston, MA 02110-1301, USA.
|
# Boston, MA 02110-1301, USA.
|
||||||
#
|
#
|
||||||
from deluge.ui.console.main import BaseCommand, match_torrents
|
from deluge.ui.console.main import BaseCommand
|
||||||
from deluge.ui.console import mapping
|
|
||||||
import deluge.ui.console.colors as colors
|
import deluge.ui.console.colors as colors
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
|
import deluge.component as component
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
"Shutdown the deluge server."
|
"Shutdown the deluge server."
|
||||||
def handle(self, **options):
|
def handle(self, **options):
|
||||||
client.daemon.shutdown(None)
|
self.console = component.get("ConsoleUI")
|
||||||
|
|
||||||
|
def on_shutdown(result):
|
||||||
|
self.write("{{success}}Daemon was shutdown")
|
||||||
|
|
||||||
|
def on_shutdown_fail(reason):
|
||||||
|
self.write("{{error}}Unable to shutdown daemon: %s" % reason)
|
||||||
|
|
||||||
|
client.daemon.shutdown().addCallback(on_shutdown).addErrback(on_shutdown_fail)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
#
|
||||||
# help.py
|
# help.py
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
||||||
|
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
|
||||||
#
|
#
|
||||||
# Deluge is free software.
|
# Deluge is free software.
|
||||||
#
|
#
|
||||||
|
@ -22,46 +22,44 @@
|
||||||
# 51 Franklin Street, Fifth Floor
|
# 51 Franklin Street, Fifth Floor
|
||||||
# Boston, MA 02110-1301, USA.
|
# Boston, MA 02110-1301, USA.
|
||||||
#
|
#
|
||||||
from deluge.ui.console import UI_PATH
|
from deluge.ui.console.main import BaseCommand
|
||||||
from deluge.ui.console.main import BaseCommand, load_commands
|
|
||||||
import deluge.ui.console.colors as colors
|
import deluge.ui.console.colors as colors
|
||||||
#from deluge.ui.console.colors import templates
|
import deluge.component as component
|
||||||
import os
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
"""displays help on other commands"""
|
"""displays help on other commands"""
|
||||||
|
|
||||||
usage = "Usage: help [command]"
|
usage = "Usage: help [command]"
|
||||||
|
|
||||||
def __init__(self):
|
# def __init__(self):
|
||||||
BaseCommand.__init__(self)
|
# BaseCommand.__init__(self)
|
||||||
# get a list of commands, exclude 'help' so we won't run into a recursive loop.
|
# get a list of commands, exclude 'help' so we won't run into a recursive loop.
|
||||||
self._commands = load_commands(os.path.join(UI_PATH,'commands'), None, exclude=['help'])
|
#self._commands = load_commands(os.path.join(UI_PATH,'commands'), None, exclude=['help'])
|
||||||
self._commands['help'] = self
|
|
||||||
|
# self._commands['help'] = self
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
self.console = component.get("ConsoleUI")
|
||||||
|
self._commands = self.console._commands
|
||||||
if args:
|
if args:
|
||||||
if len(args) > 1:
|
if len(args) > 1:
|
||||||
#print usage
|
#print usage
|
||||||
self.write(usage)
|
self.console.write(usage)
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
cmd = self._commands[args[0]]
|
cmd = self._commands[args[0]]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
#print templates.ERROR('unknown command %r' % args[0])
|
#print templates.ERROR('unknown command %r' % args[0])
|
||||||
self.write("{{error}}Unknown command %r" % args[0])
|
self.console.write("{{error}}Unknown command %r" % args[0])
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
parser = cmd.create_parser()
|
parser = cmd.create_parser()
|
||||||
self.write(parser.format_help())
|
self.console.write(parser.format_help())
|
||||||
except AttributeError, e:
|
except AttributeError, e:
|
||||||
self.write(cmd.__doc__ or 'No help for this command')
|
self.console.write(cmd.__doc__ or 'No help for this command')
|
||||||
else:
|
else:
|
||||||
max_length = max( len(k) for k in self._commands)
|
max_length = max( len(k) for k in self._commands)
|
||||||
for cmd in sorted(self._commands):
|
for cmd in sorted(self._commands):
|
||||||
self.write("{{info}}" + cmd + "{{input}} - " + self._commands[cmd].__doc__ or '')
|
self.console.write("{{info}}" + cmd + "{{input}} - " + self._commands[cmd].__doc__ or '')
|
||||||
self.write("")
|
self.console.write("")
|
||||||
self.write('For help on a specific command, use "<command> --help"')
|
self.console.write('For help on a specific command, use "<command> --help"')
|
||||||
|
|
||||||
def complete(self, text, *args):
|
|
||||||
return [ x for x in self._commands.keys() if x.startswith(text) ]
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
#
|
||||||
# info.py
|
# info.py
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
||||||
|
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
|
||||||
#
|
#
|
||||||
# Deluge is free software.
|
# Deluge is free software.
|
||||||
#
|
#
|
||||||
|
@ -23,13 +23,13 @@
|
||||||
# Boston, MA 02110-1301, USA.
|
# Boston, MA 02110-1301, USA.
|
||||||
#
|
#
|
||||||
|
|
||||||
from deluge.ui.console.main import BaseCommand, match_torrents
|
from optparse import make_option
|
||||||
from deluge.ui.console import mapping
|
|
||||||
|
from deluge.ui.console.main import BaseCommand
|
||||||
import deluge.ui.console.colors as colors
|
import deluge.ui.console.colors as colors
|
||||||
#from deluge.ui.console.colors import templates
|
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
import deluge.common as common
|
import deluge.common as common
|
||||||
from optparse import make_option
|
import deluge.component as component
|
||||||
|
|
||||||
status_keys = ["state",
|
status_keys = ["state",
|
||||||
"save_path",
|
"save_path",
|
||||||
|
@ -73,25 +73,58 @@ class Command(BaseCommand):
|
||||||
|
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
def on_to_ids(result):
|
self.console = component.get("ConsoleUI")
|
||||||
def on_match_torrents(torrents):
|
# Compile a list of torrent_ids to request the status of
|
||||||
for torrent in torrents:
|
torrent_ids = []
|
||||||
self.show_info(torrent, options.get("verbose"))
|
for arg in args:
|
||||||
|
torrent_ids.extend(self.console.match_torrent(arg))
|
||||||
|
|
||||||
match_torrents(result).addCallback(on_match_torrents)
|
def on_torrents_status(status):
|
||||||
mapping.to_ids(args).addCallback(on_to_ids)
|
# Print out the information for each torrent
|
||||||
|
for key, value in status.items():
|
||||||
|
self.show_info(key, value, options["verbose"])
|
||||||
|
|
||||||
# def complete(self, text, *args):
|
def on_torrents_status_fail(reason):
|
||||||
# torrents = match_torrents()
|
self.console.write("{{error}}Error getting torrent info: %s" % reason)
|
||||||
# names = mapping.get_names(torrents)
|
|
||||||
# return [ x[1] for x in names if x[1].startswith(text) ]
|
|
||||||
|
|
||||||
def show_info(self, torrent, verbose):
|
d = client.core.get_torrents_status({"id": torrent_ids}, status_keys)
|
||||||
|
d.addCallback(on_torrents_status)
|
||||||
|
d.addErrback(on_torrents_status_fail)
|
||||||
|
|
||||||
|
def show_info(self, torrent_id, status, verbose=False):
|
||||||
|
"""
|
||||||
|
Writes out the torrents information to the screen.
|
||||||
|
|
||||||
|
:param torrent_id: str, the torrent_id
|
||||||
|
:param status: dict, the torrents status, this should have the same keys
|
||||||
|
as status_keys
|
||||||
|
:param verbose: bool, if true, we print out more information about the
|
||||||
|
the torrent
|
||||||
|
"""
|
||||||
|
self.console.write(" ")
|
||||||
|
self.console.write("{{info}}Name: {{input}}%s" % (status["name"]))
|
||||||
|
self.console.write("{{info}}ID: {{input}}%s" % (torrent_id))
|
||||||
|
s = "{{info}}State: %s%s" % (colors.state_color[status["state"]], status["state"])
|
||||||
|
# Only show speed if active
|
||||||
|
if status["state"] in ("Seeding", "Downloading"):
|
||||||
|
if status["state"] != "Seeding":
|
||||||
|
s += " {{info}}Down Speed: {{input}}%s" % common.fspeed(status["download_payload_rate"])
|
||||||
|
s += " {{info}}Up Speed: {{input}}%s" % common.fspeed(status["upload_payload_rate"])
|
||||||
|
|
||||||
|
if common.ftime(status["eta"]):
|
||||||
|
s += " {{info}}ETA: {{input}}%s" % common.ftime(status["eta"])
|
||||||
|
|
||||||
|
self.console.write(s)
|
||||||
|
|
||||||
|
s = "{{info}}Seeds: {{input}}%s (%s)" % (status["num_seeds"], status["total_seeds"])
|
||||||
|
s += " {{info}}Peers: {{input}}%s (%s)" % (status["num_peers"], status["total_peers"])
|
||||||
|
s += " {{info}}Ratio: {{input}}%.3f" % status["ratio"]
|
||||||
|
s += " {{info}}Availibility: {{input}}%.2f" % status["distributed_copies"]
|
||||||
|
self.console.write(s)
|
||||||
|
|
||||||
|
|
||||||
|
""" def __show_info(self, torrent, verbose):
|
||||||
def _got_torrent_status(state):
|
def _got_torrent_status(state):
|
||||||
print templates.info_general('ID', torrent)
|
|
||||||
print templates.info_general('Name', state['name'])
|
|
||||||
#self._mapping[state['name']] = torrent # update mapping
|
|
||||||
print templates.info_general('Path', state['save_path'])
|
|
||||||
|
|
||||||
if verbose or not state['is_seed']:
|
if verbose or not state['is_seed']:
|
||||||
print templates.info_transfers("Completed", common.fsize(state['total_done']) + "/" + common.fsize(state['total_size']))
|
print templates.info_transfers("Completed", common.fsize(state['total_done']) + "/" + common.fsize(state['total_size']))
|
||||||
|
@ -129,3 +162,4 @@ class Command(BaseCommand):
|
||||||
str(common.fspeed(peer['up_speed'])), str(common.fspeed(peer['down_speed'])))
|
str(common.fspeed(peer['up_speed'])), str(common.fspeed(peer['down_speed'])))
|
||||||
print ""
|
print ""
|
||||||
client.core.get_torrent_status(torrent, status_keys).addCallback(_got_torrent_status)
|
client.core.get_torrent_status(torrent, status_keys).addCallback(_got_torrent_status)
|
||||||
|
"""
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
#
|
||||||
# pause.py
|
# pause.py
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
||||||
|
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
|
||||||
#
|
#
|
||||||
# Deluge is free software.
|
# Deluge is free software.
|
||||||
#
|
#
|
||||||
|
@ -22,30 +22,27 @@
|
||||||
# 51 Franklin Street, Fifth Floor
|
# 51 Franklin Street, Fifth Floor
|
||||||
# Boston, MA 02110-1301, USA.
|
# Boston, MA 02110-1301, USA.
|
||||||
#
|
#
|
||||||
from deluge.ui.console.main import BaseCommand, match_torrents
|
from deluge.ui.console.main import BaseCommand
|
||||||
from deluge.ui.console import mapping
|
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
import deluge.ui.console.colors as colors
|
import deluge.ui.console.colors as colors
|
||||||
|
import deluge.component as component
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
"""Pause a torrent"""
|
"""Pause a torrent"""
|
||||||
usage = "Usage: pause [ all | <torrent-id> [<torrent-id> ...] ]"
|
usage = "Usage: pause [ * | <torrent-id> [<torrent-id> ...] ]"
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
if len(args) == 0:
|
self.console = component.get("ConsoleUI")
|
||||||
print self.usage
|
|
||||||
return
|
|
||||||
if len(args) == 1 and args[0] == 'all':
|
|
||||||
args = tuple() # empty tuple means everything
|
|
||||||
try:
|
|
||||||
args = mapping.to_ids(args)
|
|
||||||
torrents = match_torrents(args)
|
|
||||||
client.pause_torrent(torrents)
|
|
||||||
except Exception, msg:
|
|
||||||
print templates.ERROR(str(msg))
|
|
||||||
else:
|
|
||||||
print templates.SUCCESS('torrent%s successfully paused' % ('s' if len(args) > 1 else ''))
|
|
||||||
|
|
||||||
def complete(self, text, *args):
|
if len(args) == 0:
|
||||||
torrents = match_torrents()
|
self.console.write(self.usage)
|
||||||
names = mapping.get_names(torrents)
|
return
|
||||||
return [ x[1] for x in names if x[1].startswith(text) ]
|
if len(args) > 0 and args[0].lower() == '*':
|
||||||
|
client.core.pause_all_torrents()
|
||||||
|
return
|
||||||
|
|
||||||
|
torrent_ids = []
|
||||||
|
for arg in args:
|
||||||
|
torrent_ids.extend(self.console.match_torrent(arg))
|
||||||
|
|
||||||
|
if torrent_ids:
|
||||||
|
client.core.pause_torrent(torrent_ids)
|
||||||
|
|
|
@ -34,3 +34,5 @@ class Command(BaseCommand):
|
||||||
def on_disconnect(result):
|
def on_disconnect(result):
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
client.disconnect().addCallback(on_disconnect)
|
client.disconnect().addCallback(on_disconnect)
|
||||||
|
else:
|
||||||
|
reactor.stop()
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
#
|
||||||
# resume.py
|
# resume.py
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
||||||
|
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
|
||||||
#
|
#
|
||||||
# Deluge is free software.
|
# Deluge is free software.
|
||||||
#
|
#
|
||||||
|
@ -22,30 +22,27 @@
|
||||||
# 51 Franklin Street, Fifth Floor
|
# 51 Franklin Street, Fifth Floor
|
||||||
# Boston, MA 02110-1301, USA.
|
# Boston, MA 02110-1301, USA.
|
||||||
#
|
#
|
||||||
from deluge.ui.console.main import BaseCommand, match_torrents
|
from deluge.ui.console.main import BaseCommand
|
||||||
from deluge.ui.console import mapping
|
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
import deluge.ui.console.colors as colors
|
import deluge.ui.console.colors as colors
|
||||||
|
import deluge.component as component
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
"""Resume a torrent"""
|
"""Resume a torrent"""
|
||||||
usage = "Usage: resume [ all | <torrent-id> [<torrent-id> ...] ]"
|
usage = "Usage: resume [ * | <torrent-id> [<torrent-id> ...] ]"
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
if len(args) == 0:
|
self.console = component.get("ConsoleUI")
|
||||||
print self.usage
|
|
||||||
return
|
|
||||||
if len(args) == 1 and args[0] == 'all':
|
|
||||||
args = tuple() # empty tuple means everything
|
|
||||||
try:
|
|
||||||
args = mapping.to_ids(args)
|
|
||||||
torrents = match_torrents(args)
|
|
||||||
client.resume_torrent(torrents)
|
|
||||||
except Exception, msg:
|
|
||||||
print templates.ERROR(str(msg))
|
|
||||||
else:
|
|
||||||
print templates.SUCCESS('torrent%s successfully resumed' % ('s' if len(args) > 1 else ''))
|
|
||||||
|
|
||||||
def complete(self, text, *args):
|
if len(args) == 0:
|
||||||
torrents = match_torrents()
|
self.console.write(self.usage)
|
||||||
names = mapping.get_names(torrents)
|
return
|
||||||
return [ x[1] for x in names if x[1].startswith(text) ]
|
if len(args) > 0 and args[0] == '*':
|
||||||
|
client.core.resume_all_torrents()
|
||||||
|
return
|
||||||
|
|
||||||
|
torrent_ids = []
|
||||||
|
for arg in args:
|
||||||
|
torrent_ids.extend(self.console.match_torrent(arg))
|
||||||
|
|
||||||
|
if torrent_ids:
|
||||||
|
client.core.resume_torrent(torrent_ids)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
#
|
#
|
||||||
# rm.py
|
# rm.py
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
# Copyright (C) 2008-2009 Ido Abramovich <ido.deluge@gmail.com>
|
||||||
|
# Copyright (C) 2009 Andrew Resch <andrewresch@gmail.com>
|
||||||
#
|
#
|
||||||
# Deluge is free software.
|
# Deluge is free software.
|
||||||
#
|
#
|
||||||
|
@ -22,12 +22,13 @@
|
||||||
# 51 Franklin Street, Fifth Floor
|
# 51 Franklin Street, Fifth Floor
|
||||||
# Boston, MA 02110-1301, USA.
|
# Boston, MA 02110-1301, USA.
|
||||||
#
|
#
|
||||||
from deluge.ui.console.main import BaseCommand, match_torrents
|
from deluge.ui.console.main import BaseCommand
|
||||||
from deluge.ui.console import mapping
|
|
||||||
import deluge.ui.console.colors as colors
|
import deluge.ui.console.colors as colors
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
|
import deluge.component as component
|
||||||
|
|
||||||
from optparse import make_option
|
from optparse import make_option
|
||||||
import os
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
"""Remove a torrent"""
|
"""Remove a torrent"""
|
||||||
|
@ -40,14 +41,12 @@ class Command(BaseCommand):
|
||||||
)
|
)
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
try:
|
self.console = component.get("ConsoleUI")
|
||||||
args = mapping.to_ids(args)
|
if len(args) == 0:
|
||||||
torrents = match_torrents(args)
|
self.console.write(usage)
|
||||||
client.remove_torrent(torrents, options['remove_data'])
|
|
||||||
except Exception, msg:
|
|
||||||
print template.ERROR(str(msg))
|
|
||||||
|
|
||||||
def complete(self, text, *args):
|
torrent_ids = []
|
||||||
torrents = match_torrents()
|
for arg in args:
|
||||||
names = mapping.get_names(torrents)
|
torrent_ids.extend(self.console.match_torrent(arg))
|
||||||
return [ x[1] for x in names if x[1].startswith(text) ]
|
|
||||||
|
client.core.remove_torrent(torrent_ids, options['remove_data'])
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
import deluge.common
|
import deluge.common
|
||||||
|
import colors
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
|
|
||||||
from deluge.log import LOG as log
|
from deluge.log import LOG as log
|
||||||
|
@ -58,16 +59,8 @@ class EventLog(component.Component):
|
||||||
def on_torrent_state_changed_event(self, torrent_id, state):
|
def on_torrent_state_changed_event(self, torrent_id, state):
|
||||||
log.debug("on_torrent_state_changed_event!")
|
log.debug("on_torrent_state_changed_event!")
|
||||||
# Modify the state string color
|
# Modify the state string color
|
||||||
state_color = {
|
if state in colors.state_color:
|
||||||
"Seeding": "{{blue,black,bold}}",
|
state = colors.state_color[state] + state
|
||||||
"Downloading": "{{green,black,bold}}",
|
|
||||||
"Paused": "{{white,black}}",
|
|
||||||
"Checking": "{{green,black}}",
|
|
||||||
"Queued": "{{yellow,black}}",
|
|
||||||
"Error": "{{red,black,bold}}"
|
|
||||||
}
|
|
||||||
if state in state_color:
|
|
||||||
state = state_color[state] + state
|
|
||||||
|
|
||||||
self.console.write("{{event}}* TorrentStateChanged: %s {{info}}%s (%s)" %
|
self.console.write("{{event}}* TorrentStateChanged: %s {{info}}%s (%s)" %
|
||||||
(state, self.console.get_torrent_name(torrent_id), torrent_id))
|
(state, self.console.get_torrent_name(torrent_id), torrent_id))
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
import os, sys
|
import os, sys
|
||||||
import optparse
|
import optparse
|
||||||
|
import shlex
|
||||||
|
|
||||||
|
from twisted.internet import defer, reactor
|
||||||
|
|
||||||
from deluge.ui.console import UI_PATH
|
from deluge.ui.console import UI_PATH
|
||||||
import deluge.component as component
|
import deluge.component as component
|
||||||
from deluge.ui.client import client
|
from deluge.ui.client import client
|
||||||
|
@ -32,14 +36,14 @@ import deluge.common
|
||||||
from deluge.ui.coreconfig import CoreConfig
|
from deluge.ui.coreconfig import CoreConfig
|
||||||
from deluge.ui.console.statusbars import StatusBars
|
from deluge.ui.console.statusbars import StatusBars
|
||||||
from deluge.ui.console.eventlog import EventLog
|
from deluge.ui.console.eventlog import EventLog
|
||||||
|
import deluge.ui.console.screen as screen
|
||||||
from twisted.internet import defer, reactor
|
import deluge.ui.console.colors as colors
|
||||||
import shlex
|
|
||||||
import screen
|
|
||||||
import colors
|
|
||||||
|
|
||||||
from deluge.log import LOG as log
|
from deluge.log import LOG as log
|
||||||
|
|
||||||
|
# XXX: Remove when the commands are all fixed up
|
||||||
|
def match_torrents(a=[]):
|
||||||
|
pass
|
||||||
|
|
||||||
class OptionParser(optparse.OptionParser):
|
class OptionParser(optparse.OptionParser):
|
||||||
"""subclass from optparse.OptionParser so exit() won't exit."""
|
"""subclass from optparse.OptionParser so exit() won't exit."""
|
||||||
def exit(self, status=0, msg=None):
|
def exit(self, status=0, msg=None):
|
||||||
|
@ -62,7 +66,6 @@ class BaseCommand(object):
|
||||||
option_list = tuple()
|
option_list = tuple()
|
||||||
aliases = []
|
aliases = []
|
||||||
|
|
||||||
|
|
||||||
def complete(self, text, *args):
|
def complete(self, text, *args):
|
||||||
return []
|
return []
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
@ -85,24 +88,7 @@ class BaseCommand(object):
|
||||||
epilog = self.epilog,
|
epilog = self.epilog,
|
||||||
option_list = self.option_list)
|
option_list = self.option_list)
|
||||||
|
|
||||||
|
def load_commands(command_dir, exclude=[]):
|
||||||
def match_torrents(array=[]):
|
|
||||||
# Make sure we don't have any duplicates
|
|
||||||
array = set(array)
|
|
||||||
# We return this defer and it will be fired once we received the session
|
|
||||||
# state and intersect the data.
|
|
||||||
d = defer.Deferred()
|
|
||||||
|
|
||||||
def _got_session_state(tors):
|
|
||||||
if not array:
|
|
||||||
d.callback(tors)
|
|
||||||
d.callback(list(tors.intersection(array)))
|
|
||||||
|
|
||||||
client.core.get_session_state().addCallback(_got_session_state)
|
|
||||||
|
|
||||||
return d
|
|
||||||
|
|
||||||
def load_commands(command_dir, write_func, exclude=[]):
|
|
||||||
def get_command(name):
|
def get_command(name):
|
||||||
return getattr(__import__('deluge.ui.console.commands.%s' % name, {}, {}, ['Command']), 'Command')()
|
return getattr(__import__('deluge.ui.console.commands.%s' % name, {}, {}, ['Command']), 'Command')()
|
||||||
|
|
||||||
|
@ -112,8 +98,6 @@ def load_commands(command_dir, write_func, exclude=[]):
|
||||||
if filename.split('.')[0] in exclude or filename.startswith('_') or not filename.endswith('.py'):
|
if filename.split('.')[0] in exclude or filename.startswith('_') or not filename.endswith('.py'):
|
||||||
continue
|
continue
|
||||||
cmd = get_command(filename[:-3])
|
cmd = get_command(filename[:-3])
|
||||||
# Hack to give the commands a write function
|
|
||||||
cmd.write = write_func
|
|
||||||
aliases = [ filename[:-3] ]
|
aliases = [ filename[:-3] ]
|
||||||
aliases.extend(cmd.aliases)
|
aliases.extend(cmd.aliases)
|
||||||
for a in aliases:
|
for a in aliases:
|
||||||
|
@ -126,7 +110,7 @@ class ConsoleUI(component.Component):
|
||||||
def __init__(self, args=None):
|
def __init__(self, args=None):
|
||||||
component.Component.__init__(self, "ConsoleUI", 2)
|
component.Component.__init__(self, "ConsoleUI", 2)
|
||||||
# Load all the commands
|
# Load all the commands
|
||||||
self._commands = load_commands(os.path.join(UI_PATH, 'commands'), self.write)
|
self._commands = load_commands(os.path.join(UI_PATH, 'commands'))
|
||||||
|
|
||||||
# Try to connect to the localhost daemon
|
# Try to connect to the localhost daemon
|
||||||
def on_connect(result):
|
def on_connect(result):
|
||||||
|
@ -236,10 +220,11 @@ class ConsoleUI(component.Component):
|
||||||
if not getattr(options, '_exit', False):
|
if not getattr(options, '_exit', False):
|
||||||
try:
|
try:
|
||||||
self._commands[cmd].handle(*args, **options.__dict__)
|
self._commands[cmd].handle(*args, **options.__dict__)
|
||||||
except StopIteration, e:
|
|
||||||
raise
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
self.write("{{error}}" + str(e))
|
self.write("{{error}}" + str(e))
|
||||||
|
log.exception(e)
|
||||||
|
import traceback
|
||||||
|
self.write("%s" % traceback.format_exc())
|
||||||
|
|
||||||
def tab_completer(self, line, cursor, second_hit):
|
def tab_completer(self, line, cursor, second_hit):
|
||||||
"""
|
"""
|
||||||
|
@ -330,9 +315,27 @@ class ConsoleUI(component.Component):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def match_torrent(self, string):
|
||||||
|
"""
|
||||||
|
Returns a list of torrent_id matches for the string. It will search both
|
||||||
|
torrent_ids and torrent names, but will only return torrent_ids.
|
||||||
|
|
||||||
|
:param string: str, the string to match on
|
||||||
|
|
||||||
|
:returns: list of matching torrent_ids. Will return an empty list if
|
||||||
|
no matches are found.
|
||||||
|
|
||||||
|
"""
|
||||||
|
ret = []
|
||||||
|
for tid, name in self.torrents:
|
||||||
|
if tid.startswith(string) or name.startswith(string):
|
||||||
|
ret.append(tid)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
def on_torrent_added_event(self, torrent_id):
|
def on_torrent_added_event(self, torrent_id):
|
||||||
def on_torrent_status(status):
|
def on_torrent_status(status):
|
||||||
self.torrents.append(torrent_id, status["name"])
|
self.torrents.append((torrent_id, status["name"]))
|
||||||
client.get_torrent_status(torrent_id, ["name"]).addCallback(on_torrent_status)
|
client.get_torrent_status(torrent_id, ["name"]).addCallback(on_torrent_status)
|
||||||
|
|
||||||
def on_torrent_removed_event(self, torrent_id):
|
def on_torrent_removed_event(self, torrent_id):
|
||||||
|
|
|
@ -116,15 +116,6 @@ class Screen(CursesStdIO):
|
||||||
"""
|
"""
|
||||||
log.debug("adding line: %s", text)
|
log.debug("adding line: %s", text)
|
||||||
|
|
||||||
def get_line_length(line):
|
|
||||||
"""
|
|
||||||
Returns the string length without the color formatting.
|
|
||||||
|
|
||||||
"""
|
|
||||||
while line.find("{{") != -1:
|
|
||||||
line = line[:line.find("{{")] + line[line.find("}}") + 2:]
|
|
||||||
|
|
||||||
return len(line)
|
|
||||||
|
|
||||||
def get_line_chunks(line):
|
def get_line_chunks(line):
|
||||||
"""
|
"""
|
||||||
|
@ -155,7 +146,12 @@ class Screen(CursesStdIO):
|
||||||
|
|
||||||
for line in text.splitlines():
|
for line in text.splitlines():
|
||||||
# We need to check for line lengths here and split as necessary
|
# We need to check for line lengths here and split as necessary
|
||||||
line_length = get_line_length(line)
|
try:
|
||||||
|
line_length = colors.get_line_length(line)
|
||||||
|
except colors.BadColorString:
|
||||||
|
log.error("Passed a bad colored string..")
|
||||||
|
line_length = len(line)
|
||||||
|
|
||||||
if line_length >= (self.cols - 1):
|
if line_length >= (self.cols - 1):
|
||||||
s = ""
|
s = ""
|
||||||
# The length of the text without the color tags
|
# The length of the text without the color tags
|
||||||
|
@ -198,7 +194,12 @@ class Screen(CursesStdIO):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
col = 0
|
col = 0
|
||||||
|
try:
|
||||||
parsed = colors.parse_color_string(string)
|
parsed = colors.parse_color_string(string)
|
||||||
|
except colors.BadColorString:
|
||||||
|
log.error("Cannot add bad color string: %s", string)
|
||||||
|
return
|
||||||
|
|
||||||
for index, (color, s) in enumerate(parsed):
|
for index, (color, s) in enumerate(parsed):
|
||||||
if index + 1 == len(parsed):
|
if index + 1 == len(parsed):
|
||||||
# This is the last string so lets append some " " to it
|
# This is the last string so lets append some " " to it
|
||||||
|
|
Loading…
Reference in New Issue