summaryrefslogtreecommitdiffstats
path: root/module/remote/ThriftBackend.py
diff options
context:
space:
mode:
Diffstat (limited to 'module/remote/ThriftBackend.py')
-rw-r--r--module/remote/ThriftBackend.py607
1 files changed, 607 insertions, 0 deletions
diff --git a/module/remote/ThriftBackend.py b/module/remote/ThriftBackend.py
new file mode 100644
index 000000000..eee2d6d80
--- /dev/null
+++ b/module/remote/ThriftBackend.py
@@ -0,0 +1,607 @@
+# -*- coding: utf-8 -*-
+"""
+ 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/>.
+
+ @author: mkaay
+"""
+from module.remote.RemoteManager import BackendBase
+from module.PyFile import PyFile
+
+from module.remote.thriftgen.pyload import Pyload
+from module.remote.thriftgen.pyload.ttypes import *
+
+from thrift.transport import TSocket
+from thrift.transport import TTransport
+from thrift.protocol import TBinaryProtocol
+from thrift.server import TServer
+
+import threading
+import logging
+
+class Processor(Pyload.Processor):
+ def __init__(self, *args, **kwargs):
+ Pyload.Processor.__init__(self, *args, **kwargs)
+ self.authenticated = {}
+
+ def process(self, iprot, oprot):
+ trans = oprot.trans
+ if not self.authenticated.has_key(trans):
+ self.authenticated[trans] = False
+ oldclose = trans.close
+ def wrap():
+ del self.authenticated[trans]
+ oldclose()
+ trans.close = wrap
+ authenticated = self.authenticated[trans]
+ (name, type, seqid) = iprot.readMessageBegin()
+ if name not in self._processMap or (not authenticated and not name == "login"):
+ iprot.skip(Pyload.TType.STRUCT)
+ iprot.readMessageEnd()
+ x = Pyload.TApplicationException(Pyload.TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name))
+ oprot.writeMessageBegin(name, Pyload.TMessageType.EXCEPTION, seqid)
+ x.write(oprot)
+ oprot.writeMessageEnd()
+ oprot.trans.flush()
+ return
+ elif not authenticated and name == "login":
+ args = Pyload.login_args()
+ args.read(iprot)
+ iprot.readMessageEnd()
+ result = Pyload.login_result()
+ self.authenticated[trans] = self._handler.login(args.username, args.password)
+ result.success = self.authenticated[trans]
+ oprot.writeMessageBegin("login", Pyload.TMessageType.REPLY, seqid)
+ result.write(oprot)
+ oprot.writeMessageEnd()
+ oprot.trans.flush()
+ else:
+ self._processMap[name](self, seqid, iprot, oprot)
+ return True
+
+class PyloadHandler:
+ def __init__(self, backend):
+ self.backend = backend
+ self.core = backend.core
+ self.serverMethods = self.core.server_methods
+
+ #general
+ def getConfigValue(self, category, option, section):
+ """
+ Parameters:
+ - category
+ - option
+ - section
+ """
+ self.serverMethods.get_conf_val(category, option, section)
+
+ def setConfigValue(self, category, option, value, section):
+ """
+ Parameters:
+ - category
+ - option
+ - value
+ - section
+ """
+ self.serverMethods.set_conf_val(category, option, value, section)
+
+ def _convertConfigFormat(self, c):
+ sections = []
+ for sectionName, sub in c.iteritems():
+ section = ConfigSection()
+ section.name = sectionName
+ section.decription = sub["desc"]
+ items = []
+ for key, data in sub.iteritems():
+ if key == "desc":
+ continue
+ item = ConfigItem()
+ item.name = key
+ item.decription = data["desc"]
+ item.value = str(data["value"])
+ if data["type"] == "str":
+ item.type = ConfigItemType.String
+ elif data["type"] == "int":
+ item.type = ConfigItemType.Integer
+ elif data["type"] == "bool":
+ item.type = ConfigItemType.Bool
+ elif data["type"] == "password":
+ item.type = ConfigItemType.Password
+ elif data["type"] == "ip":
+ item.type = ConfigItemType.IP
+ elif data["type"] == "file":
+ item.type = ConfigItemType.File
+ elif data["type"] == "folder":
+ item.type = ConfigItemType.Folder
+ elif data["type"] == "time":
+ item.type = ConfigItemType.Time
+ else:
+ item.type = ConfigItemType.Choice
+ item.choice = set([x.strip() for x in data["type"].split(";")])
+ items.append(item)
+ section.items = items
+ sections.append(section)
+ return sections
+
+ def getConfig(self):
+ c = self.serverMethods.get_config()
+ return self._convertConfigFormat(c)
+
+ def getPluginConfig(self):
+ c = self.serverMethods.get_plugin_config()
+ return self._convertConfigFormat(c)
+
+ def pauseServer(self):
+ self.serverMethods.pause_server()
+
+ def unpauseServer(self):
+ self.serverMethods.unpause_server()
+
+ def togglePause(self):
+ return self.serverMethods.toggle_server()
+
+ def statusServer(self):
+ status = self.serverMethods.status_server()
+ serverStatus = ServerStatus()
+ serverStatus.pause = status["pause"]
+ serverStatus.active = status["activ"]
+ serverStatus.queue = status["queue"]
+ serverStatus.total = status["total"]
+ serverStatus.speed = status["speed"]
+ serverStatus.download = status["download"]
+ serverStatus.reconnect = status["reconnect"]
+ return serverStatus
+
+ def freeSpace(self):
+ return self.serverMethods.free_space()
+
+ def getServerVersion(self):
+ return self.serverMethods.get_server_version()
+
+ def kill(self):
+ self.serverMethods.kill()
+
+ def restart(self):
+ self.serverMethods.restart()
+
+ def getLog(self, offset):
+ """
+ Parameters:
+ - offset
+ """
+ return list(self.serverMethods.restart(offset))
+
+ def checkURL(self, urls):
+ """
+ Parameters:
+ - urls
+ """
+ checked = {}
+ for u, p in self.core.pluginManager.parseUrls(urls):
+ if p == "BasePlugin":
+ checked[u] = ""
+ else:
+ checked[u] = p
+ return checked
+
+ def isTimeDownload(self):
+ return self.serverMethods.is_time_download()
+
+ def isTimeReconnect(self):
+ return self.serverMethods.is_time_reconnect()
+
+ #downloads
+ def statusDownloads(self):
+ data = []
+ for pyfile in [x.active for x in self.core.threadManager.threads + self.core.threadManager.localThreads if x.active and x.active != "quit"]:
+ if not isinstance(pyfile, PyFile):
+ continue
+ status = DownloadStatus()
+ status.id = pyfile.id
+ status.name = pyfile.name
+ status.speed = pyfile.getSpeed()/1024
+ status.eta = pyfile.getETA()
+ status.format_eta = pyfile.formatETA()
+ status.kbleft = pyfile.getBytesLeft() #holded for backward comp.
+ status.bleft = pyfile.getBytesLeft()
+ status.size = pyfile.getSize()
+ status.format_size = pyfile.formatSize()
+ status.percent = pyfile.getPercent()
+ status.status = pyfile.status
+ status.statusmsg = pyfile.m.statusMsg[pyfile.status]
+ status.format_wait = pyfile.formatWait()
+ status.wait_until = pyfile.waitUntil
+ status.package = pyfile.package().name
+ data.append(status)
+ return data
+
+ def addPackage(self, name, links, dest):
+ """
+ Parameters:
+ - name
+ - links
+ - dest
+ """
+ return self.serverMethods.add_package(name, links, dest)
+
+ def getPackageData(self, pid):
+ """
+ Parameters:
+ - pid
+ """
+ pdata = PackageData()
+ rawData = self.serverMethods.get_package_data(pid)
+ pdata.pid = rawData["id"]
+ pdata.name = rawData["name"]
+ pdata.folder = rawData["folder"]
+ pdata.site = rawData["site"]
+ pdata.password = rawData["password"]
+ pdata.queue = rawData["queue"]
+ pdata.order = rawData["order"]
+ pdata.priority = rawData["priority"]
+ pdata.links = []
+ for pyfile in rawData["links"]:
+ pdata.links.append(pyfile["id"])
+ return pdata
+
+ def getFileData(self, fid):
+ """
+ Parameters:
+ - fid
+ """
+ fdata = FileData()
+ rawData = self.serverMethods.get_file_data(pid)
+ fdata.pid = rawData["id"]
+ fdata.url = rawData["url"]
+ fdata.name = rawData["name"]
+ fdata.plugin = rawData["plugin"]
+ fdata.size = rawData["size"]
+ fdata.format_size = rawData["format_size"]
+ fdata.status = rawData["status"]
+ fdata.statusmsg = rawData["statusmsg"]
+ fdata.package = rawData["package"]
+ fdata.error = rawData["error"]
+ fdata.order = rawData["order"]
+ fdata.progress = rawData["progress"]
+ return fdata
+
+ def deleteFiles(self, fids):
+ """
+ Parameters:
+ - fids
+ """
+ self.serverMethods.del_links(fids)
+
+ def deletePackages(self, pids):
+ """
+ Parameters:
+ - pids
+ """
+ self.serverMethods.del_packages(pids)
+
+ def getQueue(self):
+ packs = self.serverMethods.get_queue()
+ ret = []
+ for pid in packs:
+ pack = self.serverMethods.get_package_data(pid)
+ pdata = PackageData()
+ pdata.pid = pack["id"]
+ pdata.name = pack["name"]
+ pdata.folder = pack["folder"]
+ pdata.site = pack["site"]
+ pdata.password = pack["password"]
+ pdata.queue = pack["queue"]
+ pdata.order = pack["order"]
+ pdata.priority = pack["priority"]
+ pdata.fileids = [int(x) for x in pack["links"].keys()]
+ ret.append(pdata)
+ return ret
+
+ def getCollector(self):
+ packs = self.serverMethods.get_queue()
+ ret = []
+ for pid in packs:
+ pack = self.serverMethods.get_package_data(pid)
+ pdata = PackageData()
+ pdata.pid = pack["id"]
+ pdata.name = pack["name"]
+ pdata.folder = pack["folder"]
+ pdata.site = pack["site"]
+ pdata.password = pack["password"]
+ pdata.queue = pack["queue"]
+ pdata.order = pack["order"]
+ pdata.priority = pack["priority"]
+ pdata.fileids = [int(x) for x in pack["links"].keys()]
+ ret.append(pdata)
+ return ret
+
+ def addFiles(self, pid, links):
+ """
+ Parameters:
+ - pid
+ - links
+ """
+ self.serverMethods.add_files(pid, links)
+
+ def pushToQueue(self, pid):
+ """
+ Parameters:
+ - pid
+ """
+ self.serverMethods.push_package_to_queue(pid)
+
+ def pullFromQueue(self, pid):
+ """
+ Parameters:
+ - pid
+ """
+ self.serverMethods.pull_out_package(pid)
+
+ def restartPackage(self, pid):
+ """
+ Parameters:
+ - pid
+ """
+ self.serverMethods.restart_package(pid)
+
+ def restartFile(self, fid):
+ """
+ Parameters:
+ - fid
+ """
+ self.serverMethods.restart_file(fid)
+
+ def recheckPackage(self, pid):
+ """
+ Parameters:
+ - pid
+ """
+ self.serverMethods.recheck_package(pid)
+
+ def stopAllDownloads(self):
+ self.serverMethods.stop_downloads()
+
+ def stopDownloads(self, fids):
+ """
+ Parameters:
+ - fids
+ """
+ self.serverMethods.abort_files(fids)
+
+ def setPackageName(self, pid, name):
+ """
+ Parameters:
+ - pid
+ - name
+ """
+ self.serverMethods.set_package_name(pid, name)
+
+ def movePackage(self, destination, pid):
+ """
+ Parameters:
+ - destination
+ - pid
+ """
+ self.serverMethods.move_package(destination, pid)
+
+ def uploadContainer(self, filename, data):
+ """
+ Parameters:
+ - filename
+ - data
+ """
+ self.serverMethods.upload_container(filename, data)
+
+ def setPriority(self, pid, priority):
+ """
+ Parameters:
+ - pid
+ - priority
+ """
+ self.serverMethods.set_priority(pid, priority)
+
+ def orderPackage(self, pid, position):
+ """
+ Parameters:
+ - pid
+ - position
+ """
+ self.serverMethods.order_package(pid, position)
+
+ def orderFile(self, fid, position):
+ """
+ Parameters:
+ - fid
+ - position
+ """
+ self.serverMethods.order_file(fid, position)
+
+ def setPackageData(self, pid, data):
+ """
+ Parameters:
+ - pid
+ - data
+ """
+ packdata = {}
+ packdata["id"] = data.pid
+ packdata["name"] = data.name
+ packdata["folder"] = data.folder
+ packdata["site"] = data.site
+ packdata["password"] = data.password
+ packdata["queue"] = data.queue
+ packdata["order"] = data.order
+ packdata["priority"] = data.priority
+ self.serverMethods.set_package_data(pid, packdata)
+
+ def deleteFinished(self):
+ self.serverMethods.delete_finished()
+
+ def restartFailed(self):
+ self.serverMethods.restart_failed()
+
+ def getPackageOrder(self, destination):
+ """
+ Parameters:
+ - destination
+ """
+ order = {}
+ if destination == Destination.Queue:
+ packs = self.serverMethods.get_queue()
+ else:
+ packs = self.serverMethods.get_collector()
+ for pid in packs:
+ pack = self.serverMethods.get_package_data(pid)
+ order[pack["order"]] = pack["id"]
+ return order
+
+ def getFileOrder(self, pid):
+ """
+ Parameters:
+ - pid
+ """
+ rawData = self.serverMethods.get_package_data(pid)
+ order = {}
+ for pyfile in rawData["links"]:
+ order[pyfile["order"]] = pyfile["id"]
+ return order
+
+ #captcha
+ def isCaptchaWaiting(self):
+ return self.serverMethods.is_captcha_waiting()
+
+ def getCaptchaTask(self, exclusive):
+ """
+ Parameters:
+ - exclusive
+ """
+ t = CaptchaTask()
+ t.tid, t.data, t.type = self.serverMethods.get_captcha_task(exclusive)
+ return t
+
+ def getCaptchaTaskStatus(self, tid):
+ """
+ Parameters:
+ - tid
+ """
+ status = self.serverMethods.get_task_status(tid)
+ if status == "init":
+ return CaptchaStatus.Init
+ elif status == "waiting":
+ return CaptchaStatus.Waiting
+ elif status == "user":
+ return CaptchaStatus.User
+ elif status == "shared-user":
+ return CaptchaStatus.SharedUser
+ elif status == "done":
+ return CaptchaStatus.Done
+
+ def setCaptchaResult(self, tid, result):
+ """
+ Parameters:
+ - tid
+ - result
+ """
+ self.serverMethods.set_captcha_result(tid, result)
+
+ #events
+ def getEvents(self):
+ events = serverMethods.get_events()
+ newEvents = []
+ for e in events:
+ e = Event()
+ if e[0] in ("update", "remove", "insert"):
+ event.id = e[3]
+ event.type = ElementType.Package if e[2] == "pack" else ElementType.File
+ event.destination = e[1]
+ if e[0] == "update":
+ event.event = EventType.Update
+ elif e[0] == "remove":
+ event.event = EventType.Remove
+ elif e[0] == "insert":
+ event.event = EventType.Insert
+ elif e[0] == "reload":
+ event.event = EventType.ReloadAll
+ event.destination = e[1]
+ elif e[0] == "account":
+ event.event = EventType.ReloadAccounts
+ elif e[0] == "config":
+ event.event = EventType.ReloadConfig
+ elif e[0] == "order":
+ event.event = EventType.ReloadOrder
+ if e[1]:
+ event.id = e[1]
+ event.type = ElementType.Package if e[2] == "pack" else ElementType.File
+ event.destination = e[3]
+ newEvents.append(event)
+ return newEvents
+
+ #accounts
+ def getAccounts(self):
+ accs = self.serverMethods.get_accounts()
+ accounts = []
+ for group in accs.values():
+ for acc in group:
+ account = AccountInfo()
+ account.validuntil = acc["validuntil"]
+ account.login = acc["login"]
+ account.options = acc["options"]
+ account.valid = acc["valid"]
+ account.trafficleft = acc["trafficleft"]
+ account.maxtraffic = acc["maxtraffic"]
+ account.premium = acc["premium"]
+ account.type = acc["type"]
+ accounts.append(account)
+ return accounts
+
+ def updateAccounts(self, data):
+ """
+ Parameters:
+ - data
+ """
+ self.serverMethods.update_account(data.type, data.login, data.password, data.options)
+
+ def removeAccount(self, plugin, account):
+ """
+ Parameters:
+ - plugin
+ - account
+ """
+ self.serverMethods.remove_account(plugin, account)
+
+ #auth
+ def login(self, username, password):
+ """
+ Parameters:
+ - username
+ - password
+ """
+ return True if self.serverMethods.checkAuth(username, password) else False
+
+ def getUserData(self):
+ return self.serverMethods.checkAuth(username, password)
+
+class ThriftBackend(BackendBase):
+ def setup(self):
+ handler = PyloadHandler(self)
+ processor = Processor(handler)
+ transport = TSocket.TServerSocket(9090)
+ tfactory = TTransport.TBufferedTransportFactory()
+ pfactory = TBinaryProtocol.TBinaryProtocolFactory()
+
+ #self.server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
+ self.server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)
+
+ #server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
+
+ def serve(self):
+ self.server.serve()