summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2011-05-10 21:23:46 +0200
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2011-05-10 21:23:46 +0200
commit60ae0ee3dce4715621b9964c91ad96e08e123204 (patch)
tree251aeb85742a32a8f3711879e4071a66e59bdc26
parentfixes netload free (diff)
downloadpyload-60ae0ee3dce4715621b9964c91ad96e08e123204.tar.xz
rewritten cli, closed #275, #304
-rw-r--r--module/HookManager.py6
-rw-r--r--module/cli/AddPackage.py66
-rw-r--r--module/cli/Handler.py48
-rw-r--r--module/cli/ManageFiles.py204
-rw-r--r--module/cli/__init__.py2
-rw-r--r--module/cli/printer.py26
-rw-r--r--module/lib/Getch.py76
-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.py2
-rw-r--r--module/remote/thriftbackend/Handler.py1
-rw-r--r--module/remote/thriftbackend/pyload.thrift2
-rw-r--r--[-rwxr-xr-x]pyLoadCli.py556
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.")