diff options
author | RaNaN <Mast3rRaNaN@hotmail.de> | 2011-05-10 21:23:46 +0200 |
---|---|---|
committer | RaNaN <Mast3rRaNaN@hotmail.de> | 2011-05-10 21:23:46 +0200 |
commit | 60ae0ee3dce4715621b9964c91ad96e08e123204 (patch) | |
tree | 251aeb85742a32a8f3711879e4071a66e59bdc26 | |
parent | fixes netload free (diff) | |
download | pyload-60ae0ee3dce4715621b9964c91ad96e08e123204.tar.xz |
-rw-r--r-- | module/HookManager.py | 6 | ||||
-rw-r--r-- | module/cli/AddPackage.py | 66 | ||||
-rw-r--r-- | module/cli/Handler.py | 48 | ||||
-rw-r--r-- | module/cli/ManageFiles.py | 204 | ||||
-rw-r--r-- | module/cli/__init__.py | 2 | ||||
-rw-r--r-- | module/cli/printer.py | 26 | ||||
-rw-r--r-- | module/lib/Getch.py | 76 | ||||
-rw-r--r-- | module/lib/SafeEval.py (renamed from module/SafeEval.py) | 0 | ||||
-rw-r--r-- | module/lib/Unzip.py (renamed from module/Unzip.py) | 0 | ||||
-rw-r--r-- | module/plugins/PluginManager.py | 2 | ||||
-rw-r--r-- | module/remote/thriftbackend/Handler.py | 1 | ||||
-rw-r--r-- | module/remote/thriftbackend/pyload.thrift | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | pyLoadCli.py | 556 |
13 files changed, 618 insertions, 371 deletions
diff --git a/module/HookManager.py b/module/HookManager.py index c3da485a9..1138a4c29 100644 --- a/module/HookManager.py +++ b/module/HookManager.py @@ -62,18 +62,16 @@ class HookManager: def addRPC(self, plugin, func, doc): plugin = plugin.rpartition(".")[2] - doc = doc.strip() + doc = doc.strip() if doc else "" if self.methods.has_key(plugin): self.methods[plugin][func] = doc else: self.methods[plugin] = {func: doc} - print self.methods - def callRPC(self, plugin, func, args, parse): if not args: args = tuple() - if parse is not False: + if parse: args = tuple([literal_eval(x) for x in args]) plugin = self.pluginMap[plugin] diff --git a/module/cli/AddPackage.py b/module/cli/AddPackage.py new file mode 100644 index 000000000..ded08742b --- /dev/null +++ b/module/cli/AddPackage.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +#Copyright (C) 2011 RaNaN +# +#This program is free software; you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation; either version 3 of the License, +#or (at your option) any later version. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +#See the GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +### + +from Handler import Handler +from printer import * + +class AddPackage(Handler): + """ let the user add packages """ + + def init(self): + self.name = "" + self.urls = [] + + def onEnter(self, inp): + if inp == "0": + self.cli.reset() + + if not self.name: + self.name = inp + self.setInput() + elif inp == "END": + #add package + self.client.addPackage(self.name, self.urls, 0) + self.cli.reset() + else: + if inp.strip(): + self.urls.append(inp) + self.setInput() + + def renderBody(self, line): + println(line, white(_("Add Package:"))) + println(line + 1, "") + line += 2 + + if not self.name: + println(line, _("Enter a name for the new package")) + println(line + 1, "") + line += 2 + else: + println(line, _("Package: %s") % self.name) + println(line + 1, _("Parse the links you want to add.")) + println(line + 2, _("Type %s when done.") % mag("END")) + println(line + 3, _("Links added: ") + mag(len(self.urls))) + line += 4 + + println(line, "") + println(line + 1, mag("0.") + _(" back to main menu")) + + return line + 2
\ No newline at end of file diff --git a/module/cli/Handler.py b/module/cli/Handler.py new file mode 100644 index 000000000..476d09386 --- /dev/null +++ b/module/cli/Handler.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +#Copyright (C) 2011 RaNaN +# +#This program is free software; you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation; either version 3 of the License, +#or (at your option) any later version. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +#See the GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +### +class Handler: + def __init__(self, cli): + self.cli = cli + self.init() + + client = property(lambda self: self.cli.client) + input = property(lambda self: self.cli.input) + + def init(self): + pass + + def onChar(self, char): + pass + + def onBackSpace(self): + pass + + def onEnter(self, inp): + pass + + def setInput(self, inp=""): + self.cli.setInput(inp) + + def backspace(self): + self.cli.setInput(self.input[:-1]) + + def renderBody(self, line): + """ gets the line where to render output and should return the line number below its content """ + return line + 1
\ No newline at end of file diff --git a/module/cli/ManageFiles.py b/module/cli/ManageFiles.py new file mode 100644 index 000000000..1d04c4c49 --- /dev/null +++ b/module/cli/ManageFiles.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +#Copyright (C) 2011 RaNaN +# +#This program is free software; you can redistribute it and/or modify +#it under the terms of the GNU General Public License as published by +#the Free Software Foundation; either version 3 of the License, +#or (at your option) any later version. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +#See the GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. +# +### + +from itertools import islice +from time import time + +from Handler import Handler +from printer import * + +from module.remote.thriftbackend.thriftgen.pyload.Pyload import PackageData, PackageDoesNotExists + +class ManageFiles(Handler): + """ possibility to manage queue/collector """ + + def init(self): + self.target = 1 #queue + self.pos = 0 #position in queue + self.package = -1 #choosen package + self.mode = "" # move/delete/restart + + self.cache = None + self.links = None + self.time = 0 + + def onChar(self, char): + if char in ("m", "d", "r"): + self.mode = char + self.setInput() + elif char == "p": + self.pos = max(0, self.pos - 5) + self.backspace() + elif char == "n": + self.pos += 5 + self.backspace() + + def onBackSpace(self): + if not self.input and self.mode: + self.mode = "" + if not self.input and self.package > -1: + self.package = -1 + + def onEnter(self, input): + if input == "0": + self.cli.reset() + elif self.package < 0 and self.mode: + #mode select + packs = self.parseInput(input) + if self.mode == "m": + [self.client.movePackage((self.target + 1) % 2, x) for x in packs] + elif self.mode == "d": + self.client.deletePackages(packs) + elif self.mode == "r": + [self.client.restartPackage(x) for x in packs] + + elif self.mode: + #edit links + links = self.parseInput(input, False) + + if self.mode == "d": + self.client.deleteFiles(links) + elif self.mode == "r": + map(self.client.restartFile, links) + + else: + #look into package + try: + self.package = int(input) + except: + pass + + self.cache = None + self.links = None + self.pos = 0 + self.mode = "" + self.setInput() + + + def renderBody(self, line): + if self.package < 0: + println(line, white(_("Manage Packages:"))) + else: + println(line, white((_("Manage Links:")))) + line += 1 + + if self.mode: + if self.mode == "m": + println(line, _("What do you want to move?")) + elif self.mode == "d": + println(line, _("What do you want to delete?")) + elif self.mode == "r": + println(line, _("What do you want to restart?")) + + println(line + 1, "Enter single number, comma seperated numbers or ranges. eg. 1,2,3 or 1-3.") + line += 2 + else: + println(line, _("Choose what yout want to do or enter package number.")) + println(line + 1, ("%s - %%s, %s - %%s, %s - %%s" % (mag("d"), mag("m"), mag("r"))) % ( + _("delete"), _("move"), _("restart"))) + line += 2 + + if self.package < 0: + #print package info + pack = self.getPackages() + i = 0 + for value in islice(pack, self.pos, self.pos + 5): + try: + println(line, mag(str(value.pid)) + ": " + value.name) + line += 1 + i += 1 + except Exception, e: + pass + for x in range(5 - i): + println(line, "") + line += 1 + else: + #print links info + pack = self.getLinks() + i = 0 + for value in islice(pack.links, self.pos, self.pos + 5): + try: + println(line, mag(value.fid) + ": %s | %s | %s" % ( + value.name, value.statusmsg, value.plugin)) + line += 1 + i += 1 + except Exception, e: + pass + for x in range(5 - i): + println(line, "") + line += 1 + + println(line, mag("p") + _(" - previous") + " | " + mag("n") + _(" - next")) + println(line + 1, mag("0.") + _(" back to main menu")) + + return line + 2 + + + def getPackages(self): + if self.cache and self.time + 2 < time(): + return self.cache + + if self.target == 1: + data = self.client.getQueue() + else: + data = self.client.getCollector() + + + self.cache = data + self.time = time() + + return data + + def getLinks(self): + if self.links and self.time + 1 < time(): + return self.links + + try: + data = self.client.getPackageData(self.package) + except: + data = PackageData(links=[]) + + self.links = data + self.time = time() + + return data + + def parseInput(self, inp, package=True): + inp = inp.strip() + if "-" in inp: + l, n, h = inp.partition("-") + l = int(l) + h = int(h) + r = range(l, h + 1) + + ret = [] + if package: + for p in self.cache: + if p.pid in r: + ret.append(p.pid) + else: + for l in self.links.links: + if l.lid in r: + ret.append(l.lid) + + return ret + + else: + return [int(x) for x in inp.split(",")]
\ No newline at end of file diff --git a/module/cli/__init__.py b/module/cli/__init__.py new file mode 100644 index 000000000..fa8a09291 --- /dev/null +++ b/module/cli/__init__.py @@ -0,0 +1,2 @@ +from AddPackage import AddPackage +from ManageFiles import ManageFiles
\ No newline at end of file diff --git a/module/cli/printer.py b/module/cli/printer.py new file mode 100644 index 000000000..c62c1800e --- /dev/null +++ b/module/cli/printer.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +def blue(string): + return "\033[1;34m" + unicode(string) + "\033[0m" + +def green(string): + return "\033[1;32m" + unicode(string) + "\033[0m" + +def yellow(string): + return "\033[1;33m" + unicode(string) + "\033[0m" + +def red(string): + return "\033[1;31m" + unicode(string) + "\033[0m" + +def cyan(string): + return "\033[1;36m" + unicode(string) + "\033[0m" + +def mag(string): + return "\033[1;35m" + unicode(string) + "\033[0m" + +def white(string): + return "\033[1;37m" + unicode(string) + "\033[0m" + +def println(line, content): + print "\033[" + str(line) + ";0H\033[2K" + content
\ No newline at end of file diff --git a/module/lib/Getch.py b/module/lib/Getch.py new file mode 100644 index 000000000..22b7ea7f8 --- /dev/null +++ b/module/lib/Getch.py @@ -0,0 +1,76 @@ +class Getch: + """ + Gets a single character from standard input. Does not echo to + the screen. + """ + + def __init__(self): + try: + self.impl = _GetchWindows() + except ImportError: + try: + self.impl = _GetchMacCarbon() + except(AttributeError, ImportError): + self.impl = _GetchUnix() + + def __call__(self): return self.impl() + + +class _GetchUnix: + def __init__(self): + import tty + import sys + + def __call__(self): + import sys + import tty + import termios + + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + try: + tty.setraw(sys.stdin.fileno()) + ch = sys.stdin.read(1) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) + return ch + + +class _GetchWindows: + def __init__(self): + import msvcrt + + def __call__(self): + import msvcrt + + return msvcrt.getch() + +class _GetchMacCarbon: + """ + A function which returns the current ASCII key that is down; + if no ASCII key is down, the null string is returned. The + page http://www.mactech.com/macintosh-c/chap02-1.html was + very helpful in figuring out how to do this. + """ + + def __init__(self): + import Carbon + Carbon.Evt #see if it has this (in Unix, it doesn't) + + def __call__(self): + import Carbon + + if Carbon.Evt.EventAvail(0x0008)[0] == 0: # 0x0008 is the keyDownMask + return '' + else: + # + # The event contains the following info: + # (what,msg,when,where,mod)=Carbon.Evt.GetNextEvent(0x0008)[1] + # + # The message (msg) contains the ASCII char which is + # extracted with the 0x000000FF charCodeMask; this + # number is converted to an ASCII character with chr() and + # returned + # + (what, msg, when, where, mod) = Carbon.Evt.GetNextEvent(0x0008)[1] + return chr(msg)
\ No newline at end of file diff --git a/module/SafeEval.py b/module/lib/SafeEval.py index 8ec9766e6..8ec9766e6 100644 --- a/module/SafeEval.py +++ b/module/lib/SafeEval.py diff --git a/module/Unzip.py b/module/lib/Unzip.py index f56fbe751..f56fbe751 100644 --- a/module/Unzip.py +++ b/module/lib/Unzip.py diff --git a/module/plugins/PluginManager.py b/module/plugins/PluginManager.py index acfabde21..0ca060152 100644 --- a/module/plugins/PluginManager.py +++ b/module/plugins/PluginManager.py @@ -29,7 +29,7 @@ from traceback import print_exc try: from ast import literal_eval except ImportError: # python 2.5 - from module.SafeEval import safe_eval as literal_eval + from module.lib.SafeEval import safe_eval as literal_eval from module.ConfigParser import IGNORE diff --git a/module/remote/thriftbackend/Handler.py b/module/remote/thriftbackend/Handler.py index 9d38109db..9a7c1489e 100644 --- a/module/remote/thriftbackend/Handler.py +++ b/module/remote/thriftbackend/Handler.py @@ -157,6 +157,7 @@ class Handler(Iface): status.format_wait = pyfile.formatWait() status.wait_until = pyfile.waitUntil status.package = pyfile.package().name + status.packageID = pyfile.package().id data.append(status) return data diff --git a/module/remote/thriftbackend/pyload.thrift b/module/remote/thriftbackend/pyload.thrift index 8e399062d..c26334051 100644 --- a/module/remote/thriftbackend/pyload.thrift +++ b/module/remote/thriftbackend/pyload.thrift @@ -162,7 +162,7 @@ struct ServiceCall { 1: string plugin, 2: string func, 3: optional list<string> arguments, - 4: optional bool parseArguments, //default True + 4: optional bool parseArguments, //default False } exception PackageDoesNotExists{ diff --git a/pyLoadCli.py b/pyLoadCli.py index 0fe88b572..5a4a152f2 100755..100644 --- a/pyLoadCli.py +++ b/pyLoadCli.py @@ -20,13 +20,12 @@ from getopt import GetoptError, getopt import gettext -from itertools import islice import os from os import _exit from os.path import join import sys from sys import exit -import threading +from threading import Thread, Lock from time import sleep from traceback import print_exc @@ -35,9 +34,13 @@ from codecs import getwriter sys.stdout = getwriter("utf8")(sys.stdout, errors="replace") from module import InitHomeDir +from module.cli.printer import * +from module.cli import AddPackage, ManageFiles + from module.utils import formatSize, decode from module.ConfigParser import ConfigParser -from module.remote.thriftbackend.ThriftClient import ThriftClient, NoConnection, NoSSL, WrongLogin, PackageDoesNotExists, ConnectionClosed +from module.remote.thriftbackend.ThriftClient import ThriftClient, NoConnection, NoSSL, WrongLogin, ConnectionClosed +from module.lib.Getch import Getch class Cli: def __init__(self, client, command): @@ -45,21 +48,22 @@ class Cli: self.command = command if not self.command: - self.getch = _Getch() + self.getch = Getch() self.input = "" - self.pos = [0, 0, 0] self.inputline = 0 + self.lastLowestLine = 0 self.menuline = 0 - self.new_package = {} + self.lock = Lock() - self.links_added = 0 + #processor funcions, these will be changed dynamically depending on control flow + self.headerHandler = self #the download status + self.bodyHandler = self #the menu section + self.inputHandler = self os.system("clear") - self.println(1, blue("py") + yellow("Load") + white(_(" Command Line Interface"))) - self.println(2, "") - - self.file_list = {} + println(1, blue("py") + yellow("Load") + white(_(" Command Line Interface"))) + println(2, "") self.thread = RefreshThread(self) self.thread.start() @@ -68,275 +72,176 @@ class Cli: else: self.processCommand() + def reset(self): + """ reset to initial main menu """ + self.input = "" + self.headerHandler = self.bodyHandler = self.inputHandler = self + def start(self): + """ main loop. handle input """ while True: #inp = raw_input() inp = self.getch.impl() if ord(inp) == 3: os.system("clear") sys.exit() # ctrl + c - elif ord(inp) == 13: + elif ord(inp) == 13: #enter try: - self.handle_input() + self.lock.acquire() + self.inputHandler.onEnter(self.input) + except Exception, e: - self.println(2, red(e)) - self.input = "" #enter - self.print_input() + println(2, red(e)) + finally: + self.lock.release() + elif ord(inp) == 127: self.input = self.input[:-1] #backspace - self.print_input() + try: + self.lock.acquire() + self.inputHandler.onBackSpace() + finally: + self.lock.release() + elif ord(inp) == 27: #ugly symbol pass else: self.input += inp - self.print_input() + try: + self.lock.acquire() + self.inputHandler.onChar(inp) + finally: + self.lock.release() - def format_time(self, seconds): - seconds = int(seconds) + self.inputline = self.bodyHandler.renderBody(self.menuline) + self.renderFooter(self.inputline) - hours, seconds = divmod(seconds, 3600) - minutes, seconds = divmod(seconds, 60) - return "%.2i:%.2i:%.2i" % (hours, minutes, seconds) - def println(self, line, content): - print "\033[" + str(line) + ";0H\033[2K" + content + "\033[" + \ - str((self.inputline if self.inputline > 0 else self.inputline + 1) - 1) + ";0H" + def refresh(self): + """refresh screen""" - def print_input(self): - self.println(self.inputline, white(" Input: ") + decode(self.input)) - self.println(self.inputline + 1, "") - self.println(self.inputline + 2, "") - self.println(self.inputline + 3, "") - self.println(self.inputline + 4, "") + println(1, blue("py") + yellow("Load") + white(_(" Command Line Interface"))) + println(2, "") - def refresh(self): - """Handle incoming data""" - data = self.client.statusDownloads() + self.lock.acquire() + + self.menuline = self.headerHandler.renderHeader(3) + 1 + println(self.menuline - 1, "") + self.inputline = self.bodyHandler.renderBody(self.menuline) + self.renderFooter(self.inputline) + + self.lock.release() + + + def setInput(self, string=""): + self.input = string + + def setHandler(self, klass): + #create new handler with reference to cli + self.bodyHandler = self.inputHandler = klass(self) + self.input = "" + + def renderHeader(self, line): + """ prints download status """ #print updated information - print "\033[J" #clear screen - self.println(1, blue("py") + yellow("Load") + white(_(" Command Line Interface"))) - self.println(2, "") - self.println(3, white(_("%s Downloads:") % (len(data)))) - line = 4 + # print "\033[J" #clear screen + # self.println(1, blue("py") + yellow("Load") + white(_(" Command Line Interface"))) + # self.println(2, "") + # self.println(3, white(_("%s Downloads:") % (len(data)))) + + data = self.client.statusDownloads() speed = 0 + + println(line, white(_("%s Downloads:") % (len(data)))) + line += 1 + for download in data: if download.status == 12: # downloading percent = download.percent z = percent / 4 speed += download.speed - self.println(line, cyan(download.name)) + println(line, cyan(download.name)) line += 1 - self.println(line, - blue("[") + yellow(z * "#" + (25 - z) * " ") + blue("] ") + green(str(percent) + "%") + _( - " Speed: ") + green(formatSize(speed)+ "/s") + _(" Size: ") + green( - download.format_size) + _(" Finished in: ") + green(download.format_eta) + _( - " ID: ") + green(download.fid)) + println(line, + blue("[") + yellow(z * "#" + (25 - z) * " ") + blue("] ") + green(str(percent) + "%") + _( + " Speed: ") + green(formatSize(speed) + "/s") + _(" Size: ") + green( + download.format_size) + _(" Finished in: ") + green(download.format_eta) + _( + " ID: ") + green(download.fid)) line += 1 if download.status == 5: - self.println(line, cyan(download.name)) + println(line, cyan(download.name)) line += 1 - self.println(line, _("waiting: ") + green(download.format_wait)) + println(line, _("waiting: ") + green(download.format_wait)) line += 1 - self.println(line, "") + + println(line, "") line += 1 status = self.client.statusServer() if status.pause: - self.println(line, - _("Status: ") + red("paused") + _(" total Speed: ") + red(formatSize(speed)+ "/s") + _( - " Files in queue: ") + red(status.queue)) + println(line, + _("Status: ") + red("paused") + _(" total Speed: ") + red(formatSize(speed) + "/s") + _( + " Files in queue: ") + red(status.queue)) else: - self.println(line, - _("Status: ") + red("running") + _(" total Speed: ") + red(formatSize(speed) + "/s") + _( - " Files in queue: ") + red(status.queue)) - line += 1 - self.println(line, "") + println(line, + _("Status: ") + red("running") + _(" total Speed: ") + red(formatSize(speed) + "/s") + _( + " Files in queue: ") + red(status.queue)) + + return line + 1 + + def renderBody(self, line): + """ prints initial menu """ + println(line, white(_("Menu:"))) + println(line + 1, "") + println(line + 2, mag("1.") + _(" Add Links")) + println(line + 3, mag("2.") + _(" Manage Queue")) + println(line + 4, mag("3.") + _(" Manage Collector")) + println(line + 5, mag("4.") + _(" (Un)Pause Server")) + println(line + 6, mag("5.") + _(" Kill Server")) + println(line + 7, mag("6.") + _(" Quit")) + + return line + 8 + + def renderFooter(self, line): + """ prints out the input line with input """ + println(line, "") line += 1 - self.menuline = line - self.build_menu() - # - self.file_list = data + println(line, white(" Input: ") + decode(self.input)) - def build_menu(self): - line = self.menuline - self.println(line, white(_("Menu:"))) - line += 1 - if not self.pos[0]:# main menu - self.println(line, "") - line += 1 - self.println(line, mag("1.") + _(" Add Links")) - line += 1 - self.println(line, mag("2.") + _(" Manage Links")) - line += 1 - self.println(line, mag("3.") + _(" Manage Collector")) - line += 1 - self.println(line, mag("4.") + _(" (Un)Pause Server")) - line += 1 - self.println(line, mag("5.") + _(" Kill Server")) - line += 1 - self.println(line, mag("6.") + _(" Quit")) - line += 1 - self.println(line, "") - line += 1 - self.println(line, "") - elif self.pos[0] == 1:#add links - - if not self.pos[1]: - self.println(line, "") - line += 1 - self.println(line, _("Name your package.")) - line += 1 - self.println(line, "") - line += 1 - self.println(line, "") - line += 1 - self.println(line, "") - line += 1 - self.println(line, "") - line += 1 - self.println(line, mag("0.") + _(" back to main menu")) - line += 1 - self.println(line, "") + #clear old output + if line < self.lastLowestLine: + for i in range(line + 1, self.lastLowestLine + 1): + println(i, "") - else: - self.println(line, _("Package: %s") % self.new_package['name']) - line += 1 - self.println(line, _("Parse the links you want to add.")) - line += 1 - self.println(line, _("Type %s when done.") % mag("END")) - line += 1 - self.println(line, _("Links added: ") + mag(self.links_added)) - line += 1 - self.println(line, "") - line += 1 - self.println(line, "") - line += 1 - self.println(line, mag("0.") + _(" back to main menu")) - line += 1 - self.println(line, "") - elif self.pos[0] == 2 or self.pos[0] == 3: #Manage Queues - swapdest = "Collector" if self.pos[0] == 2 else "Queue" - if not self.pos[1]: - if self.pos[0] == 2: - pack = self.client.getQueue() - else: - pack = self.client.getCollector() - self.println(line, _( - "Type d(number of package) to delete a package, r to restart, s to send to %s or w/o d,r,s to look into it." % swapdest)) - line += 1 - i = 0 - for value in islice(pack, self.pos[2], self.pos[2] + 5): - try: - self.println(line, mag(str(value.pid)) + ": " + value.name) - line += 1 - i += 1 - except Exception, e: - pass - for x in range(5 - i): - self.println(line, "") - line += 1 + self.lastLowestLine = line - else: - try: - pack = self.client.getPackageData(self.pos[1]) - except PackageDoesNotExists: - self.pos[1] = 0 - self.print_input() - return - - self.println(line, _("Type d(number) of the link you want to delete, r(number) to restart, s(number) to send to %s." % swapdest)) - line += 1 - i = 0 - for value in islice(pack.links, self.pos[2], self.pos[2] + 5): - try: - self.println(line, mag(value.fid) + ": %s | %s | %s" % ( - value.name, value.statusmsg, value.plugin)) - line += 1 - i += 1 - - except Exception, e: - pass - for x in range(5 - i): - self.println(line, "") - line += 1 - - self.println(line, mag("p") + _(" - previous") + " | " + mag("n") + _(" - next")) - line += 1 - self.println(line, mag("0.") + _(" back to main menu")) - - self.inputline = line + 1 - self.print_input() - - def handle_input(self): - inp = self.input.strip() - if inp == "0": - self.pos = [0, 0, 0] - self.build_menu() - return True - - if not self.pos[0]: - if inp == "1": - self.links_added = 0 - self.pos[0] = 1 - elif inp == "2" or inp == "3": - self.pos[0] = int(inp) - self.pos[1] = 0 - elif inp == "4": - self.client.togglePause() - elif inp == "5": - self.client.kill() - self.client.close() - sys.exit() - elif inp == "6": - os.system('clear') - sys.exit() - - elif self.pos[0] == 1: #add links - if not self.pos[1]: - self.new_package['name'] = inp - self.new_package['links'] = [] - self.pos[1] = 1 - else: - if inp == "END": - self.client.addPackage(self.new_package['name'], self.new_package['links'], 1) # add package - self.pos = [0, 0, 0] - self.links_added = 0 - else: #TODO validation - self.new_package['links'].append(inp) - self.links_added += 1 - - elif self.pos[0] == 2 or self.pos[0] == 3: #Manage queue/collector - if not self.pos[1]: - if inp.startswith("d"): - if inp.find("-") > -1: - self.client.deletePackages(range(*map(int, inp[1:].split("-")))) - else: - self.client.deletePackages([int(inp[1:])]) - elif inp.startswith("r"): - self.client.restartPackage(int(inp[1:])) - elif inp.startswith("s"): - self.client.movePackage(int(self.pos[0])-2,int(inp[1:])) # Opt 3-2 == 1 (queue) Opt 2-2 == 0 (collector) - elif inp != "p" and inp != "n": - self.pos[1] = int(inp) - self.pos[2] = 0 - elif inp.startswith('r'): - if inp.find("-") > -1: - map(self.client.restartFile, range(*map(int, inp[1:].split("-")))) - else: - self.client.restartFile(int(inp[1:])) - elif inp.startswith("s"): - self.client.movePackage(int(self.pos[0])-2,int(inp[1:])) # Opt 3-2 == 1 (queue) Opt 2-2 == 0 (collector) - elif inp.startswith('d'): - if inp.find("-") > -1: - self.client.deleteFiles(range(*map(int, inp[1:].split("-")))) - else: - self.client.deleteFiles([int(inp[1:])]) - if inp == "p": - self.pos[2] -= 5 - elif inp == "n": - self.pos[2] += 5 - - self.build_menu() + #set cursor to position + print "\033[" + str(self.inputline) + ";0H" + + def onChar(self, char): + """ default no special handling for single chars """ + if char == "1": + self.setHandler(AddPackage) + elif char == "2": + self.setHandler(ManageFiles) + elif char == "3": + self.setHandler(ManageFiles) + self.bodyHandler.target = 0 + elif char == "4": + self.client.togglePause() + elif char == "5": + self.client.kill() + self.client.close() + sys.exit() + elif char == "6": + os.system('clear') + sys.exit() + + def onEnter(self, inp): + pass + + def onBackSpace(self): + pass def processCommand(self): command = self.command[0] @@ -347,10 +252,15 @@ class Cli: if command == "status": files = self.client.statusDownloads() + if not files: + print "No downloads running." + for download in files: if download.status == 12: # downloading print print_status(download) - print "\tDownloading: %s @ %s/s\t %s (%s%%)" % (download.format_eta, formatSize(download.speed), formatSize(download.size - download.bleft), download.percent) + print "\tDownloading: %s @ %s/s\t %s (%s%%)" % ( + download.format_eta, formatSize(download.speed), formatSize(download.size - download.bleft), + download.percent) if download.status == 5: print print_status(download) print "\tWaiting: %s" % download.format_wait @@ -368,6 +278,13 @@ class Cli: self.client.addPackage(args[0], args[1:], 1) + elif command == "add_coll": + if len(args) < 2: + print _("Please use this syntax: add <Package name> <link> <link2> ...") + return + + self.client.addPackage(args[0], args[1:], 0) + elif command == "del_file": self.client.deleteFiles([int(x) for x in args]) print "Files deleted." @@ -376,6 +293,11 @@ class Cli: self.client.deletePackages([int(x) for x in args]) print "Packages deleted." + elif command == "move": + for pid in args: + pack = self.client.getPackageData(int(pid)) + self.client.movePackage((pack.dest + 1) % 2, pack.pid) + elif command == "pause": self.client.pause() @@ -391,9 +313,9 @@ class Cli: print_commands() -class RefreshThread(threading.Thread): +class RefreshThread(Thread): def __init__(self, cli): - threading.Thread.__init__(self) + Thread.__init__(self) self.setDaemon(True) self.cli = cli @@ -407,110 +329,11 @@ class RefreshThread(threading.Thread): print _("pyLoad was terminated") _exit(0) except Exception, e: - self.cli.println(2, red(str(e))) - self.cli.pos[1] = 0 - self.cli.pos[2] = 0 + println(2, red(str(e))) + self.cli.reset() print_exc() -class _Getch: - """ - Gets a single character from standard input. Does not echo to - the screen. - """ - - def __init__(self): - try: - self.impl = _GetchWindows() - except ImportError: - try: - self.impl = _GetchMacCarbon() - except(AttributeError, ImportError): - self.impl = _GetchUnix() - - def __call__(self): return self.impl() - - -class _GetchUnix: - def __init__(self): - import tty - import sys - - def __call__(self): - import sys - import tty - import termios - - fd = sys.stdin.fileno() - old_settings = termios.tcgetattr(fd) - try: - tty.setraw(sys.stdin.fileno()) - ch = sys.stdin.read(1) - finally: - termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) - return ch - - -class _GetchWindows: - def __init__(self): - import msvcrt - - def __call__(self): - import msvcrt - - return msvcrt.getch() - -class _GetchMacCarbon: - """ - A function which returns the current ASCII key that is down; - if no ASCII key is down, the null string is returned. The - page http://www.mactech.com/macintosh-c/chap02-1.html was - very helpful in figuring out how to do this. - """ - - def __init__(self): - import Carbon - Carbon.Evt #see if it has this (in Unix, it doesn't) - - def __call__(self): - import Carbon - - if Carbon.Evt.EventAvail(0x0008)[0] == 0: # 0x0008 is the keyDownMask - return '' - else: - # - # The event contains the following info: - # (what,msg,when,where,mod)=Carbon.Evt.GetNextEvent(0x0008)[1] - # - # The message (msg) contains the ASCII char which is - # extracted with the 0x000000FF charCodeMask; this - # number is converted to an ASCII character with chr() and - # returned - # - (what, msg, when, where, mod) = Carbon.Evt.GetNextEvent(0x0008)[1] - return chr(msg) - -def blue(string): - return "\033[1;34m" + unicode(string) + "\033[0m" - -def green(string): - return "\033[1;32m" + unicode(string) + "\033[0m" - -def yellow(string): - return "\033[1;33m" + unicode(string) + "\033[0m" - -def red(string): - return "\033[1;31m" + unicode(string) + "\033[0m" - -def cyan(string): - return "\033[1;36m" + unicode(string) + "\033[0m" - -def mag(string): - return "\033[1;35m" + unicode(string) + "\033[0m" - -def white(string): - return "\033[1;37m" + unicode(string) + "\033[0m" - def print_help(): print print "pyLoadCli Copyright (c) 2008-2011 the pyLoad Team" @@ -521,11 +344,11 @@ def print_help(): print "See pyLoadCli.py -c for a complete listing." print print "<Options>" - print " -i, --interactive", " Start in interactive mode" - print - print " -u, --username=", " " * 2, "Specify Username" + print " -i, --interactive", " Start in interactive mode" + print + print " -u, --username=", " " * 2, "Specify Username" print " --pw=<password>", " " * 2, "Password" - print " -a, --address=", " "*3, "Specify address (default=127.0.0.1)" + print " -a, --address=", " " * 3, "Specify address (default=127.0.0.1)" print " -p, --port", " " * 7, "Specify port (default=7227)" print print " -h, --help", " " * 7, "Display this help screen" @@ -537,32 +360,37 @@ def print_packages(data): for pack in data: print "Package %s (#%s):" % (pack.name, pack.pid) for download in pack.links: - print "\t" + print_file(download) + print "\t" + print_file(download) print + def print_file(download): return "#%(id)-6d %(name)-30s %(statusmsg)-10s %(plugin)-8s" % { - "id": download.fid, - "name": download.name, - "statusmsg": download.statusmsg, - "plugin": download.plugin - } + "id": download.fid, + "name": download.name, + "statusmsg": download.statusmsg, + "plugin": download.plugin + } + def print_status(download): return "#%(id)-6s %(name)-40s Status: %(statusmsg)-10s Size: %(size)s" % { - "id": download.fid, - "name": download.name, - "statusmsg": download.statusmsg, - "size": download.format_size - } + "id": download.fid, + "name": download.name, + "statusmsg": download.statusmsg, + "size": download.format_size + } + def print_commands(): commands = [("status", _("Prints server status")), ("queue", _("Prints downloads in queue")), ("collector", _("Prints downloads in collector")), ("add <name> <link1> <link2>...", _("Adds package to queue")), + ("add_coll <name> <link1> <link2>...", _("Adds package to collector")), ("del_file <fid> <fid2>...", _("Delete Files from Queue/Collector")), ("del_package <pid> <pid2>...", _("Delete Packages from Queue/Collector")), + ("move <pid> <pid2>...", _("Move Packages from Queue to Collector or vice versa")), ("pause", _("Pause the server")), ("unpause", _("continue downloads")), ("toggle", _("Toggle pause/unpause")), @@ -571,7 +399,7 @@ def print_commands(): print _("List of commands:") print for c in commands: - print "%-30s %s" % c + print "%-35s %s" % c if __name__ == "__main__": config = ConfigParser() @@ -622,7 +450,6 @@ if __name__ == "__main__": client = False if interactive: - try: client = ThriftClient(addr, port, username, password) except WrongLogin: @@ -648,18 +475,17 @@ if __name__ == "__main__": except WrongLogin: print _("Login data is wrong.") except NoConnection: - print _("Could not establish connection to %(addr)s:%(port)s." % {"addr": addr, "port" : port }) + print _("Could not establish connection to %(addr)s:%(port)s." % {"addr": addr, "port": port}) else: try: client = ThriftClient(addr, port, username, password) except WrongLogin: - print _("Login data is required.") + print _("Login data is wrong.") except NoConnection: - print _("Could not establish connection to %(addr)s:%(port)s." % {"addr": addr, "port" : port }) + print _("Could not establish connection to %(addr)s:%(port)s." % {"addr": addr, "port": port}) except NoSSL: - print _("You need py-openssl to connect to this pyLoad.") - + print _("You need py-openssl to connect to this pyLoad core.") if interactive and command: print _("Interactive mode ignored since you passed some commands.") |