diff options
| -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.") | 
